@dxos/react-ui-editor 0.4.7-main.b23cefb → 0.4.7-main.b51ad3a

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 (82) hide show
  1. package/dist/lib/browser/index.mjs +982 -711
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +9 -0
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  7. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +0 -9
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  9. package/dist/types/src/components/TextEditor/index.d.ts +0 -2
  10. package/dist/types/src/components/TextEditor/index.d.ts.map +1 -1
  11. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +1 -0
  12. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -1
  13. package/dist/types/src/{components/TextEditor → extensions/automerge}/automerge.stories.d.ts +5 -2
  14. package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -0
  15. package/dist/types/src/extensions/command/command.d.ts +10 -0
  16. package/dist/types/src/extensions/command/command.d.ts.map +1 -0
  17. package/dist/types/src/extensions/command/hint.d.ts +7 -0
  18. package/dist/types/src/extensions/command/hint.d.ts.map +1 -0
  19. package/dist/types/src/extensions/command/index.d.ts +2 -0
  20. package/dist/types/src/extensions/command/index.d.ts.map +1 -0
  21. package/dist/types/src/extensions/command/state.d.ts +18 -0
  22. package/dist/types/src/extensions/command/state.d.ts.map +1 -0
  23. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  24. package/dist/types/src/extensions/cursor-line-margin.d.ts.map +1 -1
  25. package/dist/types/src/extensions/dnd.d.ts +3 -0
  26. package/dist/types/src/extensions/dnd.d.ts.map +1 -0
  27. package/dist/types/src/extensions/index.d.ts +2 -1
  28. package/dist/types/src/extensions/index.d.ts.map +1 -1
  29. package/dist/types/src/extensions/listener.d.ts +1 -1
  30. package/dist/types/src/extensions/listener.d.ts.map +1 -1
  31. package/dist/types/src/extensions/markdown/bundle.d.ts +2 -2
  32. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  33. package/dist/types/src/extensions/markdown/decorate.d.ts +3 -0
  34. package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
  35. package/dist/types/src/extensions/mention.d.ts.map +1 -1
  36. package/dist/types/src/extensions/util/dom.d.ts +15 -0
  37. package/dist/types/src/extensions/util/dom.d.ts.map +1 -0
  38. package/dist/types/src/hooks/defs.d.ts +5 -11
  39. package/dist/types/src/hooks/defs.d.ts.map +1 -1
  40. package/dist/types/src/hooks/useEditorView.d.ts.map +1 -1
  41. package/dist/types/src/hooks/useTextEditor.d.ts +20 -5
  42. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
  43. package/dist/types/src/{components/TextEditor/hooks.stories.d.ts → hooks/useTextEditor.stories.d.ts} +2 -3
  44. package/dist/types/src/hooks/useTextEditor.stories.d.ts.map +1 -0
  45. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  46. package/dist/types/src/index.d.ts +1 -0
  47. package/dist/types/src/index.d.ts.map +1 -1
  48. package/dist/types/src/themes/default.d.ts.map +1 -1
  49. package/package.json +30 -30
  50. package/src/components/TextEditor/MarkdownEditor.stories.tsx +95 -8
  51. package/src/components/TextEditor/TextEditor.stories.tsx +0 -15
  52. package/src/components/TextEditor/TextEditor.tsx +11 -6
  53. package/src/components/TextEditor/index.ts +0 -3
  54. package/src/components/Toolbar/Toolbar.stories.tsx +2 -1
  55. package/src/{components/TextEditor → extensions/automerge}/automerge.stories.tsx +32 -37
  56. package/src/extensions/command/command.ts +35 -0
  57. package/src/extensions/command/hint.ts +76 -0
  58. package/src/extensions/command/index.ts +5 -0
  59. package/src/extensions/command/state.ts +106 -0
  60. package/src/extensions/comments.ts +2 -1
  61. package/src/extensions/cursor-line-margin.ts +5 -2
  62. package/src/extensions/dnd.ts +17 -0
  63. package/src/extensions/index.ts +2 -1
  64. package/src/extensions/listener.ts +3 -3
  65. package/src/extensions/markdown/bundle.ts +4 -14
  66. package/src/extensions/markdown/decorate.ts +21 -14
  67. package/src/extensions/mention.ts +3 -1
  68. package/src/extensions/util/dom.ts +36 -0
  69. package/src/hooks/defs.ts +6 -20
  70. package/src/hooks/useActionHandler.ts +11 -11
  71. package/src/hooks/useEditorView.ts +0 -1
  72. package/src/{components/TextEditor/hooks.stories.tsx → hooks/useTextEditor.stories.tsx} +8 -8
  73. package/src/hooks/useTextEditor.ts +69 -14
  74. package/src/hooks/useTextModel.ts +11 -16
  75. package/src/index.ts +2 -0
  76. package/src/themes/default.ts +1 -0
  77. package/src/util.ts +1 -1
  78. package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +0 -1
  79. package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +0 -1
  80. package/dist/types/src/extensions/basic.d.ts +0 -9
  81. package/dist/types/src/extensions/basic.d.ts.map +0 -1
  82. package/src/extensions/basic.ts +0 -41
@@ -23,20 +23,19 @@ var translations_default = [
23
23
  ];
24
24
 
25
25
  // packages/ui/react-ui-editor/src/index.ts
26
- import { keymap as keymap8 } from "@codemirror/view";
26
+ import { keymap as keymap9 } from "@codemirror/view";
27
+ import { tags as tags2 } from "@lezer/highlight";
27
28
  import { TextKind } from "@dxos/protocols/proto/dxos/echo/model/text";
28
29
  import { Doc, YText, YXmlFragment } from "@dxos/text-model";
29
30
 
30
- // packages/ui/react-ui-editor/src/components/TextEditor/index.ts
31
- import { tags as tags2 } from "@lezer/highlight";
32
-
33
31
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
34
- import { EditorState as EditorState2 } from "@codemirror/state";
35
- import { EditorView as EditorView14, scrollPastEnd } from "@codemirror/view";
32
+ import { EditorState as EditorState3 } from "@codemirror/state";
33
+ import { EditorView as EditorView17, scrollPastEnd as scrollPastEnd2 } from "@codemirror/view";
36
34
  import { useFocusableGroup } from "@fluentui/react-tabster";
37
- import defaultsDeep2 from "lodash.defaultsdeep";
38
- import React, { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef, useState as useState2, useMemo as useMemo2 } from "react";
39
- import { log as log3 } from "@dxos/log";
35
+ import defaultsDeep3 from "lodash.defaultsdeep";
36
+ import React, { forwardRef, useCallback, useEffect as useEffect3, useImperativeHandle, useRef as useRef3, useState as useState5, useMemo as useMemo3 } from "react";
37
+ import { DocAccessor } from "@dxos/echo-schema";
38
+ import { log as log9 } from "@dxos/log";
40
39
  import { useThemeContext } from "@dxos/react-ui";
41
40
  import { focusRing } from "@dxos/react-ui-theme";
42
41
  import { isNotFalsy as isNotFalsy4 } from "@dxos/util";
@@ -733,28 +732,8 @@ var styles2 = EditorView3.baseTheme({
733
732
  }
734
733
  });
735
734
 
736
- // packages/ui/react-ui-editor/src/extensions/basic.ts
737
- import { closeBrackets } from "@codemirror/autocomplete";
738
- import { history } from "@codemirror/commands";
739
- import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from "@codemirror/language";
740
- import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
741
- import { drawSelection, EditorView as EditorView4, highlightActiveLine, placeholder } from "@codemirror/view";
742
- import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
743
- var createBasicBundle = ({ themeMode, placeholder: _placeholder, lineWrapping = true, bracketMatching: _bracketMatching = true } = {}) => [
744
- lineWrapping && EditorView4.lineWrapping,
745
- // https://codemirror.net/docs/ref/#codemirror.minimalSetup
746
- _bracketMatching && bracketMatching(),
747
- closeBrackets(),
748
- drawSelection(),
749
- highlightActiveLine(),
750
- history(),
751
- _placeholder && placeholder(_placeholder),
752
- // https://github.com/codemirror/theme-one-dark
753
- themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
754
- ].filter(isNotFalsy2);
755
-
756
735
  // packages/ui/react-ui-editor/src/extensions/blast.ts
757
- import { EditorView as EditorView5, keymap as keymap2 } from "@codemirror/view";
736
+ import { EditorView as EditorView4, keymap as keymap2 } from "@codemirror/view";
758
737
  import defaultsDeep from "lodash.defaultsdeep";
759
738
  import { invariant } from "@dxos/invariant";
760
739
  var __dxlog_file2 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/blast.ts";
@@ -802,7 +781,7 @@ var blast = (options = defaultOptions) => {
802
781
  };
803
782
  return [
804
783
  // Cursor moved.
805
- EditorView5.updateListener.of((update2) => {
784
+ EditorView4.updateListener.of((update2) => {
806
785
  if (blaster?.node !== update2.view.scrollDOM) {
807
786
  if (blaster) {
808
787
  blaster.destroy();
@@ -1063,13 +1042,231 @@ var random = (min, max) => {
1063
1042
  return min + ~~(Math.random() * (max - min + 1));
1064
1043
  };
1065
1044
 
1045
+ // packages/ui/react-ui-editor/src/extensions/command/command.ts
1046
+ import { EditorView as EditorView6, keymap as keymap3 } from "@codemirror/view";
1047
+
1048
+ // packages/ui/react-ui-editor/src/extensions/command/hint.ts
1049
+ import { RangeSetBuilder } from "@codemirror/state";
1050
+ import { Decoration as Decoration3, EditorView as EditorView5, ViewPlugin as ViewPlugin3, WidgetType as WidgetType2 } from "@codemirror/view";
1051
+
1052
+ // packages/ui/react-ui-editor/src/extensions/command/state.ts
1053
+ import { Facet as Facet3, StateEffect as StateEffect2, StateField as StateField3 } from "@codemirror/state";
1054
+ import { showTooltip } from "@codemirror/view";
1055
+ var commandConfig = Facet3.define({
1056
+ combine: (providers) => providers[0]
1057
+ });
1058
+ var commandState = StateField3.define({
1059
+ create: () => ({}),
1060
+ update: (state, tr) => {
1061
+ for (const effect of tr.effects) {
1062
+ if (effect.is(closeEffect)) {
1063
+ return {};
1064
+ }
1065
+ if (effect.is(openEffect)) {
1066
+ const options = tr.state.facet(commandConfig);
1067
+ const { pos, fullWidth } = effect.value;
1068
+ const tooltip = {
1069
+ pos,
1070
+ above: false,
1071
+ arrow: false,
1072
+ strictSide: true,
1073
+ create: (view) => {
1074
+ const dom = document.createElement("div");
1075
+ const tooltipView = {
1076
+ dom,
1077
+ mount: (view2) => {
1078
+ if (fullWidth) {
1079
+ const parent = dom.parentElement;
1080
+ const { paddingLeft, paddingRight } = window.getComputedStyle(parent);
1081
+ const widthWithoutPadding = parent.clientWidth - parseFloat(paddingLeft) - parseFloat(paddingRight);
1082
+ dom.style.width = `${widthWithoutPadding}px`;
1083
+ }
1084
+ options.onRender(dom, (action) => {
1085
+ view2.dispatch({
1086
+ effects: closeEffect.of(null)
1087
+ });
1088
+ if (action?.insert?.length) {
1089
+ view2.dispatch({
1090
+ changes: {
1091
+ from: pos,
1092
+ insert: action.insert
1093
+ },
1094
+ selection: {
1095
+ anchor: pos + action.insert.length
1096
+ }
1097
+ });
1098
+ }
1099
+ setTimeout(() => view2.focus());
1100
+ });
1101
+ }
1102
+ };
1103
+ return tooltipView;
1104
+ }
1105
+ };
1106
+ return {
1107
+ tooltip
1108
+ };
1109
+ }
1110
+ }
1111
+ return state;
1112
+ },
1113
+ provide: (f) => [
1114
+ showTooltip.from(f, (value) => value.tooltip ?? null)
1115
+ ]
1116
+ });
1117
+ var openEffect = StateEffect2.define();
1118
+ var closeEffect = StateEffect2.define();
1119
+ var openCommand = (view) => {
1120
+ if (view.state.field(commandState, false)) {
1121
+ const selection = view.state.selection.main;
1122
+ const line = view.state.doc.lineAt(selection.from);
1123
+ if (line.from === selection.from && line.from === line.to) {
1124
+ view.dispatch({
1125
+ effects: openEffect.of({
1126
+ pos: selection.anchor,
1127
+ fullWidth: true
1128
+ })
1129
+ });
1130
+ return true;
1131
+ }
1132
+ }
1133
+ return false;
1134
+ };
1135
+ var closeCommand = (view) => {
1136
+ if (view.state.field(commandState, false)) {
1137
+ view.dispatch({
1138
+ effects: closeEffect.of(null)
1139
+ });
1140
+ return true;
1141
+ }
1142
+ return false;
1143
+ };
1144
+ var commandKeyBindings = [
1145
+ {
1146
+ key: "/",
1147
+ run: openCommand
1148
+ },
1149
+ {
1150
+ key: "Escape",
1151
+ run: closeCommand
1152
+ }
1153
+ ];
1154
+
1155
+ // packages/ui/react-ui-editor/src/extensions/util/dom.ts
1156
+ var flattenRect = (rect, left) => {
1157
+ const x = left ? rect.left : rect.right;
1158
+ return {
1159
+ left: x,
1160
+ right: x,
1161
+ top: rect.top,
1162
+ bottom: rect.bottom
1163
+ };
1164
+ };
1165
+ var scratchRange;
1166
+ var textRange = (node, from, to = from) => {
1167
+ const range = scratchRange || (scratchRange = document.createRange());
1168
+ range.setEnd(node, to);
1169
+ range.setStart(node, from);
1170
+ return range;
1171
+ };
1172
+ var clientRectsFor = (dom) => {
1173
+ if (dom.nodeType === 3) {
1174
+ return textRange(dom, 0, dom.nodeValue.length).getClientRects();
1175
+ } else if (dom.nodeType === 1) {
1176
+ return dom.getClientRects();
1177
+ } else {
1178
+ return [];
1179
+ }
1180
+ };
1181
+
1182
+ // packages/ui/react-ui-editor/src/extensions/command/hint.ts
1183
+ var CommandHint = class extends WidgetType2 {
1184
+ constructor(content) {
1185
+ super();
1186
+ this.content = content;
1187
+ }
1188
+ toDOM() {
1189
+ const wrap = document.createElement("span");
1190
+ wrap.className = "cm-placeholder";
1191
+ wrap.style.pointerEvents = "none";
1192
+ wrap.appendChild(typeof this.content === "string" ? document.createTextNode(this.content) : this.content);
1193
+ if (typeof this.content === "string") {
1194
+ wrap.setAttribute("aria-label", "placeholder " + this.content);
1195
+ } else {
1196
+ wrap.setAttribute("aria-hidden", "true");
1197
+ }
1198
+ return wrap;
1199
+ }
1200
+ coordsAt(dom) {
1201
+ const rects = dom.firstChild ? clientRectsFor(dom.firstChild) : [];
1202
+ if (!rects.length) {
1203
+ return null;
1204
+ }
1205
+ const style = window.getComputedStyle(dom.parentNode);
1206
+ const rect = flattenRect(rects[0], style.direction !== "rtl");
1207
+ const lineHeight = parseInt(style.lineHeight);
1208
+ if (rect.bottom - rect.top > lineHeight * 1.5) {
1209
+ return {
1210
+ left: rect.left,
1211
+ right: rect.right,
1212
+ top: rect.top,
1213
+ bottom: rect.top + lineHeight
1214
+ };
1215
+ }
1216
+ return rect;
1217
+ }
1218
+ ignoreEvent() {
1219
+ return false;
1220
+ }
1221
+ };
1222
+ var hintViewPlugin = ({ onHint }) => ViewPlugin3.fromClass(class {
1223
+ constructor() {
1224
+ this.deco = Decoration3.none;
1225
+ }
1226
+ update(update2) {
1227
+ const builder = new RangeSetBuilder();
1228
+ const cState = update2.view.state.field(commandState, false);
1229
+ if (!cState?.tooltip) {
1230
+ const selection = update2.view.state.selection.main;
1231
+ const line = update2.view.state.doc.lineAt(selection.from);
1232
+ if (selection.from === selection.to && line.from === line.to) {
1233
+ const hint = onHint();
1234
+ if (hint) {
1235
+ builder.add(selection.from, selection.to, Decoration3.widget({
1236
+ widget: new CommandHint(hint)
1237
+ }));
1238
+ }
1239
+ }
1240
+ }
1241
+ this.deco = builder.finish();
1242
+ }
1243
+ }, {
1244
+ provide: (plugin) => [
1245
+ EditorView5.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration3.none)
1246
+ ]
1247
+ });
1248
+
1249
+ // packages/ui/react-ui-editor/src/extensions/command/command.ts
1250
+ var command = (options) => {
1251
+ return [
1252
+ commandConfig.of(options),
1253
+ commandState,
1254
+ keymap3.of(commandKeyBindings),
1255
+ hintViewPlugin(options),
1256
+ EditorView6.focusChangeEffect.of((_, focusing) => {
1257
+ return focusing ? closeEffect.of(null) : null;
1258
+ })
1259
+ ];
1260
+ };
1261
+
1066
1262
  // packages/ui/react-ui-editor/src/extensions/comments.ts
1067
1263
  import { invertedEffects } from "@codemirror/commands";
1068
- import { Facet as Facet3, StateEffect as StateEffect2, StateField as StateField3 } from "@codemirror/state";
1069
- import { hoverTooltip, keymap as keymap3, Decoration as Decoration3, EditorView as EditorView6 } from "@codemirror/view";
1264
+ import { Facet as Facet4, StateEffect as StateEffect3, StateField as StateField4 } from "@codemirror/state";
1265
+ import { hoverTooltip, keymap as keymap4, Decoration as Decoration4, EditorView as EditorView7 } from "@codemirror/view";
1070
1266
  import sortBy from "lodash.sortby";
1071
1267
  import { useEffect } from "react";
1072
1268
  import { debounce } from "@dxos/async";
1269
+ import { log as log3 } from "@dxos/log";
1073
1270
  import { nonNullable } from "@dxos/util";
1074
1271
 
1075
1272
  // packages/ui/react-ui-editor/src/styles/markdown.ts
@@ -1137,18 +1334,26 @@ var logChanges = (trs) => {
1137
1334
  return changes2;
1138
1335
  }).filter(Boolean);
1139
1336
  if (changes.length) {
1140
- console.log("changes", changes);
1337
+ log2.info("changes", {
1338
+ changes
1339
+ }, {
1340
+ F: __dxlog_file3,
1341
+ L: 39,
1342
+ S: void 0,
1343
+ C: (f, a) => f(...a)
1344
+ });
1141
1345
  }
1142
1346
  };
1143
1347
 
1144
1348
  // packages/ui/react-ui-editor/src/extensions/comments.ts
1145
- var documentId = Facet3.define({
1349
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/comments.ts";
1350
+ var documentId = Facet4.define({
1146
1351
  combine: (values) => values[0]
1147
1352
  });
1148
- var setComments = StateEffect2.define();
1149
- var setSelection = StateEffect2.define();
1150
- var setCommentState = StateEffect2.define();
1151
- var commentsState = StateField3.define({
1353
+ var setComments = StateEffect3.define();
1354
+ var setSelection = StateEffect3.define();
1355
+ var setCommentState = StateEffect3.define();
1356
+ var commentsState = StateField4.define({
1152
1357
  create: (state) => ({
1153
1358
  id: state.facet(documentId),
1154
1359
  comments: [],
@@ -1186,7 +1391,7 @@ var commentsState = StateField3.define({
1186
1391
  return value;
1187
1392
  }
1188
1393
  });
1189
- var styles3 = EditorView6.baseTheme({
1394
+ var styles3 = EditorView7.baseTheme({
1190
1395
  "&light .cm-comment, &light .cm-comment-current": {
1191
1396
  mixBlendMode: "darken"
1192
1397
  },
@@ -1208,26 +1413,31 @@ var styles3 = EditorView6.baseTheme({
1208
1413
  backgroundColor: getToken("extend.colors.yellow.950")
1209
1414
  }
1210
1415
  });
1211
- var commentMark = Decoration3.mark({
1416
+ var commentMark = Decoration4.mark({
1212
1417
  class: "cm-comment",
1213
1418
  attributes: {
1214
1419
  "data-testid": "cm-comment"
1215
1420
  }
1216
1421
  });
1217
- var commentCurrentMark = Decoration3.mark({
1422
+ var commentCurrentMark = Decoration4.mark({
1218
1423
  class: "cm-comment-current",
1219
1424
  attributes: {
1220
1425
  "data-testid": "cm-comment"
1221
1426
  }
1222
1427
  });
1223
- var commentsDecorations = EditorView6.decorations.compute([
1428
+ var commentsDecorations = EditorView7.decorations.compute([
1224
1429
  commentsState
1225
1430
  ], (state) => {
1226
1431
  const { selection: { current }, comments: comments2 } = state.field(commentsState);
1227
1432
  const decorations = sortBy(comments2 ?? [], (range) => range.range.from)?.flatMap((comment) => {
1228
1433
  const range = comment.range;
1229
1434
  if (!range || range.from === range.to) {
1230
- console.warn("Invalid range:", range);
1435
+ log3.warn("Invalid range:", range, {
1436
+ F: __dxlog_file4,
1437
+ L: 132,
1438
+ S: void 0,
1439
+ C: (f, a) => f(...a)
1440
+ });
1231
1441
  return void 0;
1232
1442
  }
1233
1443
  if (comment.comment.id === current) {
@@ -1236,7 +1446,7 @@ var commentsDecorations = EditorView6.decorations.compute([
1236
1446
  return commentMark.range(range.from, range.to);
1237
1447
  }
1238
1448
  }).filter(nonNullable);
1239
- return Decoration3.set(decorations);
1449
+ return Decoration4.set(decorations);
1240
1450
  });
1241
1451
  var trackPastedComments = (onUpdate) => {
1242
1452
  let tracked = null;
@@ -1258,7 +1468,7 @@ var trackPastedComments = (onUpdate) => {
1258
1468
  }
1259
1469
  };
1260
1470
  return [
1261
- EditorView6.domEventHandlers({
1471
+ EditorView7.domEventHandlers({
1262
1472
  cut: handleTrack,
1263
1473
  copy: handleTrack
1264
1474
  }),
@@ -1280,7 +1490,7 @@ var trackPastedComments = (onUpdate) => {
1280
1490
  return effects;
1281
1491
  }),
1282
1492
  // Handle paste or the undo of comment deletion.
1283
- EditorView6.updateListener.of((update2) => {
1493
+ EditorView7.updateListener.of((update2) => {
1284
1494
  const restore = [];
1285
1495
  for (let i = 0; i < update2.transactions.length; i++) {
1286
1496
  const tr = update2.transactions[i];
@@ -1336,7 +1546,7 @@ var mapTrackedComment = (comment, changes) => ({
1336
1546
  from: changes.mapPos(comment.from, 1),
1337
1547
  to: changes.mapPos(comment.to, 1)
1338
1548
  });
1339
- var restoreCommentEffect = StateEffect2.define({
1549
+ var restoreCommentEffect = StateEffect3.define({
1340
1550
  map: mapTrackedComment
1341
1551
  });
1342
1552
  var createComment = (view) => {
@@ -1377,7 +1587,7 @@ var createComment = (view) => {
1377
1587
  }
1378
1588
  return false;
1379
1589
  };
1380
- var optionsFacet = Facet3.define({
1590
+ var optionsFacet = Facet4.define({
1381
1591
  combine: (providers) => providers[0]
1382
1592
  });
1383
1593
  var comments = (options = {}) => {
@@ -1392,7 +1602,7 @@ var comments = (options = {}) => {
1392
1602
  //
1393
1603
  // Keymap.
1394
1604
  //
1395
- options.onCreate ? keymap3.of([
1605
+ options.onCreate ? keymap4.of([
1396
1606
  {
1397
1607
  key: shortcut,
1398
1608
  run: callbackWrapper(createComment)
@@ -1431,7 +1641,7 @@ var comments = (options = {}) => {
1431
1641
  //
1432
1642
  // Track deleted ranges and update ranges for decorations.
1433
1643
  //
1434
- EditorView6.updateListener.of(({ view, state, changes }) => {
1644
+ EditorView7.updateListener.of(({ view, state, changes }) => {
1435
1645
  let mod = false;
1436
1646
  const { comments: comments2, ...value } = state.field(commentsState);
1437
1647
  changes.iterChanges((from, to, from2, to2) => {
@@ -1463,7 +1673,7 @@ var comments = (options = {}) => {
1463
1673
  //
1464
1674
  // Track selection/proximity.
1465
1675
  //
1466
- EditorView6.updateListener.of(({ view, state }) => {
1676
+ EditorView7.updateListener.of(({ view, state }) => {
1467
1677
  let min = Infinity;
1468
1678
  const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
1469
1679
  const { head } = state.selection.main;
@@ -1512,7 +1722,7 @@ var focusComment = (view, id, center = true) => {
1512
1722
  },
1513
1723
  effects: [
1514
1724
  //
1515
- EditorView6.scrollIntoView(range.from, center ? {
1725
+ EditorView7.scrollIntoView(range.from, center ? {
1516
1726
  y: "center"
1517
1727
  } : void 0),
1518
1728
  setSelection.of({
@@ -1540,14 +1750,16 @@ var useComments = (view, id, comments2 = []) => {
1540
1750
  };
1541
1751
 
1542
1752
  // packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts
1543
- import { Facet as Facet4, Transaction } from "@codemirror/state";
1544
- import { EditorView as EditorView7 } from "@codemirror/view";
1545
- var cursorLineMarginFacet = Facet4.define({
1753
+ import { Facet as Facet5, Transaction } from "@codemirror/state";
1754
+ import { EditorView as EditorView8 } from "@codemirror/view";
1755
+ import { log as log4 } from "@dxos/log";
1756
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts";
1757
+ var cursorLineMarginFacet = Facet5.define({
1546
1758
  combine: (input) => input[0] ?? 3
1547
1759
  });
1548
1760
  var annotation = "cursorLineMargin";
1549
1761
  var lineAtPos = (s, pos) => s.doc.lineAt(pos).number;
1550
- var cursorLineMargin = EditorView7.updateListener.of(({ transactions, state, selectionSet, startState, view }) => {
1762
+ var cursorLineMargin = EditorView8.updateListener.of(({ transactions, state, selectionSet, startState, view }) => {
1551
1763
  if (transactions.length < 1 || transactions.some((tr) => tr.isUserEvent(annotation))) {
1552
1764
  return;
1553
1765
  }
@@ -1565,7 +1777,12 @@ var cursorLineMargin = EditorView7.updateListener.of(({ transactions, state, sel
1565
1777
  const needsScrollTop = false;
1566
1778
  const needsScrollBot = mainLine >= visBotLine - cursorLineMargin2;
1567
1779
  if (needsScrollTop && needsScrollBot) {
1568
- console.warn("is cursorScrollMargin too large for the editor size?");
1780
+ log4.warn("is cursorScrollMargin too large for the editor size?", void 0, {
1781
+ F: __dxlog_file5,
1782
+ L: 66,
1783
+ S: void 0,
1784
+ C: (f, a) => f(...a)
1785
+ });
1569
1786
  return;
1570
1787
  }
1571
1788
  if (!needsScrollTop && !needsScrollBot) {
@@ -1583,38 +1800,57 @@ var cursorLineMargin = EditorView7.updateListener.of(({ transactions, state, sel
1583
1800
  }
1584
1801
  view.dispatch({
1585
1802
  annotations: Transaction.userEvent.of(annotation),
1586
- effects: EditorView7.scrollIntoView(s.selection.main.head, {
1803
+ effects: EditorView8.scrollIntoView(s.selection.main.head, {
1587
1804
  y: needsScrollTop ? "start" : "end",
1588
1805
  yMargin: view.defaultLineHeight * cursorLineMargin2
1589
1806
  })
1590
1807
  });
1591
1808
  });
1592
1809
 
1810
+ // packages/ui/react-ui-editor/src/extensions/dnd.ts
1811
+ import { EditorView as EditorView9 } from "@codemirror/view";
1812
+ import { log as log5 } from "@dxos/log";
1813
+ var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/dnd.ts";
1814
+ var dnd = () => {
1815
+ return EditorView9.domEventHandlers({
1816
+ drop: (event, view) => {
1817
+ log5.info("domEventHandlersDrop", {
1818
+ event
1819
+ }, {
1820
+ F: __dxlog_file6,
1821
+ L: 14,
1822
+ S: void 0,
1823
+ C: (f, a) => f(...a)
1824
+ });
1825
+ }
1826
+ });
1827
+ };
1828
+
1593
1829
  // packages/ui/react-ui-editor/src/extensions/listener.ts
1594
- import { EditorView as EditorView8 } from "@codemirror/view";
1830
+ import { EditorView as EditorView10 } from "@codemirror/view";
1595
1831
  var listener = ({ onFocus, onChange }) => {
1596
1832
  const extensions = [];
1597
- onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
1598
- onFocus(focused);
1833
+ onFocus && extensions.push(EditorView10.focusChangeEffect.of((_, focusing) => {
1834
+ onFocus(focusing);
1599
1835
  return null;
1600
1836
  }));
1601
- onChange && extensions.push(EditorView8.updateListener.of((update2) => {
1837
+ onChange && extensions.push(EditorView10.updateListener.of((update2) => {
1602
1838
  onChange(update2.state.doc.toString());
1603
1839
  }));
1604
1840
  return extensions;
1605
1841
  };
1606
1842
 
1607
1843
  // packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
1608
- import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
1609
- import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
1844
+ import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
1845
+ import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
1610
1846
  import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
1611
- import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
1847
+ import { bracketMatching, defaultHighlightStyle, indentOnInput, syntaxHighlighting } from "@codemirror/language";
1612
1848
  import { languages } from "@codemirror/language-data";
1613
1849
  import { searchKeymap } from "@codemirror/search";
1614
1850
  import { EditorState } from "@codemirror/state";
1615
- import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
1616
- import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
1617
- import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
1851
+ import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
1852
+ import { EditorView as EditorView11, drawSelection, dropCursor, keymap as keymap5, placeholder } from "@codemirror/view";
1853
+ import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
1618
1854
 
1619
1855
  // packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
1620
1856
  import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
@@ -1807,19 +2043,17 @@ var markdownHighlightStyle = (readonly) => {
1807
2043
  // packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
1808
2044
  var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
1809
2045
  return [
1810
- lineWrapping && EditorView9.lineWrapping,
2046
+ // TODO(burdon): Reconcile with createBasicExtensions.
2047
+ lineWrapping && EditorView11.lineWrapping,
1811
2048
  EditorState.allowMultipleSelections.of(true),
1812
2049
  EditorState.tabSize.of(2),
1813
- // https://github.com/codemirror/basic-setup
1814
- bracketMatching2(),
1815
- closeBrackets2(),
1816
- crosshairCursor(),
2050
+ bracketMatching(),
2051
+ closeBrackets(),
1817
2052
  dropCursor(),
1818
- drawSelection2(),
1819
- highlightActiveLine2(),
1820
- history2(),
2053
+ drawSelection(),
2054
+ history(),
1821
2055
  indentOnInput(),
1822
- _placeholder && placeholder2(_placeholder),
2056
+ _placeholder && placeholder(_placeholder),
1823
2057
  // Main extension.
1824
2058
  // https://github.com/codemirror/lang-markdown
1825
2059
  // https://codemirror.net/5/mode/markdown/index.html (demo).
@@ -1839,10 +2073,10 @@ var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrap
1839
2073
  ]
1840
2074
  }),
1841
2075
  // https://github.com/codemirror/theme-one-dark
1842
- themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
2076
+ themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
1843
2077
  // Custom styles.
1844
- syntaxHighlighting2(markdownHighlightStyle()),
1845
- keymap4.of([
2078
+ syntaxHighlighting(markdownHighlightStyle()),
2079
+ keymap5.of([
1846
2080
  // https://codemirror.net/docs/ref/#commands.indentWithTab
1847
2081
  indentWithTab,
1848
2082
  // https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
@@ -1854,22 +2088,22 @@ var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrap
1854
2088
  // https://codemirror.net/docs/ref/#commands.standardKeymap
1855
2089
  ...standardKeymap
1856
2090
  ])
1857
- ].filter(isNotFalsy3);
2091
+ ].filter(isNotFalsy2);
1858
2092
  };
1859
2093
 
1860
2094
  // packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
1861
2095
  import { syntaxTree } from "@codemirror/language";
1862
- import { RangeSetBuilder, StateEffect as StateEffect3 } from "@codemirror/state";
1863
- import { EditorView as EditorView10, Decoration as Decoration4, WidgetType as WidgetType2, ViewPlugin as ViewPlugin3 } from "@codemirror/view";
2096
+ import { RangeSetBuilder as RangeSetBuilder2, StateEffect as StateEffect4 } from "@codemirror/state";
2097
+ import { EditorView as EditorView12, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
1864
2098
  import { mx as mx2 } from "@dxos/react-ui-theme";
1865
- var HorizontalRuleWidget = class extends WidgetType2 {
2099
+ var HorizontalRuleWidget = class extends WidgetType3 {
1866
2100
  toDOM() {
1867
2101
  const el = document.createElement("span");
1868
2102
  el.className = "cm-hr";
1869
2103
  return el;
1870
2104
  }
1871
2105
  };
1872
- var LinkButton = class extends WidgetType2 {
2106
+ var LinkButton = class extends WidgetType3 {
1873
2107
  constructor(url, render) {
1874
2108
  super();
1875
2109
  this.url = url;
@@ -1884,7 +2118,7 @@ var LinkButton = class extends WidgetType2 {
1884
2118
  return el;
1885
2119
  }
1886
2120
  };
1887
- var CheckboxWidget = class extends WidgetType2 {
2121
+ var CheckboxWidget = class extends WidgetType3 {
1888
2122
  constructor(_checked) {
1889
2123
  super();
1890
2124
  this._checked = _checked;
@@ -1921,28 +2155,28 @@ var CheckboxWidget = class extends WidgetType2 {
1921
2155
  return false;
1922
2156
  }
1923
2157
  };
1924
- var hide = Decoration4.replace({});
1925
- var fencedCodeLine = Decoration4.line({
2158
+ var hide = Decoration5.replace({});
2159
+ var fencedCodeLine = Decoration5.line({
1926
2160
  class: mx2("cm-code cm-codeblock-line")
1927
2161
  });
1928
- var fencedCodeLineFirst = Decoration4.line({
2162
+ var fencedCodeLineFirst = Decoration5.line({
1929
2163
  class: mx2("cm-code cm-codeblock-line", "cm-codeblock-first")
1930
2164
  });
1931
- var fencedCodeLineLast = Decoration4.line({
2165
+ var fencedCodeLineLast = Decoration5.line({
1932
2166
  class: mx2("cm-code cm-codeblock-line", "cm-codeblock-last")
1933
2167
  });
1934
- var horizontalRule = Decoration4.replace({
2168
+ var horizontalRule = Decoration5.replace({
1935
2169
  widget: new HorizontalRuleWidget()
1936
2170
  });
1937
- var checkedTask = Decoration4.replace({
2171
+ var checkedTask = Decoration5.replace({
1938
2172
  widget: new CheckboxWidget(true)
1939
2173
  });
1940
- var uncheckedTask = Decoration4.replace({
2174
+ var uncheckedTask = Decoration5.replace({
1941
2175
  widget: new CheckboxWidget(false)
1942
2176
  });
1943
2177
  var editingRange = (state, range, focus) => {
1944
2178
  const { readOnly, selection: { main: { head } } } = state;
1945
- return focus && !readOnly && head >= range.from && head < range.to;
2179
+ return focus && !readOnly && head >= range.from && head <= range.to;
1946
2180
  };
1947
2181
  var MarksByParent = /* @__PURE__ */ new Set([
1948
2182
  "CodeMark",
@@ -1952,8 +2186,8 @@ var MarksByParent = /* @__PURE__ */ new Set([
1952
2186
  "SuperscriptMark"
1953
2187
  ]);
1954
2188
  var buildDecorations = (view, options, focus) => {
1955
- const deco = new RangeSetBuilder();
1956
- const atomicDeco = new RangeSetBuilder();
2189
+ const deco = new RangeSetBuilder2();
2190
+ const atomicDeco = new RangeSetBuilder2();
1957
2191
  const { state } = view;
1958
2192
  for (const { from, to } of view.visibleRanges) {
1959
2193
  syntaxTree(state).iterate({
@@ -1970,7 +2204,7 @@ var buildDecorations = (view, options, focus) => {
1970
2204
  break;
1971
2205
  }
1972
2206
  const first = block.from <= node.from;
1973
- const last = block.to >= node.to;
2207
+ const last = block.to >= node.to && /^(\s>)*```$/.test(state.doc.sliceString(block.from, block.to));
1974
2208
  deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
1975
2209
  if (!editing && (first || last)) {
1976
2210
  atomicDeco.add(block.from, block.to, hide);
@@ -1986,7 +2220,7 @@ var buildDecorations = (view, options, focus) => {
1986
2220
  if (!editing) {
1987
2221
  atomicDeco.add(node.from, marks[0].to, hide);
1988
2222
  }
1989
- deco.add(marks[0].to, marks[1].from, Decoration4.mark({
2223
+ deco.add(marks[0].to, marks[1].from, Decoration5.mark({
1990
2224
  tagName: "a",
1991
2225
  attributes: {
1992
2226
  class: "cm-link",
@@ -1996,7 +2230,7 @@ var buildDecorations = (view, options, focus) => {
1996
2230
  }
1997
2231
  }));
1998
2232
  if (!editing) {
1999
- atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration4.replace({
2233
+ atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
2000
2234
  widget: new LinkButton(url, options.renderLinkButton)
2001
2235
  }) : hide);
2002
2236
  }
@@ -2014,7 +2248,7 @@ var buildDecorations = (view, options, focus) => {
2014
2248
  } else if (node.name === "TaskMarker") {
2015
2249
  if (!editingRange(state, node, focus)) {
2016
2250
  const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
2017
- atomicDeco.add(node.from - 2, node.from - 1, Decoration4.mark({
2251
+ atomicDeco.add(node.from - 2, node.from - 1, Decoration5.mark({
2018
2252
  class: "cm-task"
2019
2253
  }));
2020
2254
  atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
@@ -2032,50 +2266,51 @@ var buildDecorations = (view, options, focus) => {
2032
2266
  atomicDeco: atomicDeco.finish()
2033
2267
  };
2034
2268
  };
2035
- var forceUpdate = StateEffect3.define();
2269
+ var forceUpdate = StateEffect4.define();
2036
2270
  var decorateMarkdown = (options = {}) => {
2037
2271
  return [
2038
- ViewPlugin3.fromClass(class {
2272
+ ViewPlugin4.fromClass(class {
2039
2273
  constructor(view) {
2040
- this.pendingUpdate = -1;
2041
2274
  ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(view, options, view.hasFocus));
2042
2275
  }
2043
2276
  update(update2) {
2044
- if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate)))) {
2277
+ if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
2045
2278
  ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(update2.view, options, update2.view.hasFocus));
2046
2279
  this.clearUpdate();
2047
2280
  } else if (update2.selectionSet) {
2048
2281
  this.scheduleUpdate(update2.view);
2049
2282
  }
2050
2283
  }
2051
- clearUpdate() {
2052
- if (this.pendingUpdate > -1) {
2053
- window.clearTimeout(this.pendingUpdate);
2054
- this.pendingUpdate = -1;
2055
- }
2056
- }
2284
+ // TODO(burdon): BUG: If the cursor is at the end of a link at the end of a line,
2285
+ // the cursor will float in space or be in the wrong position after the decoration is applied.
2057
2286
  scheduleUpdate(view) {
2058
2287
  this.clearUpdate();
2059
- this.pendingUpdate = window.setTimeout(() => {
2288
+ this.pendingUpdate = setTimeout(() => {
2060
2289
  view.dispatch({
2061
2290
  effects: forceUpdate.of(null)
2062
2291
  });
2063
- }, options.selectionChangeDelay ?? 400);
2292
+ }, options.selectionChangeDelay);
2293
+ }
2294
+ clearUpdate() {
2295
+ if (this.pendingUpdate) {
2296
+ clearTimeout(this.pendingUpdate);
2297
+ this.pendingUpdate = void 0;
2298
+ }
2064
2299
  }
2065
2300
  destroy() {
2066
2301
  this.clearUpdate();
2067
2302
  }
2068
2303
  }, {
2069
2304
  provide: (plugin) => [
2070
- EditorView10.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration4.none),
2071
- EditorView10.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration4.none),
2072
- EditorView10.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration4.none)
2305
+ EditorView12.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
2306
+ EditorView12.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
2307
+ EditorView12.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
2073
2308
  ]
2074
2309
  }),
2075
2310
  formattingStyles
2076
2311
  ];
2077
2312
  };
2078
- var formattingStyles = EditorView10.baseTheme({
2313
+ var formattingStyles = EditorView12.baseTheme({
2079
2314
  "& .cm-code": {
2080
2315
  fontFamily: getToken("fontFamily.mono", []).join(",")
2081
2316
  },
@@ -2128,7 +2363,7 @@ var formattingStyles = EditorView10.baseTheme({
2128
2363
  import { snippet } from "@codemirror/autocomplete";
2129
2364
  import { syntaxTree as syntaxTree2 } from "@codemirror/language";
2130
2365
  import { EditorSelection } from "@codemirror/state";
2131
- import { EditorView as EditorView11, keymap as keymap5 } from "@codemirror/view";
2366
+ import { EditorView as EditorView13, keymap as keymap6 } from "@codemirror/view";
2132
2367
  import { useState, useMemo } from "react";
2133
2368
  var compareFormatting = (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;
2134
2369
  var Inline;
@@ -3000,7 +3235,7 @@ var toggleCodeblock = (target) => {
3000
3235
  };
3001
3236
  var formatting = (options = {}) => {
3002
3237
  return [
3003
- keymap5.of([
3238
+ keymap6.of([
3004
3239
  {
3005
3240
  key: "meta-b",
3006
3241
  run: toggleStrong
@@ -3198,7 +3433,7 @@ var getFormatting = (state) => {
3198
3433
  };
3199
3434
  var useFormattingState = () => {
3200
3435
  const [state, setState] = useState(null);
3201
- const observer = useMemo(() => EditorView11.updateListener.of((update2) => {
3436
+ const observer = useMemo(() => EditorView13.updateListener.of((update2) => {
3202
3437
  if (update2.docChanged || update2.selectionSet) {
3203
3438
  const newState = getFormatting(update2.state);
3204
3439
  if (!state || !compareFormatting(state, newState)) {
@@ -3214,12 +3449,12 @@ var useFormattingState = () => {
3214
3449
 
3215
3450
  // packages/ui/react-ui-editor/src/extensions/markdown/image.ts
3216
3451
  import { syntaxTree as syntaxTree3 } from "@codemirror/language";
3217
- import { StateField as StateField4 } from "@codemirror/state";
3218
- import { Decoration as Decoration5, EditorView as EditorView12, WidgetType as WidgetType3 } from "@codemirror/view";
3452
+ import { StateField as StateField5 } from "@codemirror/state";
3453
+ import { Decoration as Decoration6, EditorView as EditorView14, WidgetType as WidgetType4 } from "@codemirror/view";
3219
3454
  var image = (options = {}) => {
3220
- return StateField4.define({
3455
+ return StateField5.define({
3221
3456
  create: (state) => {
3222
- return Decoration5.set(buildDecorations2(0, state.doc.length, state));
3457
+ return Decoration6.set(buildDecorations2(0, state.doc.length, state));
3223
3458
  },
3224
3459
  update: (value, tr) => {
3225
3460
  if (!tr.docChanged && !tr.selection) {
@@ -3242,7 +3477,7 @@ var image = (options = {}) => {
3242
3477
  add: buildDecorations2(from, to, tr.state)
3243
3478
  });
3244
3479
  },
3245
- provide: (field) => EditorView12.decorations.from(field)
3480
+ provide: (field) => EditorView14.decorations.from(field)
3246
3481
  });
3247
3482
  };
3248
3483
  var preloaded = /* @__PURE__ */ new Set();
@@ -3264,7 +3499,7 @@ var buildDecorations2 = (from, to, state) => {
3264
3499
  const hide2 = state.readOnly || cursor < node.from || cursor > node.to;
3265
3500
  const url = state.sliceDoc(urlNode.from, urlNode.to);
3266
3501
  preloadImage(url);
3267
- decorations.push(Decoration5.replace({
3502
+ decorations.push(Decoration6.replace({
3268
3503
  block: true,
3269
3504
  widget: new ImageWidget(url)
3270
3505
  }).range(hide2 ? node.from : node.to, node.to));
@@ -3276,7 +3511,7 @@ var buildDecorations2 = (from, to, state) => {
3276
3511
  });
3277
3512
  return decorations;
3278
3513
  };
3279
- var ImageWidget = class extends WidgetType3 {
3514
+ var ImageWidget = class extends WidgetType4 {
3280
3515
  constructor(_url) {
3281
3516
  super();
3282
3517
  this._url = _url;
@@ -3329,17 +3564,17 @@ var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
3329
3564
 
3330
3565
  // packages/ui/react-ui-editor/src/extensions/markdown/table.ts
3331
3566
  import { syntaxTree as syntaxTree5 } from "@codemirror/language";
3332
- import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField5 } from "@codemirror/state";
3333
- import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
3567
+ import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "@codemirror/state";
3568
+ import { Decoration as Decoration7, EditorView as EditorView15, WidgetType as WidgetType5 } from "@codemirror/view";
3334
3569
  var table = (options = {}) => {
3335
- return StateField5.define({
3570
+ return StateField6.define({
3336
3571
  create: (state) => update(state, options),
3337
3572
  update: (_, tr) => update(tr.state, options),
3338
- provide: (field) => EditorView13.decorations.from(field)
3573
+ provide: (field) => EditorView15.decorations.from(field)
3339
3574
  });
3340
3575
  };
3341
3576
  var update = (state, options) => {
3342
- const builder = new RangeSetBuilder2();
3577
+ const builder = new RangeSetBuilder3();
3343
3578
  const cursor = state.selection.main.head;
3344
3579
  const tables = [];
3345
3580
  const getTable = () => tables[tables.length - 1];
@@ -3379,16 +3614,16 @@ var update = (state, options) => {
3379
3614
  });
3380
3615
  tables.forEach((table2) => {
3381
3616
  const hide2 = state.readOnly || cursor < table2.from || cursor > table2.to;
3382
- hide2 && builder.add(table2.from, table2.to, Decoration6.replace({
3617
+ hide2 && builder.add(table2.from, table2.to, Decoration7.replace({
3383
3618
  widget: new TableWidget(table2)
3384
3619
  }));
3385
- builder.add(table2.from, table2.to, Decoration6.mark({
3620
+ builder.add(table2.from, table2.to, Decoration7.mark({
3386
3621
  class: "cm-table"
3387
3622
  }));
3388
3623
  });
3389
3624
  return builder.finish();
3390
3625
  };
3391
- var TableWidget = class extends WidgetType4 {
3626
+ var TableWidget = class extends WidgetType5 {
3392
3627
  constructor(_table) {
3393
3628
  super();
3394
3629
  this._table = _table;
@@ -3427,6 +3662,8 @@ var TableWidget = class extends WidgetType4 {
3427
3662
 
3428
3663
  // packages/ui/react-ui-editor/src/extensions/mention.ts
3429
3664
  import { autocompletion as autocompletion2 } from "@codemirror/autocomplete";
3665
+ import { log as log6 } from "@dxos/log";
3666
+ var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/extensions/mention.ts";
3430
3667
  var mention = ({ onSearch }) => {
3431
3668
  return autocompletion2({
3432
3669
  // TODO(burdon): Not working.
@@ -3438,7 +3675,14 @@ var mention = ({ onSearch }) => {
3438
3675
  icons: false,
3439
3676
  override: [
3440
3677
  (context) => {
3441
- console.log(context);
3678
+ log6.info("completion context", {
3679
+ context
3680
+ }, {
3681
+ F: __dxlog_file7,
3682
+ L: 26,
3683
+ S: void 0,
3684
+ C: (f, a) => f(...a)
3685
+ });
3442
3686
  const match = context.matchBefore(/@(\w+)?/);
3443
3687
  if (!match || match.from === match.to && !context.explicit) {
3444
3688
  return null;
@@ -3455,10 +3699,10 @@ var mention = ({ onSearch }) => {
3455
3699
  };
3456
3700
 
3457
3701
  // packages/ui/react-ui-editor/src/extensions/modes.ts
3458
- import { Facet as Facet5 } from "@codemirror/state";
3459
- import { keymap as keymap6 } from "@codemirror/view";
3702
+ import { Facet as Facet6 } from "@codemirror/state";
3703
+ import { keymap as keymap7 } from "@codemirror/view";
3460
3704
  import { vim } from "@replit/codemirror-vim";
3461
- var editorMode = Facet5.define({
3705
+ var editorMode = Facet6.define({
3462
3706
  combine: (modes) => modes[0] ?? {}
3463
3707
  });
3464
3708
  var EditorModes = {
@@ -3469,7 +3713,7 @@ var EditorModes = {
3469
3713
  type: "vim",
3470
3714
  noTabster: true
3471
3715
  }),
3472
- keymap6.of([
3716
+ keymap7.of([
3473
3717
  {
3474
3718
  key: "Alt-Escape",
3475
3719
  run: (view) => {
@@ -3489,7 +3733,7 @@ var outliner = (options = {}) => {
3489
3733
  };
3490
3734
 
3491
3735
  // packages/ui/react-ui-editor/src/extensions/typewriter.ts
3492
- import { keymap as keymap7 } from "@codemirror/view";
3736
+ import { keymap as keymap8 } from "@codemirror/view";
3493
3737
  var defaultItems = [
3494
3738
  "hello world!",
3495
3739
  "this is a test.",
@@ -3499,7 +3743,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
3499
3743
  let t;
3500
3744
  let idx = 0;
3501
3745
  return [
3502
- keymap7.of([
3746
+ keymap8.of([
3503
3747
  {
3504
3748
  // Reset.
3505
3749
  key: "alt-meta-'",
@@ -3545,171 +3789,355 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
3545
3789
  ];
3546
3790
  };
3547
3791
 
3548
- // packages/ui/react-ui-editor/src/themes/default.ts
3549
- import get4 from "lodash.get";
3550
- var defaultTheme = {
3551
- //
3552
- // Main layout:
3553
- // https://codemirror.net/examples/styling
3554
- //
3555
- // <div class="cm-editor [cm-focused] [generated classes]">
3556
- // <div class="cm-scroller">
3557
- // <div class="cm-gutters">
3558
- // <div class="cm-gutter [...]">
3559
- // <div class="cm-gutterElement">...</div>
3560
- // </div>
3561
- // </div>
3562
- // <div class="cm-content" role="textbox" contenteditable="true">
3563
- // <div class="cm-line"></div>
3564
- // </div>
3565
- // <div class="cm-selectionLayer">
3566
- // <div class="cm-selectionBackground"></div>
3567
- // </div>
3568
- // <div class="cm-cursorLayer">
3569
- // <div class="cm-cursor"></div>
3570
- // </div>
3571
- // </div>
3572
- // </div>
3573
- //
3574
- "&": {},
3575
- "&.cm-focused": {
3576
- outline: "none"
3577
- },
3578
- // NOTE: See https://codemirror.net/docs/guide (DOM Structure).
3579
- ".cm-scroller": {
3580
- // TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
3581
- // Inside of that is the scroller element. If the editor has its own scrollbar, this one should be styled with overflow: auto. But it doesn't have to—the editor also supports growing to accomodate its content, or growing up to a certain max-height and then scrolling.
3582
- overflowY: "auto",
3583
- fontFamily: get4(tokens, "fontFamily.mono", []).join(","),
3584
- lineHeight: 1.5
3585
- },
3586
- ".cm-content": {
3587
- // TODO(burdon): Is it possible to remove the padding value from CM's default theme?
3588
- // padding: 'unset',
3589
- // NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
3590
- fontSize: "16px"
3591
- },
3592
- "&light .cm-content": {
3593
- color: get4(tokens, "extend.semanticColors.base.fg.light", "black"),
3594
- caretColor: "black"
3595
- },
3596
- "&dark .cm-content": {
3597
- color: get4(tokens, "extend.semanticColors.base.fg.dark", "white"),
3598
- caretColor: "white"
3599
- },
3600
- //
3601
- // Cursor
3602
- //
3603
- "&light .cm-cursor, &light .cm-dropCursor": {
3604
- borderLeft: "2px solid black"
3605
- },
3606
- "&dark .cm-cursor, &dark .cm-dropCursor": {
3607
- borderLeft: "2px solid white"
3608
- },
3609
- "&light .cm-placeholder": {
3610
- color: get4(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
3611
- },
3612
- "&dark .cm-placeholder": {
3613
- color: get4(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
3614
- },
3615
- //
3616
- // line
3617
- //
3618
- ".cm-line": {
3619
- paddingInline: 0
3620
- },
3621
- ".cm-activeLine": {
3622
- background: "transparent"
3623
- },
3624
- //
3625
- // gutter
3626
- //
3627
- ".cm-gutterElement": {
3628
- width: "48px"
3629
- },
3630
- //
3631
- // Selection
3632
- //
3633
- "&light .cm-selectionBackground": {
3634
- background: get4(tokens, "extend.colors.primary.100")
3635
- },
3636
- "&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
3637
- background: get4(tokens, "extend.colors.primary.200")
3638
- },
3639
- "&dark .cm-selectionBackground": {
3640
- background: get4(tokens, "extend.colors.primary.700")
3641
- },
3642
- "&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
3643
- background: get4(tokens, "extend.colors.primary.600")
3644
- },
3645
- //
3646
- // Search
3647
- //
3648
- "&light .cm-searchMatch": {
3649
- backgroundColor: get4(tokens, "extend.colors.yellow.100")
3650
- },
3651
- "&dark .cm-searchMatch": {
3652
- backgroundColor: get4(tokens, "extend.colors.yellow.700")
3653
- },
3654
- //
3655
- // link
3656
- //
3657
- ".cm-link": {
3658
- color: get4(tokens, "extend.colors.primary.500"),
3659
- textDecorationLine: "underline",
3660
- textDecorationThickness: "1px",
3661
- textUnderlineOffset: "2px",
3662
- borderRadius: ".125rem",
3663
- fontFamily: get4(tokens, "fontFamily.body", []).join(",")
3664
- },
3665
- //
3666
- // tooltip
3667
- //
3668
- ".cm-tooltip": {
3669
- border: "none"
3670
- },
3671
- ".cm-tooltip-below": {},
3792
+ // packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
3793
+ import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
3794
+ import { Context as Context2 } from "@dxos/context";
3795
+ import { invariant as invariant2 } from "@dxos/invariant";
3796
+ import { log as log7 } from "@dxos/log";
3797
+ var __dxlog_file8 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
3798
+ var DEBOUNCE_INTERVAL = 100;
3799
+ var SpaceAwarenessProvider = class {
3800
+ constructor(params) {
3801
+ this._remoteStates = /* @__PURE__ */ new Map();
3802
+ this.remoteStateChange = new Event2();
3803
+ this._space = params.space;
3804
+ this._channel = params.channel;
3805
+ this._peerId = params.peerId;
3806
+ this._info = params.info;
3807
+ }
3808
+ open() {
3809
+ this._ctx = new Context2();
3810
+ this._postTask = new DeferredTask(this._ctx, async () => {
3811
+ if (this._localState) {
3812
+ await this._space.postMessage(this._channel, {
3813
+ kind: "post",
3814
+ state: this._localState
3815
+ });
3816
+ await sleep(DEBOUNCE_INTERVAL);
3817
+ }
3818
+ });
3819
+ this._ctx.onDispose(this._space.listen(this._channel, (message) => {
3820
+ switch (message.payload.kind) {
3821
+ case "query": {
3822
+ this._handleQueryMessage();
3823
+ break;
3824
+ }
3825
+ case "post": {
3826
+ this._handlePostMessage(message.payload);
3827
+ break;
3828
+ }
3829
+ }
3830
+ }));
3831
+ void this._space.postMessage(this._channel, {
3832
+ kind: "query"
3833
+ }).catch((err) => {
3834
+ log7.debug("failed to query awareness", {
3835
+ err
3836
+ }, {
3837
+ F: __dxlog_file8,
3838
+ L: 89,
3839
+ S: this,
3840
+ C: (f, a) => f(...a)
3841
+ });
3842
+ });
3843
+ }
3844
+ close() {
3845
+ void this._ctx?.dispose();
3846
+ this._ctx = void 0;
3847
+ this._postTask = void 0;
3848
+ }
3849
+ getRemoteStates() {
3850
+ return Array.from(this._remoteStates.values());
3851
+ }
3852
+ update(position) {
3853
+ invariant2(this._postTask, void 0, {
3854
+ F: __dxlog_file8,
3855
+ L: 104,
3856
+ S: this,
3857
+ A: [
3858
+ "this._postTask",
3859
+ ""
3860
+ ]
3861
+ });
3862
+ this._localState = {
3863
+ peerId: this._peerId,
3864
+ position,
3865
+ info: this._info
3866
+ };
3867
+ this._postTask.schedule();
3868
+ }
3869
+ _handleQueryMessage() {
3870
+ invariant2(this._postTask, void 0, {
3871
+ F: __dxlog_file8,
3872
+ L: 115,
3873
+ S: this,
3874
+ A: [
3875
+ "this._postTask",
3876
+ ""
3877
+ ]
3878
+ });
3879
+ this._postTask.schedule();
3880
+ }
3881
+ _handlePostMessage(message) {
3882
+ invariant2(message.kind === "post", void 0, {
3883
+ F: __dxlog_file8,
3884
+ L: 120,
3885
+ S: this,
3886
+ A: [
3887
+ "message.kind === 'post'",
3888
+ ""
3889
+ ]
3890
+ });
3891
+ this._remoteStates.set(message.state.peerId, message.state);
3892
+ this.remoteStateChange.emit();
3893
+ }
3894
+ };
3895
+
3896
+ // packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
3897
+ var useActionHandler = (view) => {
3898
+ return (action) => {
3899
+ if (!view) {
3900
+ return;
3901
+ }
3902
+ let inlineType, listType;
3903
+ switch (action.type) {
3904
+ case "heading":
3905
+ setHeading(parseInt(action.data))(view);
3906
+ break;
3907
+ case "strong":
3908
+ case "emphasis":
3909
+ case "strikethrough":
3910
+ case "code":
3911
+ inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
3912
+ (typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
3913
+ break;
3914
+ case "list-ordered":
3915
+ case "list-bullet":
3916
+ case "list-task":
3917
+ listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
3918
+ (action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
3919
+ break;
3920
+ case "blockquote":
3921
+ (action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
3922
+ break;
3923
+ case "codeblock":
3924
+ (action.data === false ? removeCodeblock : addCodeblock)(view);
3925
+ break;
3926
+ case "table":
3927
+ insertTable(view);
3928
+ break;
3929
+ case "link":
3930
+ (action.data === false ? removeLink : addLink)(view);
3931
+ break;
3932
+ case "comment":
3933
+ createComment(view);
3934
+ break;
3935
+ }
3936
+ setTimeout(() => {
3937
+ if (!view.hasFocus) {
3938
+ view.focus();
3939
+ }
3940
+ });
3941
+ };
3942
+ };
3943
+
3944
+ // packages/ui/react-ui-editor/src/hooks/useEditorView.ts
3945
+ import { useRef, useState as useState2 } from "react";
3946
+ var useEditorView = (id) => {
3947
+ const editorRef = useRef(null);
3948
+ const [prev, setPrev] = useState2([
3949
+ null,
3950
+ ""
3951
+ ]);
3952
+ if (prev[0] !== editorRef.current) {
3953
+ setPrev([
3954
+ editorRef.current,
3955
+ id
3956
+ ]);
3957
+ }
3958
+ return [
3959
+ editorRef,
3960
+ prev[1] !== id
3961
+ ];
3962
+ };
3963
+
3964
+ // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
3965
+ import { closeBrackets as closeBrackets2 } from "@codemirror/autocomplete";
3966
+ import { history as history2 } from "@codemirror/commands";
3967
+ import { bracketMatching as bracketMatching2 } from "@codemirror/language";
3968
+ import { EditorSelection as EditorSelection2, EditorState as EditorState2 } from "@codemirror/state";
3969
+ import { crosshairCursor, drawSelection as drawSelection2, dropCursor as dropCursor2, EditorView as EditorView16, highlightActiveLine, lineNumbers, placeholder as placeholder2, scrollPastEnd } from "@codemirror/view";
3970
+ import defaultsDeep2 from "lodash.defaultsdeep";
3971
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
3972
+ import { log as log8 } from "@dxos/log";
3973
+ import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
3974
+
3975
+ // packages/ui/react-ui-editor/src/themes/default.ts
3976
+ import get4 from "lodash.get";
3977
+ var defaultTheme = {
3672
3978
  //
3673
- // autocomplete
3979
+ // Main layout:
3980
+ // https://codemirror.net/examples/styling
3674
3981
  //
3675
- ".cm-tooltip-autocomplete": {
3676
- marginTop: "4px",
3677
- marginLeft: "-3px"
3982
+ // <div class="cm-editor [cm-focused] [generated classes]">
3983
+ // <div class="cm-scroller">
3984
+ // <div class="cm-gutters">
3985
+ // <div class="cm-gutter [...]">
3986
+ // <div class="cm-gutterElement">...</div>
3987
+ // </div>
3988
+ // </div>
3989
+ // <div class="cm-content" role="textbox" contenteditable="true">
3990
+ // <div class="cm-line"></div>
3991
+ // </div>
3992
+ // <div class="cm-selectionLayer">
3993
+ // <div class="cm-selectionBackground"></div>
3994
+ // </div>
3995
+ // <div class="cm-cursorLayer">
3996
+ // <div class="cm-cursor"></div>
3997
+ // </div>
3998
+ // </div>
3999
+ // </div>
4000
+ //
4001
+ "&": {},
4002
+ "&.cm-focused": {
4003
+ outline: "none"
3678
4004
  },
3679
- ".cm-tooltip-autocomplete ul li": {},
3680
- ".cm-tooltip-autocomplete ul li[aria-selected]": {},
3681
- ".cm-completionIcon": {
3682
- display: "none"
4005
+ // NOTE: See https://codemirror.net/docs/guide (DOM Structure).
4006
+ ".cm-scroller": {
4007
+ // TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
4008
+ // Inside of that is the scroller element. If the editor has its own scrollbar, this one should be styled with overflow: auto. But it doesn't have to—the editor also supports growing to accomodate its content, or growing up to a certain max-height and then scrolling.
4009
+ overflowY: "auto",
4010
+ fontFamily: get4(tokens, "fontFamily.mono", []).join(","),
4011
+ lineHeight: 1.5
3683
4012
  },
3684
- ".cm-completionLabel": {
3685
- fontFamily: get4(tokens, "fontFamily.body", []).join(",")
4013
+ ".cm-content": {
4014
+ // TODO(burdon): Is it possible to remove the padding value from CM's default theme?
4015
+ // padding: 'unset',
4016
+ // NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
4017
+ fontSize: "16px"
3686
4018
  },
3687
- ".cm-completionMatchedText": {
3688
- textDecoration: "none"
4019
+ "&light .cm-content": {
4020
+ color: get4(tokens, "extend.semanticColors.base.fg.light", "black"),
4021
+ caretColor: "black"
4022
+ },
4023
+ "&dark .cm-content": {
4024
+ color: get4(tokens, "extend.semanticColors.base.fg.dark", "white"),
4025
+ caretColor: "white"
3689
4026
  },
3690
4027
  //
3691
- // table
4028
+ // Cursor
3692
4029
  //
3693
- ".cm-table *": {
3694
- fontFamily: `${get4(tokens, "fontFamily.mono", []).join(",")} !important`,
3695
- textDecoration: "none !important"
4030
+ "&light .cm-cursor, &light .cm-dropCursor": {
4031
+ borderLeft: "2px solid black"
3696
4032
  },
3697
- ".cm-table-head": {
3698
- padding: "2px 16px 2px 0px",
3699
- borderBottom: `1px solid ${get4(tokens, "extend.colors.neutral.500")}`,
3700
- fontWeight: 100,
3701
- textAlign: "left",
3702
- color: get4(tokens, "extend.colors.neutral.500")
4033
+ "&dark .cm-cursor, &dark .cm-dropCursor": {
4034
+ borderLeft: "2px solid white"
3703
4035
  },
3704
- ".cm-table-cell": {
3705
- padding: "2px 16px 2px 0px"
4036
+ "&light .cm-placeholder": {
4037
+ color: get4(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
4038
+ },
4039
+ "&dark .cm-placeholder": {
4040
+ color: get4(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
3706
4041
  },
3707
4042
  //
3708
- // image
4043
+ // line
3709
4044
  //
3710
- ".cm-image": {
3711
- display: "block",
3712
- height: "0"
4045
+ ".cm-line": {
4046
+ paddingInline: 0
4047
+ },
4048
+ ".cm-activeLine": {
4049
+ background: "transparent"
4050
+ },
4051
+ //
4052
+ // gutter
4053
+ //
4054
+ ".cm-gutterElement": {
4055
+ width: "48px"
4056
+ },
4057
+ //
4058
+ // Selection
4059
+ //
4060
+ "&light .cm-selectionBackground": {
4061
+ background: get4(tokens, "extend.colors.primary.100")
4062
+ },
4063
+ "&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
4064
+ background: get4(tokens, "extend.colors.primary.200")
4065
+ },
4066
+ "&dark .cm-selectionBackground": {
4067
+ background: get4(tokens, "extend.colors.primary.700")
4068
+ },
4069
+ "&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
4070
+ background: get4(tokens, "extend.colors.primary.600")
4071
+ },
4072
+ //
4073
+ // Search
4074
+ //
4075
+ "&light .cm-searchMatch": {
4076
+ backgroundColor: get4(tokens, "extend.colors.yellow.100")
4077
+ },
4078
+ "&dark .cm-searchMatch": {
4079
+ backgroundColor: get4(tokens, "extend.colors.yellow.700")
4080
+ },
4081
+ //
4082
+ // link
4083
+ //
4084
+ ".cm-link": {
4085
+ color: get4(tokens, "extend.colors.primary.500"),
4086
+ textDecorationLine: "underline",
4087
+ textDecorationThickness: "1px",
4088
+ textUnderlineOffset: "2px",
4089
+ borderRadius: ".125rem",
4090
+ fontFamily: get4(tokens, "fontFamily.body", []).join(",")
4091
+ },
4092
+ //
4093
+ // tooltip
4094
+ //
4095
+ ".cm-tooltip": {
4096
+ border: "none",
4097
+ background: "unset"
4098
+ },
4099
+ ".cm-tooltip-below": {},
4100
+ //
4101
+ // autocomplete
4102
+ //
4103
+ ".cm-tooltip-autocomplete": {
4104
+ marginTop: "4px",
4105
+ marginLeft: "-3px"
4106
+ },
4107
+ ".cm-tooltip-autocomplete ul li": {},
4108
+ ".cm-tooltip-autocomplete ul li[aria-selected]": {},
4109
+ ".cm-completionIcon": {
4110
+ display: "none"
4111
+ },
4112
+ ".cm-completionLabel": {
4113
+ fontFamily: get4(tokens, "fontFamily.body", []).join(",")
4114
+ },
4115
+ ".cm-completionMatchedText": {
4116
+ textDecoration: "none"
4117
+ },
4118
+ //
4119
+ // table
4120
+ //
4121
+ ".cm-table *": {
4122
+ fontFamily: `${get4(tokens, "fontFamily.mono", []).join(",")} !important`,
4123
+ textDecoration: "none !important"
4124
+ },
4125
+ ".cm-table-head": {
4126
+ padding: "2px 16px 2px 0px",
4127
+ borderBottom: `1px solid ${get4(tokens, "extend.colors.neutral.500")}`,
4128
+ fontWeight: 100,
4129
+ textAlign: "left",
4130
+ color: get4(tokens, "extend.colors.neutral.500")
4131
+ },
4132
+ ".cm-table-cell": {
4133
+ padding: "2px 16px 2px 0px"
4134
+ },
4135
+ //
4136
+ // image
4137
+ //
4138
+ ".cm-image": {
4139
+ display: "block",
4140
+ height: "0"
3713
4141
  },
3714
4142
  ".cm-image.cm-loaded-image": {
3715
4143
  height: "auto",
@@ -3795,19 +4223,238 @@ var codeTheme = {
3795
4223
  }
3796
4224
  };
3797
4225
 
4226
+ // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
4227
+ var __dxlog_file9 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
4228
+ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}, deps = []) => {
4229
+ const onUpdate = useRef2();
4230
+ const [view, setView] = useState3();
4231
+ const parentRef = useRef2(null);
4232
+ useEffect2(() => {
4233
+ let view2;
4234
+ if (parentRef.current) {
4235
+ const state = EditorState2.create({
4236
+ doc,
4237
+ selection,
4238
+ extensions: [
4239
+ // TODO(burdon): Doesn't catch errors in keymap functions.
4240
+ EditorView16.exceptionSink.of((err) => {
4241
+ log8.catch(err, void 0, {
4242
+ F: __dxlog_file9,
4243
+ L: 70,
4244
+ S: void 0,
4245
+ C: (f, a) => f(...a)
4246
+ });
4247
+ }),
4248
+ extensions,
4249
+ EditorView16.updateListener.of(() => {
4250
+ onUpdate.current?.();
4251
+ })
4252
+ ].filter(isNotFalsy3)
4253
+ });
4254
+ view2 = new EditorView16({
4255
+ parent: parentRef.current,
4256
+ scrollTo,
4257
+ state,
4258
+ // NOTE: Uncomment to debug/monitor all transactions.
4259
+ // https://codemirror.net/docs/ref/#view.EditorView.dispatch
4260
+ dispatchTransactions: (trs, view3) => {
4261
+ if (debug) {
4262
+ logChanges(trs);
4263
+ }
4264
+ view3.update(trs);
4265
+ }
4266
+ });
4267
+ setView(view2);
4268
+ }
4269
+ return () => {
4270
+ view2?.destroy();
4271
+ };
4272
+ }, deps);
4273
+ useEffect2(() => {
4274
+ if (view) {
4275
+ if (!selection && !view.state.selection.main.anchor) {
4276
+ selection = EditorSelection2.single(view.state.doc.line(1).to);
4277
+ }
4278
+ if (selection || scrollTo) {
4279
+ onUpdate.current = () => {
4280
+ onUpdate.current = void 0;
4281
+ view.dispatch({
4282
+ selection,
4283
+ effects: scrollTo && [
4284
+ scrollTo
4285
+ ],
4286
+ scrollIntoView: !scrollTo
4287
+ });
4288
+ };
4289
+ }
4290
+ if (autoFocus) {
4291
+ view.focus();
4292
+ }
4293
+ }
4294
+ }, [
4295
+ view,
4296
+ autoFocus,
4297
+ selection,
4298
+ scrollTo
4299
+ ]);
4300
+ return {
4301
+ parentRef,
4302
+ view
4303
+ };
4304
+ };
4305
+ var defaults = {
4306
+ bracketMatching: true,
4307
+ closeBrackets: true,
4308
+ drawSelection: true,
4309
+ editable: true,
4310
+ history: true,
4311
+ lineWrapping: true
4312
+ };
4313
+ var createBasicExtensions = (_props) => {
4314
+ const props = defaultsDeep2({}, _props, defaults);
4315
+ return [
4316
+ // TODO(burdon): Doesn't catch errors in keymap functions.
4317
+ EditorView16.exceptionSink.of((err) => {
4318
+ log8.catch(err, void 0, {
4319
+ F: __dxlog_file9,
4320
+ L: 167,
4321
+ S: void 0,
4322
+ C: (f, a) => f(...a)
4323
+ });
4324
+ }),
4325
+ props.allowMultipleSelections && EditorState2.allowMultipleSelections.of(true),
4326
+ props.bracketMatching && bracketMatching2(),
4327
+ props.closeBrackets && closeBrackets2(),
4328
+ props.crosshairCursor && crosshairCursor(),
4329
+ props.dropCursor && dropCursor2(),
4330
+ props.drawSelection && drawSelection2(),
4331
+ props.highlightActiveLine && highlightActiveLine(),
4332
+ props.history && history2(),
4333
+ props.lineNumbers && lineNumbers(),
4334
+ props.lineWrapping && EditorView16.lineWrapping,
4335
+ props.placeholder && placeholder2(props.placeholder),
4336
+ props.readonly && [
4337
+ EditorState2.readOnly.of(true),
4338
+ EditorView16.editable.of(false)
4339
+ ],
4340
+ props.scrollPastEnd && scrollPastEnd(),
4341
+ props.tabSize && EditorState2.tabSize.of(props.tabSize)
4342
+ ].filter(isNotFalsy3);
4343
+ };
4344
+ var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
4345
+ return [
4346
+ EditorView16.baseTheme(defaultTheme),
4347
+ EditorView16.darkTheme.of(themeMode === "dark"),
4348
+ theme && EditorView16.theme(theme),
4349
+ slots?.editor?.className && EditorView16.editorAttributes.of({
4350
+ class: slots.editor.className
4351
+ }),
4352
+ slots?.content?.className && EditorView16.contentAttributes.of({
4353
+ class: slots.content.className
4354
+ })
4355
+ ].filter(isNotFalsy3);
4356
+ };
4357
+
4358
+ // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
4359
+ import get5 from "lodash.get";
4360
+ import { useState as useState4, useMemo as useMemo2 } from "react";
4361
+ import { generateName } from "@dxos/display-name";
4362
+ import { getRawDoc } from "@dxos/echo-schema";
4363
+ import { invariant as invariant3 } from "@dxos/invariant";
4364
+ import { isAutomergeObject } from "@dxos/react-client/echo";
4365
+ import { hueTokens } from "@dxos/react-ui-theme";
4366
+ import { hexToHue } from "@dxos/util";
4367
+ var __dxlog_file10 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
4368
+ var useTextExtensions = ({ id, text, space, identity }) => {
4369
+ const extensions = [
4370
+ automerge(text)
4371
+ ];
4372
+ const peerId = identity?.identityKey.toHex();
4373
+ const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
4374
+ if (space && identity) {
4375
+ const awarenessProvider2 = new SpaceAwarenessProvider({
4376
+ space,
4377
+ channel: `awareness.${id}`,
4378
+ peerId: identity.identityKey.toHex(),
4379
+ info: {
4380
+ displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
4381
+ color: cursorDarkValue,
4382
+ lightColor: cursorLightValue
4383
+ }
4384
+ });
4385
+ extensions.push(awareness(awarenessProvider2));
4386
+ }
4387
+ return extensions;
4388
+ };
4389
+ var useTextModel = (props) => useMemo2(() => createModel(props), Object.values(props));
4390
+ var useInMemoryTextModel = ({ id, defaultContent }) => {
4391
+ const [content, setContent] = useState4(defaultContent ?? "");
4392
+ return {
4393
+ id,
4394
+ content,
4395
+ text: () => content,
4396
+ setContent
4397
+ };
4398
+ };
4399
+ var createModel = ({ space, identity, text }) => {
4400
+ if (!text) {
4401
+ return void 0;
4402
+ }
4403
+ invariant3(isAutomergeObject(text), void 0, {
4404
+ F: __dxlog_file10,
4405
+ L: 89,
4406
+ S: void 0,
4407
+ A: [
4408
+ "isAutomergeObject(text)",
4409
+ ""
4410
+ ]
4411
+ });
4412
+ const obj = text;
4413
+ const doc = getRawDoc(obj, [
4414
+ obj.field
4415
+ ]);
4416
+ const peerId = identity?.identityKey.toHex();
4417
+ const { cursorLightValue, cursorDarkValue } = hueTokens[identity?.profile?.data?.hue ?? hexToHue(peerId ?? "0")];
4418
+ const awarenessProvider2 = space && new SpaceAwarenessProvider({
4419
+ space,
4420
+ channel: `automerge.awareness.${obj.id}`,
4421
+ info: {
4422
+ displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
4423
+ color: cursorLightValue,
4424
+ lightColor: cursorDarkValue
4425
+ },
4426
+ peerId: identity?.identityKey.toHex() ?? "Anonymous"
4427
+ });
4428
+ const extensions = [
4429
+ automerge({
4430
+ handle: doc.handle,
4431
+ path: doc.path
4432
+ })
4433
+ ];
4434
+ if (awarenessProvider2) {
4435
+ extensions.push(awareness(awarenessProvider2));
4436
+ }
4437
+ return {
4438
+ id: obj.id,
4439
+ content: doc,
4440
+ text: () => get5(doc.handle.docSync(), doc.path),
4441
+ extension: extensions
4442
+ };
4443
+ };
4444
+
3798
4445
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
3799
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
3800
- var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo = EditorView14.scrollIntoView(0), moveToEndOfLine, selection, theme, slots = defaultSlots, extensions = [], scrollPastEnd: _scrollPastEnd, debug }, forwardedRef) => {
4446
+ var __dxlog_file11 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
4447
+ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo = EditorView17.scrollIntoView(0), moveToEndOfLine, selection, theme, slots = defaultSlots, extensions = [], scrollPastEnd: _scrollPastEnd, debug }, forwardedRef) => {
3801
4448
  const tabsterDOMAttribute = useFocusableGroup({
3802
4449
  tabBehavior: "limited"
3803
4450
  });
3804
4451
  const { themeMode } = useThemeContext();
3805
- const rootRef = useRef(null);
3806
- const [view, setView] = useState2(null);
4452
+ const rootRef = useRef3(null);
4453
+ const [view, setView] = useState5(null);
3807
4454
  useImperativeHandle(forwardedRef, () => view, [
3808
4455
  view
3809
4456
  ]);
3810
- useEffect2(() => {
4457
+ useEffect3(() => {
3811
4458
  if (autoFocus) {
3812
4459
  view?.focus();
3813
4460
  }
@@ -3815,38 +4462,38 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3815
4462
  view,
3816
4463
  autoFocus
3817
4464
  ]);
3818
- useEffect2(() => {
4465
+ useEffect3(() => {
3819
4466
  if (!model || !rootRef.current) {
3820
4467
  return;
3821
4468
  }
3822
- const state = EditorState2.create({
3823
- doc: model.text(),
4469
+ const state = EditorState3.create({
4470
+ doc: typeof model.content === "string" ? model.content : DocAccessor.getValue(model.content),
3824
4471
  selection,
3825
4472
  extensions: [
3826
4473
  // TODO(burdon): Doesn't catch errors in keymap functions.
3827
- EditorView14.exceptionSink.of((err) => {
3828
- log3.catch(err, void 0, {
3829
- F: __dxlog_file4,
3830
- L: 122,
4474
+ EditorView17.exceptionSink.of((err) => {
4475
+ log9.catch(err, void 0, {
4476
+ F: __dxlog_file11,
4477
+ L: 123,
3831
4478
  S: void 0,
3832
4479
  C: (f, a) => f(...a)
3833
4480
  });
3834
4481
  }),
3835
4482
  // Theme.
3836
4483
  // TODO(burdon): Make base theme configurable.
3837
- EditorView14.baseTheme(defaultTheme),
3838
- theme && EditorView14.theme(theme),
3839
- EditorView14.darkTheme.of(themeMode === "dark"),
3840
- slots.editor?.className && EditorView14.editorAttributes.of({
4484
+ EditorView17.baseTheme(defaultTheme),
4485
+ theme && EditorView17.theme(theme),
4486
+ EditorView17.darkTheme.of(themeMode === "dark"),
4487
+ slots.editor?.className && EditorView17.editorAttributes.of({
3841
4488
  class: slots.editor.className
3842
4489
  }),
3843
- slots.content?.className && EditorView14.contentAttributes.of({
4490
+ slots.content?.className && EditorView17.contentAttributes.of({
3844
4491
  class: slots.content.className
3845
4492
  }),
3846
4493
  // NOTE: Assumes default line height.
3847
- _scrollPastEnd && scrollPastEnd(),
4494
+ _scrollPastEnd && scrollPastEnd2(),
3848
4495
  // Focus.
3849
- EditorView14.updateListener.of((update2) => {
4496
+ EditorView17.updateListener.of((update2) => {
3850
4497
  update2.transactions.forEach((transaction) => {
3851
4498
  if (transaction.isUserEvent("focus.container")) {
3852
4499
  rootRef.current?.focus();
@@ -3854,8 +4501,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3854
4501
  });
3855
4502
  }),
3856
4503
  // State.
3857
- EditorView14.editable.of(!readonly),
3858
- EditorState2.readOnly.of(!!readonly),
4504
+ EditorView17.editable.of(!readonly),
4505
+ EditorState3.readOnly.of(!!readonly),
3859
4506
  // Storage and replication.
3860
4507
  // NOTE: This must come before user extensions.
3861
4508
  model.extension,
@@ -3863,7 +4510,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3863
4510
  ...extensions
3864
4511
  ].filter(isNotFalsy4)
3865
4512
  });
3866
- const view2 = new EditorView14({
4513
+ const view2 = new EditorView17({
3867
4514
  state,
3868
4515
  parent: rootRef.current,
3869
4516
  scrollTo,
@@ -3920,14 +4567,16 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3920
4567
  ...tabsterDOMAttribute
3921
4568
  });
3922
4569
  });
3923
- var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
4570
+ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping = true, theme = textTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
3924
4571
  const { themeMode } = useThemeContext();
3925
- const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
3926
- const extensions = useMemo2(() => [
3927
- createBasicBundle({
3928
- themeMode,
3929
- placeholder: placeholder3,
3930
- lineWrapping
4572
+ const updatedSlots = defaultsDeep3({}, slots, defaultTextSlots);
4573
+ const extensions = useMemo3(() => [
4574
+ createBasicExtensions({
4575
+ lineWrapping,
4576
+ placeholder: placeholder3
4577
+ }),
4578
+ createThemeExtensions({
4579
+ themeMode
3931
4580
  }),
3932
4581
  ..._extensions ?? []
3933
4582
  ], [
@@ -3947,8 +4596,8 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
3947
4596
  });
3948
4597
  var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
3949
4598
  const { themeMode } = useThemeContext();
3950
- const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
3951
- const extensions = useMemo2(() => [
4599
+ const updatedSlots = defaultsDeep3({}, slots, defaultMarkdownSlots);
4600
+ const extensions = useMemo3(() => [
3952
4601
  createMarkdownExtensions({
3953
4602
  themeMode,
3954
4603
  placeholder: placeholder3
@@ -3986,7 +4635,7 @@ var defaultMarkdownSlots = {
3986
4635
  // packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
3987
4636
  import { ChatText, Code, CodeBlock, Link, ListBullets, ListChecks, ListNumbers, Paragraph, TextStrikethrough, Table as Table2, TextB, TextHOne, TextHTwo, TextHThree, TextHFour, TextHFive, TextHSix, TextItalic, Quotes } from "@phosphor-icons/react";
3988
4637
  import { createContext } from "@radix-ui/react-context";
3989
- import React2, { useRef as useRef2, useState as useState3 } from "react";
4638
+ import React2, { useRef as useRef4, useState as useState6 } from "react";
3990
4639
  import { DensityProvider, ElevationProvider, Select, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
3991
4640
  import { getSize } from "@dxos/react-ui-theme";
3992
4641
  var tooltipProps = {
@@ -4044,9 +4693,9 @@ var MarkdownHeading = () => {
4044
4693
  const header = blockType && /heading(\d)/.exec(blockType);
4045
4694
  const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
4046
4695
  const HeadingIcon = HeadingIcons[value ?? "0"];
4047
- const suppressNextTooltip = useRef2(false);
4048
- const [tooltipOpen, setTooltipOpen] = useState3(false);
4049
- const [selectOpen, setSelectOpen] = useState3(false);
4696
+ const suppressNextTooltip = useRef4(false);
4697
+ const [tooltipOpen, setTooltipOpen] = useState6(false);
4698
+ const [selectOpen, setSelectOpen] = useState6(false);
4050
4699
  return /* @__PURE__ */ React2.createElement(Tooltip.Root, {
4051
4700
  open: tooltipOpen,
4052
4701
  onOpenChange: (nextOpen) => {
@@ -4249,384 +4898,6 @@ var Toolbar = {
4249
4898
  Markdown: MarkdownStandard,
4250
4899
  Extended: MarkdownExtended
4251
4900
  };
4252
-
4253
- // packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
4254
- import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
4255
- import { Context as Context2 } from "@dxos/context";
4256
- import { invariant as invariant2 } from "@dxos/invariant";
4257
- import { log as log4 } from "@dxos/log";
4258
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
4259
- var DEBOUNCE_INTERVAL = 100;
4260
- var SpaceAwarenessProvider = class {
4261
- constructor(params) {
4262
- this._remoteStates = /* @__PURE__ */ new Map();
4263
- this.remoteStateChange = new Event2();
4264
- this._space = params.space;
4265
- this._channel = params.channel;
4266
- this._peerId = params.peerId;
4267
- this._info = params.info;
4268
- }
4269
- open() {
4270
- this._ctx = new Context2();
4271
- this._postTask = new DeferredTask(this._ctx, async () => {
4272
- if (this._localState) {
4273
- await this._space.postMessage(this._channel, {
4274
- kind: "post",
4275
- state: this._localState
4276
- });
4277
- await sleep(DEBOUNCE_INTERVAL);
4278
- }
4279
- });
4280
- this._ctx.onDispose(this._space.listen(this._channel, (message) => {
4281
- switch (message.payload.kind) {
4282
- case "query": {
4283
- this._handleQueryMessage();
4284
- break;
4285
- }
4286
- case "post": {
4287
- this._handlePostMessage(message.payload);
4288
- break;
4289
- }
4290
- }
4291
- }));
4292
- void this._space.postMessage(this._channel, {
4293
- kind: "query"
4294
- }).catch((err) => {
4295
- log4.debug("failed to query awareness", {
4296
- err
4297
- }, {
4298
- F: __dxlog_file5,
4299
- L: 89,
4300
- S: this,
4301
- C: (f, a) => f(...a)
4302
- });
4303
- });
4304
- }
4305
- close() {
4306
- void this._ctx?.dispose();
4307
- this._ctx = void 0;
4308
- this._postTask = void 0;
4309
- }
4310
- getRemoteStates() {
4311
- return Array.from(this._remoteStates.values());
4312
- }
4313
- update(position) {
4314
- invariant2(this._postTask, void 0, {
4315
- F: __dxlog_file5,
4316
- L: 104,
4317
- S: this,
4318
- A: [
4319
- "this._postTask",
4320
- ""
4321
- ]
4322
- });
4323
- this._localState = {
4324
- peerId: this._peerId,
4325
- position,
4326
- info: this._info
4327
- };
4328
- this._postTask.schedule();
4329
- }
4330
- _handleQueryMessage() {
4331
- invariant2(this._postTask, void 0, {
4332
- F: __dxlog_file5,
4333
- L: 115,
4334
- S: this,
4335
- A: [
4336
- "this._postTask",
4337
- ""
4338
- ]
4339
- });
4340
- this._postTask.schedule();
4341
- }
4342
- _handlePostMessage(message) {
4343
- invariant2(message.kind === "post", void 0, {
4344
- F: __dxlog_file5,
4345
- L: 120,
4346
- S: this,
4347
- A: [
4348
- "message.kind === 'post'",
4349
- ""
4350
- ]
4351
- });
4352
- this._remoteStates.set(message.state.peerId, message.state);
4353
- this.remoteStateChange.emit();
4354
- }
4355
- };
4356
-
4357
- // packages/ui/react-ui-editor/src/hooks/defs.ts
4358
- import { StateField as StateField6 } from "@codemirror/state";
4359
- var modelState = StateField6.define({
4360
- create: () => void 0,
4361
- update: (model) => model
4362
- });
4363
-
4364
- // packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
4365
- var useActionHandler = (view) => {
4366
- return (action) => {
4367
- if (!view) {
4368
- return;
4369
- }
4370
- let inlineType, listType;
4371
- switch (action.type) {
4372
- case "heading":
4373
- setHeading(parseInt(action.data))(view);
4374
- break;
4375
- case "strong":
4376
- case "emphasis":
4377
- case "strikethrough":
4378
- case "code":
4379
- inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
4380
- (typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
4381
- break;
4382
- case "list-ordered":
4383
- case "list-bullet":
4384
- case "list-task":
4385
- listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
4386
- (action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
4387
- break;
4388
- case "blockquote":
4389
- (action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
4390
- break;
4391
- case "codeblock":
4392
- (action.data === false ? removeCodeblock : addCodeblock)(view);
4393
- break;
4394
- case "table":
4395
- insertTable(view);
4396
- break;
4397
- case "link":
4398
- (action.data === false ? removeLink : addLink)(view);
4399
- break;
4400
- case "comment":
4401
- createComment(view);
4402
- break;
4403
- }
4404
- setTimeout(() => {
4405
- if (!view.hasFocus) {
4406
- view.focus();
4407
- }
4408
- });
4409
- };
4410
- };
4411
-
4412
- // packages/ui/react-ui-editor/src/hooks/useEditorView.ts
4413
- import { useRef as useRef3, useState as useState4 } from "react";
4414
- var useEditorView = (id) => {
4415
- const editorRef = useRef3(null);
4416
- const [prev, setPrev] = useState4([
4417
- null,
4418
- ""
4419
- ]);
4420
- if (prev[0] !== editorRef.current) {
4421
- setPrev([
4422
- editorRef.current,
4423
- id
4424
- ]);
4425
- }
4426
- return [
4427
- editorRef,
4428
- prev[1] !== id
4429
- ];
4430
- };
4431
-
4432
- // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
4433
- import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
4434
- import { EditorView as EditorView15 } from "@codemirror/view";
4435
- import { useEffect as useEffect3, useRef as useRef4, useState as useState5 } from "react";
4436
- import { log as log5 } from "@dxos/log";
4437
- import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
4438
- var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
4439
- var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}, deps) => {
4440
- const onUpdate = useRef4();
4441
- const [view, setView] = useState5();
4442
- const parentRef = useRef4(null);
4443
- useEffect3(() => {
4444
- let view2;
4445
- if (parentRef.current) {
4446
- const state = EditorState3.create({
4447
- doc,
4448
- selection,
4449
- extensions: [
4450
- // TODO(burdon): Doesn't catch errors in keymap functions.
4451
- EditorView15.exceptionSink.of((err) => {
4452
- log5.catch(err, void 0, {
4453
- F: __dxlog_file6,
4454
- L: 57,
4455
- S: void 0,
4456
- C: (f, a) => f(...a)
4457
- });
4458
- }),
4459
- extensions,
4460
- EditorView15.updateListener.of(() => {
4461
- onUpdate.current?.();
4462
- })
4463
- ].filter(isNotFalsy5)
4464
- });
4465
- view2 = new EditorView15({
4466
- parent: parentRef.current,
4467
- scrollTo,
4468
- state,
4469
- // NOTE: Uncomment to debug/monitor all transactions.
4470
- // https://codemirror.net/docs/ref/#view.EditorView.dispatch
4471
- dispatchTransactions: (trs, view3) => {
4472
- if (debug) {
4473
- logChanges(trs);
4474
- }
4475
- view3.update(trs);
4476
- }
4477
- });
4478
- setView(view2);
4479
- }
4480
- return () => {
4481
- view2?.destroy();
4482
- };
4483
- }, deps);
4484
- useEffect3(() => {
4485
- if (view) {
4486
- if (!selection && !view.state.selection.main.anchor) {
4487
- selection = EditorSelection2.single(view.state.doc.line(1).to);
4488
- }
4489
- if (selection || scrollTo) {
4490
- onUpdate.current = () => {
4491
- onUpdate.current = void 0;
4492
- view.dispatch({
4493
- selection,
4494
- effects: scrollTo && [
4495
- scrollTo
4496
- ],
4497
- scrollIntoView: !scrollTo
4498
- });
4499
- };
4500
- }
4501
- if (autoFocus) {
4502
- view.focus();
4503
- }
4504
- }
4505
- }, [
4506
- view,
4507
- autoFocus,
4508
- selection,
4509
- scrollTo
4510
- ]);
4511
- return {
4512
- parentRef,
4513
- view
4514
- };
4515
- };
4516
- var createDataExtensions = ({ readonly = false } = {}) => {
4517
- return [
4518
- //
4519
- EditorState3.readOnly.of(readonly),
4520
- EditorView15.editable.of(!readonly)
4521
- ];
4522
- };
4523
- var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
4524
- return [
4525
- //
4526
- EditorView15.baseTheme(defaultTheme),
4527
- theme && EditorView15.theme(theme),
4528
- EditorView15.darkTheme.of(themeMode === "dark"),
4529
- EditorView15.editorAttributes.of({
4530
- class: slots?.editor?.className ?? ""
4531
- }),
4532
- EditorView15.contentAttributes.of({
4533
- class: slots?.content?.className ?? ""
4534
- })
4535
- ].filter(isNotFalsy5);
4536
- };
4537
-
4538
- // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
4539
- import get5 from "lodash.get";
4540
- import { useState as useState6, useMemo as useMemo3 } from "react";
4541
- import { generateName } from "@dxos/display-name";
4542
- import { getRawDoc } from "@dxos/echo-schema";
4543
- import { invariant as invariant3 } from "@dxos/invariant";
4544
- import { isAutomergeObject } from "@dxos/react-client/echo";
4545
- import { hueTokens } from "@dxos/react-ui-theme";
4546
- import { hexToHue } from "@dxos/util";
4547
- var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
4548
- var useTextExtensions = ({ id, text, space, identity }) => {
4549
- const extensions = [
4550
- automerge(text)
4551
- ];
4552
- const peerId = identity?.identityKey.toHex();
4553
- const { cursorLightValue, cursorDarkValue } = hueTokens[hexToHue(peerId ?? "0")];
4554
- if (space && identity) {
4555
- const awarenessProvider2 = new SpaceAwarenessProvider({
4556
- space,
4557
- channel: `awareness.${id}`,
4558
- peerId: identity.identityKey.toHex(),
4559
- info: {
4560
- displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
4561
- color: cursorDarkValue,
4562
- lightColor: cursorLightValue
4563
- }
4564
- });
4565
- extensions.push(awareness(awarenessProvider2));
4566
- }
4567
- return extensions;
4568
- };
4569
- var useTextModel = (props) => useMemo3(() => createModel(props), Object.values(props));
4570
- var useInMemoryTextModel = ({ id, defaultContent }) => {
4571
- const [content, setContent] = useState6(defaultContent ?? "");
4572
- return {
4573
- id,
4574
- content,
4575
- setContent,
4576
- text: () => content
4577
- };
4578
- };
4579
- var createModel = ({ space, identity, text }) => {
4580
- if (!text) {
4581
- return void 0;
4582
- }
4583
- invariant3(isAutomergeObject(text), void 0, {
4584
- F: __dxlog_file7,
4585
- L: 87,
4586
- S: void 0,
4587
- A: [
4588
- "isAutomergeObject(text)",
4589
- ""
4590
- ]
4591
- });
4592
- const obj = text;
4593
- const doc = getRawDoc(obj, [
4594
- obj.field
4595
- ]);
4596
- const peerId = identity?.identityKey.toHex();
4597
- const { cursorLightValue, cursorDarkValue } = hueTokens[hexToHue(peerId ?? "0")];
4598
- const awarenessProvider2 = space && new SpaceAwarenessProvider({
4599
- space,
4600
- channel: `automerge.awareness.${obj.id}`,
4601
- info: {
4602
- displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
4603
- color: cursorLightValue,
4604
- lightColor: cursorDarkValue
4605
- },
4606
- peerId: identity?.identityKey.toHex() ?? "Anonymous"
4607
- });
4608
- const extensions = [
4609
- modelState.init(() => model),
4610
- automerge({
4611
- handle: doc.handle,
4612
- path: doc.path
4613
- })
4614
- ];
4615
- if (awarenessProvider2) {
4616
- extensions.push(awareness(awarenessProvider2));
4617
- }
4618
- const model = {
4619
- id: obj.id,
4620
- content: doc,
4621
- text: () => get5(doc.handle.docSync(), doc.path),
4622
- extension: extensions,
4623
- peer: identity ? {
4624
- id: identity.identityKey.toHex(),
4625
- name: identity.profile?.displayName
4626
- } : void 0
4627
- };
4628
- return model;
4629
- };
4630
4901
  export {
4631
4902
  BaseTextEditor,
4632
4903
  Cursor,
@@ -4655,11 +4926,11 @@ export {
4655
4926
  blast,
4656
4927
  callbackWrapper,
4657
4928
  codeTheme,
4929
+ command,
4658
4930
  comments,
4659
4931
  compareFormatting,
4660
- createBasicBundle,
4932
+ createBasicExtensions,
4661
4933
  createComment,
4662
- createDataExtensions,
4663
4934
  createMarkdownExtensions,
4664
4935
  createThemeExtensions,
4665
4936
  cursorLineMargin,
@@ -4670,6 +4941,7 @@ export {
4670
4941
  defaultSlots,
4671
4942
  defaultTextSlots,
4672
4943
  defaultTheme,
4944
+ dnd,
4673
4945
  editorFillLayoutEditor,
4674
4946
  editorFillLayoutRoot,
4675
4947
  editorMode,
@@ -4680,7 +4952,7 @@ export {
4680
4952
  getToken,
4681
4953
  image,
4682
4954
  insertTable,
4683
- keymap8 as keymap,
4955
+ keymap9 as keymap,
4684
4956
  linkTooltip,
4685
4957
  listener,
4686
4958
  logChanges,
@@ -4689,7 +4961,6 @@ export {
4689
4961
  markdownTagsExtensions,
4690
4962
  markdownTheme,
4691
4963
  mention,
4692
- modelState,
4693
4964
  outliner,
4694
4965
  removeBlockquote,
4695
4966
  removeCodeblock,