@dxos/react-ui-editor 0.4.7-main.ec8b8b7 → 0.4.7-main.f4b92be

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 (83) hide show
  1. package/dist/lib/browser/index.mjs +941 -741
  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.map +1 -1
  12. package/dist/types/src/{components/TextEditor → extensions/automerge}/automerge.stories.d.ts +4 -2
  13. package/dist/types/src/extensions/automerge/automerge.stories.d.ts.map +1 -0
  14. package/dist/types/src/extensions/command/command.d.ts +10 -0
  15. package/dist/types/src/extensions/command/command.d.ts.map +1 -0
  16. package/dist/types/src/extensions/command/hint.d.ts +7 -0
  17. package/dist/types/src/extensions/command/hint.d.ts.map +1 -0
  18. package/dist/types/src/extensions/command/index.d.ts +2 -0
  19. package/dist/types/src/extensions/command/index.d.ts.map +1 -0
  20. package/dist/types/src/extensions/command/state.d.ts +18 -0
  21. package/dist/types/src/extensions/command/state.d.ts.map +1 -0
  22. package/dist/types/src/extensions/cursor-line-margin.d.ts.map +1 -1
  23. package/dist/types/src/extensions/dnd.d.ts +3 -0
  24. package/dist/types/src/extensions/dnd.d.ts.map +1 -0
  25. package/dist/types/src/extensions/index.d.ts +2 -1
  26. package/dist/types/src/extensions/index.d.ts.map +1 -1
  27. package/dist/types/src/extensions/listener.d.ts +1 -1
  28. package/dist/types/src/extensions/listener.d.ts.map +1 -1
  29. package/dist/types/src/extensions/markdown/bundle.d.ts +2 -2
  30. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  31. package/dist/types/src/extensions/markdown/decorate.d.ts +3 -0
  32. package/dist/types/src/extensions/markdown/decorate.d.ts.map +1 -1
  33. package/dist/types/src/extensions/util/dom.d.ts +15 -0
  34. package/dist/types/src/extensions/util/dom.d.ts.map +1 -0
  35. package/dist/types/src/hooks/defs.d.ts +5 -11
  36. package/dist/types/src/hooks/defs.d.ts.map +1 -1
  37. package/dist/types/src/hooks/useEditorView.d.ts.map +1 -1
  38. package/dist/types/src/hooks/useTextEditor.d.ts +20 -5
  39. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -1
  40. package/dist/types/src/{components/TextEditor/hooks.stories.d.ts → hooks/useTextEditor.stories.d.ts} +1 -3
  41. package/dist/types/src/hooks/useTextEditor.stories.d.ts.map +1 -0
  42. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  43. package/dist/types/src/index.d.ts +1 -0
  44. package/dist/types/src/index.d.ts.map +1 -1
  45. package/dist/types/src/styles/index.d.ts +0 -1
  46. package/dist/types/src/styles/index.d.ts.map +1 -1
  47. package/dist/types/src/themes/default.d.ts.map +1 -1
  48. package/package.json +25 -25
  49. package/src/components/TextEditor/MarkdownEditor.stories.tsx +95 -8
  50. package/src/components/TextEditor/TextEditor.stories.tsx +0 -15
  51. package/src/components/TextEditor/TextEditor.tsx +11 -6
  52. package/src/components/TextEditor/index.ts +0 -3
  53. package/src/components/Toolbar/Toolbar.stories.tsx +2 -1
  54. package/src/{components/TextEditor → extensions/automerge}/automerge.stories.tsx +32 -37
  55. package/src/extensions/awareness.ts +3 -3
  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/cursor-line-margin.ts +2 -1
  61. package/src/extensions/dnd.ts +15 -0
  62. package/src/extensions/index.ts +2 -1
  63. package/src/extensions/listener.ts +3 -3
  64. package/src/extensions/markdown/bundle.ts +4 -14
  65. package/src/extensions/markdown/decorate.ts +20 -13
  66. package/src/extensions/util/dom.ts +36 -0
  67. package/src/hooks/defs.ts +6 -20
  68. package/src/hooks/useActionHandler.ts +11 -11
  69. package/src/hooks/useEditorView.ts +0 -1
  70. package/src/{components/TextEditor/hooks.stories.tsx → hooks/useTextEditor.stories.tsx} +8 -8
  71. package/src/hooks/useTextEditor.ts +69 -14
  72. package/src/hooks/useTextModel.ts +18 -18
  73. package/src/index.ts +2 -0
  74. package/src/styles/index.ts +0 -1
  75. package/src/themes/default.ts +1 -0
  76. package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +0 -1
  77. package/dist/types/src/components/TextEditor/hooks.stories.d.ts.map +0 -1
  78. package/dist/types/src/extensions/basic.d.ts +0 -9
  79. package/dist/types/src/extensions/basic.d.ts.map +0 -1
  80. package/dist/types/src/styles/cursors.d.ts +0 -5
  81. package/dist/types/src/styles/cursors.d.ts.map +0 -1
  82. package/src/extensions/basic.ts +0 -41
  83. package/src/styles/cursors.ts +0 -21
@@ -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 log5 } 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";
@@ -596,7 +595,7 @@ var RemoteSelectionsDecorator = class {
596
595
  to: startLine.from + startLine.length,
597
596
  value: Decoration2.mark({
598
597
  attributes: {
599
- style: `background-color: ${color}`
598
+ style: `background-color: ${lightColor}`
600
599
  },
601
600
  class: "cm-collab-selection"
602
601
  })
@@ -606,7 +605,7 @@ var RemoteSelectionsDecorator = class {
606
605
  to: end,
607
606
  value: Decoration2.mark({
608
607
  attributes: {
609
- style: `background-color: ${color}`
608
+ style: `background-color: ${lightColor}`
610
609
  },
611
610
  class: "cm-collab-selection"
612
611
  })
@@ -618,7 +617,7 @@ var RemoteSelectionsDecorator = class {
618
617
  to: linePos,
619
618
  value: Decoration2.line({
620
619
  attributes: {
621
- style: `background-color: ${color}`,
620
+ style: `background-color: ${lightColor}`,
622
621
  class: "cm-collab-selectionLine"
623
622
  }
624
623
  })
@@ -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,52 +1042,231 @@ var random = (min, max) => {
1063
1042
  return min + ~~(Math.random() * (max - min + 1));
1064
1043
  };
1065
1044
 
1066
- // packages/ui/react-ui-editor/src/extensions/comments.ts
1067
- 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";
1070
- import sortBy from "lodash.sortby";
1071
- import { useEffect } from "react";
1072
- import { debounce } from "@dxos/async";
1073
- import { nonNullable } from "@dxos/util";
1045
+ // packages/ui/react-ui-editor/src/extensions/command/command.ts
1046
+ import { EditorView as EditorView6, keymap as keymap3 } from "@codemirror/view";
1074
1047
 
1075
- // packages/ui/react-ui-editor/src/styles/cursors.ts
1076
- import * as random2 from "lib0/random";
1077
- var cursorColors = [
1078
- {
1079
- color: "#30bced",
1080
- light: "#30bced33"
1081
- },
1082
- {
1083
- color: "#6eeb83",
1084
- light: "#6eeb8333"
1085
- },
1086
- {
1087
- color: "#ffbc42",
1088
- light: "#ffbc4233"
1089
- },
1090
- {
1091
- color: "#ecd444",
1092
- light: "#ecd44433"
1093
- },
1094
- {
1095
- color: "#ee6352",
1096
- light: "#ee635233"
1097
- },
1098
- {
1099
- color: "#9ac2c9",
1100
- light: "#9ac2c933"
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;
1101
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 = [
1102
1145
  {
1103
- color: "#8acb88",
1104
- light: "#8acb8833"
1146
+ key: "/",
1147
+ run: openCommand
1105
1148
  },
1106
1149
  {
1107
- color: "#1be7ff",
1108
- light: "#1be7ff33"
1150
+ key: "Escape",
1151
+ run: closeCommand
1109
1152
  }
1110
1153
  ];
1111
- var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
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
+
1262
+ // packages/ui/react-ui-editor/src/extensions/comments.ts
1263
+ import { invertedEffects } from "@codemirror/commands";
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";
1266
+ import sortBy from "lodash.sortby";
1267
+ import { useEffect } from "react";
1268
+ import { debounce } from "@dxos/async";
1269
+ import { nonNullable } from "@dxos/util";
1112
1270
 
1113
1271
  // packages/ui/react-ui-editor/src/styles/markdown.ts
1114
1272
  import { mx } from "@dxos/react-ui-theme";
@@ -1180,13 +1338,13 @@ var logChanges = (trs) => {
1180
1338
  };
1181
1339
 
1182
1340
  // packages/ui/react-ui-editor/src/extensions/comments.ts
1183
- var documentId = Facet3.define({
1341
+ var documentId = Facet4.define({
1184
1342
  combine: (values) => values[0]
1185
1343
  });
1186
- var setComments = StateEffect2.define();
1187
- var setSelection = StateEffect2.define();
1188
- var setCommentState = StateEffect2.define();
1189
- var commentsState = StateField3.define({
1344
+ var setComments = StateEffect3.define();
1345
+ var setSelection = StateEffect3.define();
1346
+ var setCommentState = StateEffect3.define();
1347
+ var commentsState = StateField4.define({
1190
1348
  create: (state) => ({
1191
1349
  id: state.facet(documentId),
1192
1350
  comments: [],
@@ -1224,7 +1382,7 @@ var commentsState = StateField3.define({
1224
1382
  return value;
1225
1383
  }
1226
1384
  });
1227
- var styles3 = EditorView6.baseTheme({
1385
+ var styles3 = EditorView7.baseTheme({
1228
1386
  "&light .cm-comment, &light .cm-comment-current": {
1229
1387
  mixBlendMode: "darken"
1230
1388
  },
@@ -1246,19 +1404,19 @@ var styles3 = EditorView6.baseTheme({
1246
1404
  backgroundColor: getToken("extend.colors.yellow.950")
1247
1405
  }
1248
1406
  });
1249
- var commentMark = Decoration3.mark({
1407
+ var commentMark = Decoration4.mark({
1250
1408
  class: "cm-comment",
1251
1409
  attributes: {
1252
1410
  "data-testid": "cm-comment"
1253
1411
  }
1254
1412
  });
1255
- var commentCurrentMark = Decoration3.mark({
1413
+ var commentCurrentMark = Decoration4.mark({
1256
1414
  class: "cm-comment-current",
1257
1415
  attributes: {
1258
1416
  "data-testid": "cm-comment"
1259
1417
  }
1260
1418
  });
1261
- var commentsDecorations = EditorView6.decorations.compute([
1419
+ var commentsDecorations = EditorView7.decorations.compute([
1262
1420
  commentsState
1263
1421
  ], (state) => {
1264
1422
  const { selection: { current }, comments: comments2 } = state.field(commentsState);
@@ -1274,7 +1432,7 @@ var commentsDecorations = EditorView6.decorations.compute([
1274
1432
  return commentMark.range(range.from, range.to);
1275
1433
  }
1276
1434
  }).filter(nonNullable);
1277
- return Decoration3.set(decorations);
1435
+ return Decoration4.set(decorations);
1278
1436
  });
1279
1437
  var trackPastedComments = (onUpdate) => {
1280
1438
  let tracked = null;
@@ -1296,7 +1454,7 @@ var trackPastedComments = (onUpdate) => {
1296
1454
  }
1297
1455
  };
1298
1456
  return [
1299
- EditorView6.domEventHandlers({
1457
+ EditorView7.domEventHandlers({
1300
1458
  cut: handleTrack,
1301
1459
  copy: handleTrack
1302
1460
  }),
@@ -1318,7 +1476,7 @@ var trackPastedComments = (onUpdate) => {
1318
1476
  return effects;
1319
1477
  }),
1320
1478
  // Handle paste or the undo of comment deletion.
1321
- EditorView6.updateListener.of((update2) => {
1479
+ EditorView7.updateListener.of((update2) => {
1322
1480
  const restore = [];
1323
1481
  for (let i = 0; i < update2.transactions.length; i++) {
1324
1482
  const tr = update2.transactions[i];
@@ -1374,7 +1532,7 @@ var mapTrackedComment = (comment, changes) => ({
1374
1532
  from: changes.mapPos(comment.from, 1),
1375
1533
  to: changes.mapPos(comment.to, 1)
1376
1534
  });
1377
- var restoreCommentEffect = StateEffect2.define({
1535
+ var restoreCommentEffect = StateEffect3.define({
1378
1536
  map: mapTrackedComment
1379
1537
  });
1380
1538
  var createComment = (view) => {
@@ -1415,7 +1573,7 @@ var createComment = (view) => {
1415
1573
  }
1416
1574
  return false;
1417
1575
  };
1418
- var optionsFacet = Facet3.define({
1576
+ var optionsFacet = Facet4.define({
1419
1577
  combine: (providers) => providers[0]
1420
1578
  });
1421
1579
  var comments = (options = {}) => {
@@ -1430,7 +1588,7 @@ var comments = (options = {}) => {
1430
1588
  //
1431
1589
  // Keymap.
1432
1590
  //
1433
- options.onCreate ? keymap3.of([
1591
+ options.onCreate ? keymap4.of([
1434
1592
  {
1435
1593
  key: shortcut,
1436
1594
  run: callbackWrapper(createComment)
@@ -1469,7 +1627,7 @@ var comments = (options = {}) => {
1469
1627
  //
1470
1628
  // Track deleted ranges and update ranges for decorations.
1471
1629
  //
1472
- EditorView6.updateListener.of(({ view, state, changes }) => {
1630
+ EditorView7.updateListener.of(({ view, state, changes }) => {
1473
1631
  let mod = false;
1474
1632
  const { comments: comments2, ...value } = state.field(commentsState);
1475
1633
  changes.iterChanges((from, to, from2, to2) => {
@@ -1501,7 +1659,7 @@ var comments = (options = {}) => {
1501
1659
  //
1502
1660
  // Track selection/proximity.
1503
1661
  //
1504
- EditorView6.updateListener.of(({ view, state }) => {
1662
+ EditorView7.updateListener.of(({ view, state }) => {
1505
1663
  let min = Infinity;
1506
1664
  const { selection: { current, closest }, comments: comments2 } = state.field(commentsState);
1507
1665
  const { head } = state.selection.main;
@@ -1550,7 +1708,7 @@ var focusComment = (view, id, center = true) => {
1550
1708
  },
1551
1709
  effects: [
1552
1710
  //
1553
- EditorView6.scrollIntoView(range.from, center ? {
1711
+ EditorView7.scrollIntoView(range.from, center ? {
1554
1712
  y: "center"
1555
1713
  } : void 0),
1556
1714
  setSelection.of({
@@ -1578,14 +1736,14 @@ var useComments = (view, id, comments2 = []) => {
1578
1736
  };
1579
1737
 
1580
1738
  // packages/ui/react-ui-editor/src/extensions/cursor-line-margin.ts
1581
- import { Facet as Facet4, Transaction } from "@codemirror/state";
1582
- import { EditorView as EditorView7 } from "@codemirror/view";
1583
- var cursorLineMarginFacet = Facet4.define({
1739
+ import { Facet as Facet5, Transaction } from "@codemirror/state";
1740
+ import { EditorView as EditorView8 } from "@codemirror/view";
1741
+ var cursorLineMarginFacet = Facet5.define({
1584
1742
  combine: (input) => input[0] ?? 3
1585
1743
  });
1586
1744
  var annotation = "cursorLineMargin";
1587
1745
  var lineAtPos = (s, pos) => s.doc.lineAt(pos).number;
1588
- var cursorLineMargin = EditorView7.updateListener.of(({ transactions, state, selectionSet, startState, view }) => {
1746
+ var cursorLineMargin = EditorView8.updateListener.of(({ transactions, state, selectionSet, startState, view }) => {
1589
1747
  if (transactions.length < 1 || transactions.some((tr) => tr.isUserEvent(annotation))) {
1590
1748
  return;
1591
1749
  }
@@ -1621,38 +1779,48 @@ var cursorLineMargin = EditorView7.updateListener.of(({ transactions, state, sel
1621
1779
  }
1622
1780
  view.dispatch({
1623
1781
  annotations: Transaction.userEvent.of(annotation),
1624
- effects: EditorView7.scrollIntoView(s.selection.main.head, {
1782
+ effects: EditorView8.scrollIntoView(s.selection.main.head, {
1625
1783
  y: needsScrollTop ? "start" : "end",
1626
1784
  yMargin: view.defaultLineHeight * cursorLineMargin2
1627
1785
  })
1628
1786
  });
1629
1787
  });
1630
1788
 
1789
+ // packages/ui/react-ui-editor/src/extensions/dnd.ts
1790
+ import { EditorView as EditorView9 } from "@codemirror/view";
1791
+ var dnd = () => {
1792
+ return EditorView9.domEventHandlers({
1793
+ drop: (event, view) => {
1794
+ console.log(event);
1795
+ }
1796
+ });
1797
+ };
1798
+
1631
1799
  // packages/ui/react-ui-editor/src/extensions/listener.ts
1632
- import { EditorView as EditorView8 } from "@codemirror/view";
1800
+ import { EditorView as EditorView10 } from "@codemirror/view";
1633
1801
  var listener = ({ onFocus, onChange }) => {
1634
1802
  const extensions = [];
1635
- onFocus && extensions.push(EditorView8.focusChangeEffect.of((_, focused) => {
1636
- onFocus(focused);
1803
+ onFocus && extensions.push(EditorView10.focusChangeEffect.of((_, focusing) => {
1804
+ onFocus(focusing);
1637
1805
  return null;
1638
1806
  }));
1639
- onChange && extensions.push(EditorView8.updateListener.of((update2) => {
1807
+ onChange && extensions.push(EditorView10.updateListener.of((update2) => {
1640
1808
  onChange(update2.state.doc.toString());
1641
1809
  }));
1642
1810
  return extensions;
1643
1811
  };
1644
1812
 
1645
1813
  // packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
1646
- import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
1647
- import { history as history2, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
1814
+ import { closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete";
1815
+ import { history, historyKeymap, indentWithTab, standardKeymap } from "@codemirror/commands";
1648
1816
  import { markdownLanguage as markdownLanguage3, markdown } from "@codemirror/lang-markdown";
1649
- import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
1817
+ import { bracketMatching, defaultHighlightStyle, indentOnInput, syntaxHighlighting } from "@codemirror/language";
1650
1818
  import { languages } from "@codemirror/language-data";
1651
1819
  import { searchKeymap } from "@codemirror/search";
1652
1820
  import { EditorState } from "@codemirror/state";
1653
- import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
1654
- import { crosshairCursor, drawSelection as drawSelection2, dropCursor, EditorView as EditorView9, highlightActiveLine as highlightActiveLine2, keymap as keymap4, placeholder as placeholder2 } from "@codemirror/view";
1655
- import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
1821
+ import { oneDarkHighlightStyle } from "@codemirror/theme-one-dark";
1822
+ import { EditorView as EditorView11, drawSelection, dropCursor, keymap as keymap5, placeholder } from "@codemirror/view";
1823
+ import { isNotFalsy as isNotFalsy2 } from "@dxos/util";
1656
1824
 
1657
1825
  // packages/ui/react-ui-editor/src/extensions/markdown/highlight.ts
1658
1826
  import { markdownLanguage as markdownLanguage2 } from "@codemirror/lang-markdown";
@@ -1845,19 +2013,17 @@ var markdownHighlightStyle = (readonly) => {
1845
2013
  // packages/ui/react-ui-editor/src/extensions/markdown/bundle.ts
1846
2014
  var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrapping = true } = {}) => {
1847
2015
  return [
1848
- lineWrapping && EditorView9.lineWrapping,
2016
+ // TODO(burdon): Reconcile with createBasicExtensions.
2017
+ lineWrapping && EditorView11.lineWrapping,
1849
2018
  EditorState.allowMultipleSelections.of(true),
1850
2019
  EditorState.tabSize.of(2),
1851
- // https://github.com/codemirror/basic-setup
1852
- bracketMatching2(),
1853
- closeBrackets2(),
1854
- crosshairCursor(),
2020
+ bracketMatching(),
2021
+ closeBrackets(),
1855
2022
  dropCursor(),
1856
- drawSelection2(),
1857
- highlightActiveLine2(),
1858
- history2(),
2023
+ drawSelection(),
2024
+ history(),
1859
2025
  indentOnInput(),
1860
- _placeholder && placeholder2(_placeholder),
2026
+ _placeholder && placeholder(_placeholder),
1861
2027
  // Main extension.
1862
2028
  // https://github.com/codemirror/lang-markdown
1863
2029
  // https://codemirror.net/5/mode/markdown/index.html (demo).
@@ -1877,10 +2043,10 @@ var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrap
1877
2043
  ]
1878
2044
  }),
1879
2045
  // https://github.com/codemirror/theme-one-dark
1880
- themeMode === "dark" ? syntaxHighlighting2(oneDarkHighlightStyle2) : syntaxHighlighting2(defaultHighlightStyle2),
2046
+ themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
1881
2047
  // Custom styles.
1882
- syntaxHighlighting2(markdownHighlightStyle()),
1883
- keymap4.of([
2048
+ syntaxHighlighting(markdownHighlightStyle()),
2049
+ keymap5.of([
1884
2050
  // https://codemirror.net/docs/ref/#commands.indentWithTab
1885
2051
  indentWithTab,
1886
2052
  // https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
@@ -1892,22 +2058,22 @@ var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrap
1892
2058
  // https://codemirror.net/docs/ref/#commands.standardKeymap
1893
2059
  ...standardKeymap
1894
2060
  ])
1895
- ].filter(isNotFalsy3);
2061
+ ].filter(isNotFalsy2);
1896
2062
  };
1897
2063
 
1898
2064
  // packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
1899
2065
  import { syntaxTree } from "@codemirror/language";
1900
- import { RangeSetBuilder, StateEffect as StateEffect3 } from "@codemirror/state";
1901
- import { EditorView as EditorView10, Decoration as Decoration4, WidgetType as WidgetType2, ViewPlugin as ViewPlugin3 } from "@codemirror/view";
2066
+ import { RangeSetBuilder as RangeSetBuilder2, StateEffect as StateEffect4 } from "@codemirror/state";
2067
+ import { EditorView as EditorView12, Decoration as Decoration5, WidgetType as WidgetType3, ViewPlugin as ViewPlugin4 } from "@codemirror/view";
1902
2068
  import { mx as mx2 } from "@dxos/react-ui-theme";
1903
- var HorizontalRuleWidget = class extends WidgetType2 {
2069
+ var HorizontalRuleWidget = class extends WidgetType3 {
1904
2070
  toDOM() {
1905
2071
  const el = document.createElement("span");
1906
2072
  el.className = "cm-hr";
1907
2073
  return el;
1908
2074
  }
1909
2075
  };
1910
- var LinkButton = class extends WidgetType2 {
2076
+ var LinkButton = class extends WidgetType3 {
1911
2077
  constructor(url, render) {
1912
2078
  super();
1913
2079
  this.url = url;
@@ -1922,7 +2088,7 @@ var LinkButton = class extends WidgetType2 {
1922
2088
  return el;
1923
2089
  }
1924
2090
  };
1925
- var CheckboxWidget = class extends WidgetType2 {
2091
+ var CheckboxWidget = class extends WidgetType3 {
1926
2092
  constructor(_checked) {
1927
2093
  super();
1928
2094
  this._checked = _checked;
@@ -1959,23 +2125,23 @@ var CheckboxWidget = class extends WidgetType2 {
1959
2125
  return false;
1960
2126
  }
1961
2127
  };
1962
- var hide = Decoration4.replace({});
1963
- var fencedCodeLine = Decoration4.line({
2128
+ var hide = Decoration5.replace({});
2129
+ var fencedCodeLine = Decoration5.line({
1964
2130
  class: mx2("cm-code cm-codeblock-line")
1965
2131
  });
1966
- var fencedCodeLineFirst = Decoration4.line({
2132
+ var fencedCodeLineFirst = Decoration5.line({
1967
2133
  class: mx2("cm-code cm-codeblock-line", "cm-codeblock-first")
1968
2134
  });
1969
- var fencedCodeLineLast = Decoration4.line({
2135
+ var fencedCodeLineLast = Decoration5.line({
1970
2136
  class: mx2("cm-code cm-codeblock-line", "cm-codeblock-last")
1971
2137
  });
1972
- var horizontalRule = Decoration4.replace({
2138
+ var horizontalRule = Decoration5.replace({
1973
2139
  widget: new HorizontalRuleWidget()
1974
2140
  });
1975
- var checkedTask = Decoration4.replace({
2141
+ var checkedTask = Decoration5.replace({
1976
2142
  widget: new CheckboxWidget(true)
1977
2143
  });
1978
- var uncheckedTask = Decoration4.replace({
2144
+ var uncheckedTask = Decoration5.replace({
1979
2145
  widget: new CheckboxWidget(false)
1980
2146
  });
1981
2147
  var editingRange = (state, range, focus) => {
@@ -1990,8 +2156,8 @@ var MarksByParent = /* @__PURE__ */ new Set([
1990
2156
  "SuperscriptMark"
1991
2157
  ]);
1992
2158
  var buildDecorations = (view, options, focus) => {
1993
- const deco = new RangeSetBuilder();
1994
- const atomicDeco = new RangeSetBuilder();
2159
+ const deco = new RangeSetBuilder2();
2160
+ const atomicDeco = new RangeSetBuilder2();
1995
2161
  const { state } = view;
1996
2162
  for (const { from, to } of view.visibleRanges) {
1997
2163
  syntaxTree(state).iterate({
@@ -2008,7 +2174,7 @@ var buildDecorations = (view, options, focus) => {
2008
2174
  break;
2009
2175
  }
2010
2176
  const first = block.from <= node.from;
2011
- const last = block.to >= node.to;
2177
+ const last = block.to >= node.to && /^(\s>)*```$/.test(state.doc.sliceString(block.from, block.to));
2012
2178
  deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
2013
2179
  if (!editing && (first || last)) {
2014
2180
  atomicDeco.add(block.from, block.to, hide);
@@ -2024,7 +2190,7 @@ var buildDecorations = (view, options, focus) => {
2024
2190
  if (!editing) {
2025
2191
  atomicDeco.add(node.from, marks[0].to, hide);
2026
2192
  }
2027
- deco.add(marks[0].to, marks[1].from, Decoration4.mark({
2193
+ deco.add(marks[0].to, marks[1].from, Decoration5.mark({
2028
2194
  tagName: "a",
2029
2195
  attributes: {
2030
2196
  class: "cm-link",
@@ -2034,7 +2200,7 @@ var buildDecorations = (view, options, focus) => {
2034
2200
  }
2035
2201
  }));
2036
2202
  if (!editing) {
2037
- atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration4.replace({
2203
+ atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration5.replace({
2038
2204
  widget: new LinkButton(url, options.renderLinkButton)
2039
2205
  }) : hide);
2040
2206
  }
@@ -2052,7 +2218,7 @@ var buildDecorations = (view, options, focus) => {
2052
2218
  } else if (node.name === "TaskMarker") {
2053
2219
  if (!editingRange(state, node, focus)) {
2054
2220
  const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
2055
- atomicDeco.add(node.from - 2, node.from - 1, Decoration4.mark({
2221
+ atomicDeco.add(node.from - 2, node.from - 1, Decoration5.mark({
2056
2222
  class: "cm-task"
2057
2223
  }));
2058
2224
  atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
@@ -2070,50 +2236,51 @@ var buildDecorations = (view, options, focus) => {
2070
2236
  atomicDeco: atomicDeco.finish()
2071
2237
  };
2072
2238
  };
2073
- var forceUpdate = StateEffect3.define();
2239
+ var forceUpdate = StateEffect4.define();
2074
2240
  var decorateMarkdown = (options = {}) => {
2075
2241
  return [
2076
- ViewPlugin3.fromClass(class {
2242
+ ViewPlugin4.fromClass(class {
2077
2243
  constructor(view) {
2078
- this.pendingUpdate = -1;
2079
2244
  ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(view, options, view.hasFocus));
2080
2245
  }
2081
2246
  update(update2) {
2082
- if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate)))) {
2247
+ if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate))) || update2.selectionSet && !options.selectionChangeDelay) {
2083
2248
  ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(update2.view, options, update2.view.hasFocus));
2084
2249
  this.clearUpdate();
2085
2250
  } else if (update2.selectionSet) {
2086
2251
  this.scheduleUpdate(update2.view);
2087
2252
  }
2088
2253
  }
2089
- clearUpdate() {
2090
- if (this.pendingUpdate > -1) {
2091
- window.clearTimeout(this.pendingUpdate);
2092
- this.pendingUpdate = -1;
2093
- }
2094
- }
2254
+ // TODO(burdon): BUG: If the cursor is at the end of a link at the end of a line,
2255
+ // the cursor will float in space or be in the wrong position after the decoration is applied.
2095
2256
  scheduleUpdate(view) {
2096
2257
  this.clearUpdate();
2097
- this.pendingUpdate = window.setTimeout(() => {
2258
+ this.pendingUpdate = setTimeout(() => {
2098
2259
  view.dispatch({
2099
2260
  effects: forceUpdate.of(null)
2100
2261
  });
2101
- }, options.selectionChangeDelay ?? 400);
2262
+ }, options.selectionChangeDelay);
2263
+ }
2264
+ clearUpdate() {
2265
+ if (this.pendingUpdate) {
2266
+ clearTimeout(this.pendingUpdate);
2267
+ this.pendingUpdate = void 0;
2268
+ }
2102
2269
  }
2103
2270
  destroy() {
2104
2271
  this.clearUpdate();
2105
2272
  }
2106
2273
  }, {
2107
2274
  provide: (plugin) => [
2108
- EditorView10.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration4.none),
2109
- EditorView10.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration4.none),
2110
- EditorView10.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration4.none)
2275
+ EditorView12.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
2276
+ EditorView12.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration5.none),
2277
+ EditorView12.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration5.none)
2111
2278
  ]
2112
2279
  }),
2113
2280
  formattingStyles
2114
2281
  ];
2115
2282
  };
2116
- var formattingStyles = EditorView10.baseTheme({
2283
+ var formattingStyles = EditorView12.baseTheme({
2117
2284
  "& .cm-code": {
2118
2285
  fontFamily: getToken("fontFamily.mono", []).join(",")
2119
2286
  },
@@ -2166,7 +2333,7 @@ var formattingStyles = EditorView10.baseTheme({
2166
2333
  import { snippet } from "@codemirror/autocomplete";
2167
2334
  import { syntaxTree as syntaxTree2 } from "@codemirror/language";
2168
2335
  import { EditorSelection } from "@codemirror/state";
2169
- import { EditorView as EditorView11, keymap as keymap5 } from "@codemirror/view";
2336
+ import { EditorView as EditorView13, keymap as keymap6 } from "@codemirror/view";
2170
2337
  import { useState, useMemo } from "react";
2171
2338
  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;
2172
2339
  var Inline;
@@ -3038,7 +3205,7 @@ var toggleCodeblock = (target) => {
3038
3205
  };
3039
3206
  var formatting = (options = {}) => {
3040
3207
  return [
3041
- keymap5.of([
3208
+ keymap6.of([
3042
3209
  {
3043
3210
  key: "meta-b",
3044
3211
  run: toggleStrong
@@ -3236,7 +3403,7 @@ var getFormatting = (state) => {
3236
3403
  };
3237
3404
  var useFormattingState = () => {
3238
3405
  const [state, setState] = useState(null);
3239
- const observer = useMemo(() => EditorView11.updateListener.of((update2) => {
3406
+ const observer = useMemo(() => EditorView13.updateListener.of((update2) => {
3240
3407
  if (update2.docChanged || update2.selectionSet) {
3241
3408
  const newState = getFormatting(update2.state);
3242
3409
  if (!state || !compareFormatting(state, newState)) {
@@ -3252,12 +3419,12 @@ var useFormattingState = () => {
3252
3419
 
3253
3420
  // packages/ui/react-ui-editor/src/extensions/markdown/image.ts
3254
3421
  import { syntaxTree as syntaxTree3 } from "@codemirror/language";
3255
- import { StateField as StateField4 } from "@codemirror/state";
3256
- import { Decoration as Decoration5, EditorView as EditorView12, WidgetType as WidgetType3 } from "@codemirror/view";
3422
+ import { StateField as StateField5 } from "@codemirror/state";
3423
+ import { Decoration as Decoration6, EditorView as EditorView14, WidgetType as WidgetType4 } from "@codemirror/view";
3257
3424
  var image = (options = {}) => {
3258
- return StateField4.define({
3425
+ return StateField5.define({
3259
3426
  create: (state) => {
3260
- return Decoration5.set(buildDecorations2(0, state.doc.length, state));
3427
+ return Decoration6.set(buildDecorations2(0, state.doc.length, state));
3261
3428
  },
3262
3429
  update: (value, tr) => {
3263
3430
  if (!tr.docChanged && !tr.selection) {
@@ -3280,7 +3447,7 @@ var image = (options = {}) => {
3280
3447
  add: buildDecorations2(from, to, tr.state)
3281
3448
  });
3282
3449
  },
3283
- provide: (field) => EditorView12.decorations.from(field)
3450
+ provide: (field) => EditorView14.decorations.from(field)
3284
3451
  });
3285
3452
  };
3286
3453
  var preloaded = /* @__PURE__ */ new Set();
@@ -3302,7 +3469,7 @@ var buildDecorations2 = (from, to, state) => {
3302
3469
  const hide2 = state.readOnly || cursor < node.from || cursor > node.to;
3303
3470
  const url = state.sliceDoc(urlNode.from, urlNode.to);
3304
3471
  preloadImage(url);
3305
- decorations.push(Decoration5.replace({
3472
+ decorations.push(Decoration6.replace({
3306
3473
  block: true,
3307
3474
  widget: new ImageWidget(url)
3308
3475
  }).range(hide2 ? node.from : node.to, node.to));
@@ -3314,7 +3481,7 @@ var buildDecorations2 = (from, to, state) => {
3314
3481
  });
3315
3482
  return decorations;
3316
3483
  };
3317
- var ImageWidget = class extends WidgetType3 {
3484
+ var ImageWidget = class extends WidgetType4 {
3318
3485
  constructor(_url) {
3319
3486
  super();
3320
3487
  this._url = _url;
@@ -3367,17 +3534,17 @@ var linkTooltip = (render) => hoverTooltip2((view, pos, side) => {
3367
3534
 
3368
3535
  // packages/ui/react-ui-editor/src/extensions/markdown/table.ts
3369
3536
  import { syntaxTree as syntaxTree5 } from "@codemirror/language";
3370
- import { RangeSetBuilder as RangeSetBuilder2, StateField as StateField5 } from "@codemirror/state";
3371
- import { Decoration as Decoration6, EditorView as EditorView13, WidgetType as WidgetType4 } from "@codemirror/view";
3537
+ import { RangeSetBuilder as RangeSetBuilder3, StateField as StateField6 } from "@codemirror/state";
3538
+ import { Decoration as Decoration7, EditorView as EditorView15, WidgetType as WidgetType5 } from "@codemirror/view";
3372
3539
  var table = (options = {}) => {
3373
- return StateField5.define({
3540
+ return StateField6.define({
3374
3541
  create: (state) => update(state, options),
3375
3542
  update: (_, tr) => update(tr.state, options),
3376
- provide: (field) => EditorView13.decorations.from(field)
3543
+ provide: (field) => EditorView15.decorations.from(field)
3377
3544
  });
3378
3545
  };
3379
3546
  var update = (state, options) => {
3380
- const builder = new RangeSetBuilder2();
3547
+ const builder = new RangeSetBuilder3();
3381
3548
  const cursor = state.selection.main.head;
3382
3549
  const tables = [];
3383
3550
  const getTable = () => tables[tables.length - 1];
@@ -3417,16 +3584,16 @@ var update = (state, options) => {
3417
3584
  });
3418
3585
  tables.forEach((table2) => {
3419
3586
  const hide2 = state.readOnly || cursor < table2.from || cursor > table2.to;
3420
- hide2 && builder.add(table2.from, table2.to, Decoration6.replace({
3587
+ hide2 && builder.add(table2.from, table2.to, Decoration7.replace({
3421
3588
  widget: new TableWidget(table2)
3422
3589
  }));
3423
- builder.add(table2.from, table2.to, Decoration6.mark({
3590
+ builder.add(table2.from, table2.to, Decoration7.mark({
3424
3591
  class: "cm-table"
3425
3592
  }));
3426
3593
  });
3427
3594
  return builder.finish();
3428
3595
  };
3429
- var TableWidget = class extends WidgetType4 {
3596
+ var TableWidget = class extends WidgetType5 {
3430
3597
  constructor(_table) {
3431
3598
  super();
3432
3599
  this._table = _table;
@@ -3493,10 +3660,10 @@ var mention = ({ onSearch }) => {
3493
3660
  };
3494
3661
 
3495
3662
  // packages/ui/react-ui-editor/src/extensions/modes.ts
3496
- import { Facet as Facet5 } from "@codemirror/state";
3497
- import { keymap as keymap6 } from "@codemirror/view";
3663
+ import { Facet as Facet6 } from "@codemirror/state";
3664
+ import { keymap as keymap7 } from "@codemirror/view";
3498
3665
  import { vim } from "@replit/codemirror-vim";
3499
- var editorMode = Facet5.define({
3666
+ var editorMode = Facet6.define({
3500
3667
  combine: (modes) => modes[0] ?? {}
3501
3668
  });
3502
3669
  var EditorModes = {
@@ -3507,7 +3674,7 @@ var EditorModes = {
3507
3674
  type: "vim",
3508
3675
  noTabster: true
3509
3676
  }),
3510
- keymap6.of([
3677
+ keymap7.of([
3511
3678
  {
3512
3679
  key: "Alt-Escape",
3513
3680
  run: (view) => {
@@ -3527,7 +3694,7 @@ var outliner = (options = {}) => {
3527
3694
  };
3528
3695
 
3529
3696
  // packages/ui/react-ui-editor/src/extensions/typewriter.ts
3530
- import { keymap as keymap7 } from "@codemirror/view";
3697
+ import { keymap as keymap8 } from "@codemirror/view";
3531
3698
  var defaultItems = [
3532
3699
  "hello world!",
3533
3700
  "this is a test.",
@@ -3537,7 +3704,7 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
3537
3704
  let t;
3538
3705
  let idx = 0;
3539
3706
  return [
3540
- keymap7.of([
3707
+ keymap8.of([
3541
3708
  {
3542
3709
  // Reset.
3543
3710
  key: "alt-meta-'",
@@ -3583,172 +3750,356 @@ var typewriter = ({ delay = 75, items = defaultItems } = {}) => {
3583
3750
  ];
3584
3751
  };
3585
3752
 
3586
- // packages/ui/react-ui-editor/src/themes/default.ts
3587
- import get4 from "lodash.get";
3588
- var defaultTheme = {
3589
- //
3590
- // Main layout:
3591
- // https://codemirror.net/examples/styling
3592
- //
3593
- // <div class="cm-editor [cm-focused] [generated classes]">
3594
- // <div class="cm-scroller">
3595
- // <div class="cm-gutters">
3596
- // <div class="cm-gutter [...]">
3597
- // <div class="cm-gutterElement">...</div>
3598
- // </div>
3599
- // </div>
3600
- // <div class="cm-content" role="textbox" contenteditable="true">
3601
- // <div class="cm-line"></div>
3602
- // </div>
3603
- // <div class="cm-selectionLayer">
3604
- // <div class="cm-selectionBackground"></div>
3605
- // </div>
3606
- // <div class="cm-cursorLayer">
3607
- // <div class="cm-cursor"></div>
3608
- // </div>
3609
- // </div>
3610
- // </div>
3611
- //
3612
- "&": {},
3613
- "&.cm-focused": {
3614
- outline: "none"
3615
- },
3616
- // NOTE: See https://codemirror.net/docs/guide (DOM Structure).
3617
- ".cm-scroller": {
3618
- // TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
3619
- // 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.
3620
- overflowY: "auto",
3621
- fontFamily: get4(tokens, "fontFamily.mono", []).join(","),
3622
- lineHeight: 1.5
3623
- },
3624
- ".cm-content": {
3625
- // TODO(burdon): Is it possible to remove the padding value from CM's default theme?
3626
- // padding: 'unset',
3627
- // NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
3628
- fontSize: "16px"
3629
- },
3630
- "&light .cm-content": {
3631
- color: get4(tokens, "extend.semanticColors.base.fg.light", "black"),
3632
- caretColor: "black"
3633
- },
3634
- "&dark .cm-content": {
3635
- color: get4(tokens, "extend.semanticColors.base.fg.dark", "white"),
3636
- caretColor: "white"
3637
- },
3638
- //
3639
- // Cursor
3640
- //
3641
- "&light .cm-cursor, &light .cm-dropCursor": {
3642
- borderLeft: "2px solid black"
3643
- },
3644
- "&dark .cm-cursor, &dark .cm-dropCursor": {
3645
- borderLeft: "2px solid white"
3646
- },
3647
- "&light .cm-placeholder": {
3648
- color: get4(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
3649
- },
3650
- "&dark .cm-placeholder": {
3651
- color: get4(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
3652
- },
3653
- //
3654
- // line
3655
- //
3656
- ".cm-line": {
3657
- paddingInline: 0
3658
- },
3659
- ".cm-activeLine": {
3660
- background: "transparent"
3661
- },
3662
- //
3663
- // gutter
3664
- //
3665
- ".cm-gutterElement": {
3666
- width: "48px"
3667
- },
3668
- //
3669
- // Selection
3670
- //
3671
- "&light .cm-selectionBackground": {
3672
- background: get4(tokens, "extend.colors.primary.100")
3673
- },
3674
- "&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
3675
- background: get4(tokens, "extend.colors.primary.200")
3676
- },
3677
- "&dark .cm-selectionBackground": {
3678
- background: get4(tokens, "extend.colors.primary.700")
3679
- },
3680
- "&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
3681
- background: get4(tokens, "extend.colors.primary.600")
3682
- },
3683
- //
3684
- // Search
3685
- //
3686
- "&light .cm-searchMatch": {
3687
- backgroundColor: get4(tokens, "extend.colors.yellow.100")
3688
- },
3689
- "&dark .cm-searchMatch": {
3690
- backgroundColor: get4(tokens, "extend.colors.yellow.700")
3691
- },
3692
- //
3693
- // link
3694
- //
3695
- ".cm-link": {
3696
- color: get4(tokens, "extend.colors.primary.500"),
3697
- textDecorationLine: "underline",
3698
- textDecorationThickness: "1px",
3699
- textUnderlineOffset: "2px",
3700
- borderRadius: ".125rem",
3701
- fontFamily: get4(tokens, "fontFamily.body", []).join(",")
3702
- },
3703
- //
3704
- // tooltip
3705
- //
3706
- ".cm-tooltip": {
3707
- border: "none"
3708
- },
3709
- ".cm-tooltip-below": {},
3753
+ // packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
3754
+ import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
3755
+ import { Context as Context2 } from "@dxos/context";
3756
+ import { invariant as invariant2 } from "@dxos/invariant";
3757
+ import { log as log3 } from "@dxos/log";
3758
+ var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
3759
+ var DEBOUNCE_INTERVAL = 100;
3760
+ var SpaceAwarenessProvider = class {
3761
+ constructor(params) {
3762
+ this._remoteStates = /* @__PURE__ */ new Map();
3763
+ this.remoteStateChange = new Event2();
3764
+ this._space = params.space;
3765
+ this._channel = params.channel;
3766
+ this._peerId = params.peerId;
3767
+ this._info = params.info;
3768
+ }
3769
+ open() {
3770
+ this._ctx = new Context2();
3771
+ this._postTask = new DeferredTask(this._ctx, async () => {
3772
+ if (this._localState) {
3773
+ await this._space.postMessage(this._channel, {
3774
+ kind: "post",
3775
+ state: this._localState
3776
+ });
3777
+ await sleep(DEBOUNCE_INTERVAL);
3778
+ }
3779
+ });
3780
+ this._ctx.onDispose(this._space.listen(this._channel, (message) => {
3781
+ switch (message.payload.kind) {
3782
+ case "query": {
3783
+ this._handleQueryMessage();
3784
+ break;
3785
+ }
3786
+ case "post": {
3787
+ this._handlePostMessage(message.payload);
3788
+ break;
3789
+ }
3790
+ }
3791
+ }));
3792
+ void this._space.postMessage(this._channel, {
3793
+ kind: "query"
3794
+ }).catch((err) => {
3795
+ log3.debug("failed to query awareness", {
3796
+ err
3797
+ }, {
3798
+ F: __dxlog_file4,
3799
+ L: 89,
3800
+ S: this,
3801
+ C: (f, a) => f(...a)
3802
+ });
3803
+ });
3804
+ }
3805
+ close() {
3806
+ void this._ctx?.dispose();
3807
+ this._ctx = void 0;
3808
+ this._postTask = void 0;
3809
+ }
3810
+ getRemoteStates() {
3811
+ return Array.from(this._remoteStates.values());
3812
+ }
3813
+ update(position) {
3814
+ invariant2(this._postTask, void 0, {
3815
+ F: __dxlog_file4,
3816
+ L: 104,
3817
+ S: this,
3818
+ A: [
3819
+ "this._postTask",
3820
+ ""
3821
+ ]
3822
+ });
3823
+ this._localState = {
3824
+ peerId: this._peerId,
3825
+ position,
3826
+ info: this._info
3827
+ };
3828
+ this._postTask.schedule();
3829
+ }
3830
+ _handleQueryMessage() {
3831
+ invariant2(this._postTask, void 0, {
3832
+ F: __dxlog_file4,
3833
+ L: 115,
3834
+ S: this,
3835
+ A: [
3836
+ "this._postTask",
3837
+ ""
3838
+ ]
3839
+ });
3840
+ this._postTask.schedule();
3841
+ }
3842
+ _handlePostMessage(message) {
3843
+ invariant2(message.kind === "post", void 0, {
3844
+ F: __dxlog_file4,
3845
+ L: 120,
3846
+ S: this,
3847
+ A: [
3848
+ "message.kind === 'post'",
3849
+ ""
3850
+ ]
3851
+ });
3852
+ this._remoteStates.set(message.state.peerId, message.state);
3853
+ this.remoteStateChange.emit();
3854
+ }
3855
+ };
3856
+
3857
+ // packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
3858
+ var useActionHandler = (view) => {
3859
+ return (action) => {
3860
+ if (!view) {
3861
+ return;
3862
+ }
3863
+ let inlineType, listType;
3864
+ switch (action.type) {
3865
+ case "heading":
3866
+ setHeading(parseInt(action.data))(view);
3867
+ break;
3868
+ case "strong":
3869
+ case "emphasis":
3870
+ case "strikethrough":
3871
+ case "code":
3872
+ inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
3873
+ (typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
3874
+ break;
3875
+ case "list-ordered":
3876
+ case "list-bullet":
3877
+ case "list-task":
3878
+ listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
3879
+ (action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
3880
+ break;
3881
+ case "blockquote":
3882
+ (action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
3883
+ break;
3884
+ case "codeblock":
3885
+ (action.data === false ? removeCodeblock : addCodeblock)(view);
3886
+ break;
3887
+ case "table":
3888
+ insertTable(view);
3889
+ break;
3890
+ case "link":
3891
+ (action.data === false ? removeLink : addLink)(view);
3892
+ break;
3893
+ case "comment":
3894
+ createComment(view);
3895
+ break;
3896
+ }
3897
+ setTimeout(() => {
3898
+ if (!view.hasFocus) {
3899
+ view.focus();
3900
+ }
3901
+ });
3902
+ };
3903
+ };
3904
+
3905
+ // packages/ui/react-ui-editor/src/hooks/useEditorView.ts
3906
+ import { useRef, useState as useState2 } from "react";
3907
+ var useEditorView = (id) => {
3908
+ const editorRef = useRef(null);
3909
+ const [prev, setPrev] = useState2([
3910
+ null,
3911
+ ""
3912
+ ]);
3913
+ if (prev[0] !== editorRef.current) {
3914
+ setPrev([
3915
+ editorRef.current,
3916
+ id
3917
+ ]);
3918
+ }
3919
+ return [
3920
+ editorRef,
3921
+ prev[1] !== id
3922
+ ];
3923
+ };
3924
+
3925
+ // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
3926
+ import { closeBrackets as closeBrackets2 } from "@codemirror/autocomplete";
3927
+ import { history as history2 } from "@codemirror/commands";
3928
+ import { bracketMatching as bracketMatching2 } from "@codemirror/language";
3929
+ import { EditorSelection as EditorSelection2, EditorState as EditorState2 } from "@codemirror/state";
3930
+ import { crosshairCursor, drawSelection as drawSelection2, dropCursor as dropCursor2, EditorView as EditorView16, highlightActiveLine, lineNumbers, placeholder as placeholder2, scrollPastEnd } from "@codemirror/view";
3931
+ import defaultsDeep2 from "lodash.defaultsdeep";
3932
+ import { useEffect as useEffect2, useRef as useRef2, useState as useState3 } from "react";
3933
+ import { log as log4 } from "@dxos/log";
3934
+ import { isNotFalsy as isNotFalsy3 } from "@dxos/util";
3935
+
3936
+ // packages/ui/react-ui-editor/src/themes/default.ts
3937
+ import get4 from "lodash.get";
3938
+ var defaultTheme = {
3710
3939
  //
3711
- // autocomplete
3940
+ // Main layout:
3941
+ // https://codemirror.net/examples/styling
3712
3942
  //
3713
- ".cm-tooltip-autocomplete": {
3714
- marginTop: "4px",
3715
- marginLeft: "-3px"
3943
+ // <div class="cm-editor [cm-focused] [generated classes]">
3944
+ // <div class="cm-scroller">
3945
+ // <div class="cm-gutters">
3946
+ // <div class="cm-gutter [...]">
3947
+ // <div class="cm-gutterElement">...</div>
3948
+ // </div>
3949
+ // </div>
3950
+ // <div class="cm-content" role="textbox" contenteditable="true">
3951
+ // <div class="cm-line"></div>
3952
+ // </div>
3953
+ // <div class="cm-selectionLayer">
3954
+ // <div class="cm-selectionBackground"></div>
3955
+ // </div>
3956
+ // <div class="cm-cursorLayer">
3957
+ // <div class="cm-cursor"></div>
3958
+ // </div>
3959
+ // </div>
3960
+ // </div>
3961
+ //
3962
+ "&": {},
3963
+ "&.cm-focused": {
3964
+ outline: "none"
3716
3965
  },
3717
- ".cm-tooltip-autocomplete ul li": {},
3718
- ".cm-tooltip-autocomplete ul li[aria-selected]": {},
3719
- ".cm-completionIcon": {
3720
- display: "none"
3966
+ // NOTE: See https://codemirror.net/docs/guide (DOM Structure).
3967
+ ".cm-scroller": {
3968
+ // TODO(burdon): Reconcile with docs: https://codemirror.net/docs/guide
3969
+ // 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.
3970
+ overflowY: "auto",
3971
+ fontFamily: get4(tokens, "fontFamily.mono", []).join(","),
3972
+ lineHeight: 1.5
3721
3973
  },
3722
- ".cm-completionLabel": {
3723
- fontFamily: get4(tokens, "fontFamily.body", []).join(",")
3974
+ ".cm-content": {
3975
+ // TODO(burdon): Is it possible to remove the padding value from CM's default theme?
3976
+ // padding: 'unset',
3977
+ // NOTE: Base font size (otherwise defined by HTML tag, which might be different for storybook).
3978
+ fontSize: "16px"
3724
3979
  },
3725
- ".cm-completionMatchedText": {
3726
- textDecoration: "none"
3980
+ "&light .cm-content": {
3981
+ color: get4(tokens, "extend.semanticColors.base.fg.light", "black"),
3982
+ caretColor: "black"
3983
+ },
3984
+ "&dark .cm-content": {
3985
+ color: get4(tokens, "extend.semanticColors.base.fg.dark", "white"),
3986
+ caretColor: "white"
3727
3987
  },
3728
3988
  //
3729
- // table
3989
+ // Cursor
3730
3990
  //
3731
- ".cm-table *": {
3732
- fontFamily: `${get4(tokens, "fontFamily.mono", []).join(",")} !important`,
3733
- textDecoration: "none !important"
3991
+ "&light .cm-cursor, &light .cm-dropCursor": {
3992
+ borderLeft: "2px solid black"
3734
3993
  },
3735
- ".cm-table-head": {
3736
- padding: "2px 16px 2px 0px",
3737
- borderBottom: `1px solid ${get4(tokens, "extend.colors.neutral.500")}`,
3738
- fontWeight: 100,
3739
- textAlign: "left",
3740
- color: get4(tokens, "extend.colors.neutral.500")
3994
+ "&dark .cm-cursor, &dark .cm-dropCursor": {
3995
+ borderLeft: "2px solid white"
3741
3996
  },
3742
- ".cm-table-cell": {
3743
- padding: "2px 16px 2px 0px"
3997
+ "&light .cm-placeholder": {
3998
+ color: get4(tokens, "extend.semanticColors.description.light", "rgba(0,0,0,.2)")
3999
+ },
4000
+ "&dark .cm-placeholder": {
4001
+ color: get4(tokens, "extend.semanticColors.description.dark", "rgba(255,255,255,.2)")
3744
4002
  },
3745
4003
  //
3746
- // image
4004
+ // line
3747
4005
  //
3748
- ".cm-image": {
3749
- display: "block",
3750
- height: "0"
3751
- },
4006
+ ".cm-line": {
4007
+ paddingInline: 0
4008
+ },
4009
+ ".cm-activeLine": {
4010
+ background: "transparent"
4011
+ },
4012
+ //
4013
+ // gutter
4014
+ //
4015
+ ".cm-gutterElement": {
4016
+ width: "48px"
4017
+ },
4018
+ //
4019
+ // Selection
4020
+ //
4021
+ "&light .cm-selectionBackground": {
4022
+ background: get4(tokens, "extend.colors.primary.100")
4023
+ },
4024
+ "&light.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
4025
+ background: get4(tokens, "extend.colors.primary.200")
4026
+ },
4027
+ "&dark .cm-selectionBackground": {
4028
+ background: get4(tokens, "extend.colors.primary.700")
4029
+ },
4030
+ "&dark.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground": {
4031
+ background: get4(tokens, "extend.colors.primary.600")
4032
+ },
4033
+ //
4034
+ // Search
4035
+ //
4036
+ "&light .cm-searchMatch": {
4037
+ backgroundColor: get4(tokens, "extend.colors.yellow.100")
4038
+ },
4039
+ "&dark .cm-searchMatch": {
4040
+ backgroundColor: get4(tokens, "extend.colors.yellow.700")
4041
+ },
4042
+ //
4043
+ // link
4044
+ //
4045
+ ".cm-link": {
4046
+ color: get4(tokens, "extend.colors.primary.500"),
4047
+ textDecorationLine: "underline",
4048
+ textDecorationThickness: "1px",
4049
+ textUnderlineOffset: "2px",
4050
+ borderRadius: ".125rem",
4051
+ fontFamily: get4(tokens, "fontFamily.body", []).join(",")
4052
+ },
4053
+ //
4054
+ // tooltip
4055
+ //
4056
+ ".cm-tooltip": {
4057
+ border: "none",
4058
+ background: "unset"
4059
+ },
4060
+ ".cm-tooltip-below": {},
4061
+ //
4062
+ // autocomplete
4063
+ //
4064
+ ".cm-tooltip-autocomplete": {
4065
+ marginTop: "4px",
4066
+ marginLeft: "-3px"
4067
+ },
4068
+ ".cm-tooltip-autocomplete ul li": {},
4069
+ ".cm-tooltip-autocomplete ul li[aria-selected]": {},
4070
+ ".cm-completionIcon": {
4071
+ display: "none"
4072
+ },
4073
+ ".cm-completionLabel": {
4074
+ fontFamily: get4(tokens, "fontFamily.body", []).join(",")
4075
+ },
4076
+ ".cm-completionMatchedText": {
4077
+ textDecoration: "none"
4078
+ },
4079
+ //
4080
+ // table
4081
+ //
4082
+ ".cm-table *": {
4083
+ fontFamily: `${get4(tokens, "fontFamily.mono", []).join(",")} !important`,
4084
+ textDecoration: "none !important"
4085
+ },
4086
+ ".cm-table-head": {
4087
+ padding: "2px 16px 2px 0px",
4088
+ borderBottom: `1px solid ${get4(tokens, "extend.colors.neutral.500")}`,
4089
+ fontWeight: 100,
4090
+ textAlign: "left",
4091
+ color: get4(tokens, "extend.colors.neutral.500")
4092
+ },
4093
+ ".cm-table-cell": {
4094
+ padding: "2px 16px 2px 0px"
4095
+ },
4096
+ //
4097
+ // image
4098
+ //
4099
+ ".cm-image": {
4100
+ display: "block",
4101
+ height: "0"
4102
+ },
3752
4103
  ".cm-image.cm-loaded-image": {
3753
4104
  height: "auto",
3754
4105
  borderTop: "0.5rem solid transparent",
@@ -3833,19 +4184,238 @@ var codeTheme = {
3833
4184
  }
3834
4185
  };
3835
4186
 
4187
+ // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
4188
+ var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
4189
+ var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}, deps = []) => {
4190
+ const onUpdate = useRef2();
4191
+ const [view, setView] = useState3();
4192
+ const parentRef = useRef2(null);
4193
+ useEffect2(() => {
4194
+ let view2;
4195
+ if (parentRef.current) {
4196
+ const state = EditorState2.create({
4197
+ doc,
4198
+ selection,
4199
+ extensions: [
4200
+ // TODO(burdon): Doesn't catch errors in keymap functions.
4201
+ EditorView16.exceptionSink.of((err) => {
4202
+ log4.catch(err, void 0, {
4203
+ F: __dxlog_file5,
4204
+ L: 70,
4205
+ S: void 0,
4206
+ C: (f, a) => f(...a)
4207
+ });
4208
+ }),
4209
+ extensions,
4210
+ EditorView16.updateListener.of(() => {
4211
+ onUpdate.current?.();
4212
+ })
4213
+ ].filter(isNotFalsy3)
4214
+ });
4215
+ view2 = new EditorView16({
4216
+ parent: parentRef.current,
4217
+ scrollTo,
4218
+ state,
4219
+ // NOTE: Uncomment to debug/monitor all transactions.
4220
+ // https://codemirror.net/docs/ref/#view.EditorView.dispatch
4221
+ dispatchTransactions: (trs, view3) => {
4222
+ if (debug) {
4223
+ logChanges(trs);
4224
+ }
4225
+ view3.update(trs);
4226
+ }
4227
+ });
4228
+ setView(view2);
4229
+ }
4230
+ return () => {
4231
+ view2?.destroy();
4232
+ };
4233
+ }, deps);
4234
+ useEffect2(() => {
4235
+ if (view) {
4236
+ if (!selection && !view.state.selection.main.anchor) {
4237
+ selection = EditorSelection2.single(view.state.doc.line(1).to);
4238
+ }
4239
+ if (selection || scrollTo) {
4240
+ onUpdate.current = () => {
4241
+ onUpdate.current = void 0;
4242
+ view.dispatch({
4243
+ selection,
4244
+ effects: scrollTo && [
4245
+ scrollTo
4246
+ ],
4247
+ scrollIntoView: !scrollTo
4248
+ });
4249
+ };
4250
+ }
4251
+ if (autoFocus) {
4252
+ view.focus();
4253
+ }
4254
+ }
4255
+ }, [
4256
+ view,
4257
+ autoFocus,
4258
+ selection,
4259
+ scrollTo
4260
+ ]);
4261
+ return {
4262
+ parentRef,
4263
+ view
4264
+ };
4265
+ };
4266
+ var defaults = {
4267
+ bracketMatching: true,
4268
+ closeBrackets: true,
4269
+ drawSelection: true,
4270
+ editable: true,
4271
+ history: true,
4272
+ lineWrapping: true
4273
+ };
4274
+ var createBasicExtensions = (_props) => {
4275
+ const props = defaultsDeep2({}, _props, defaults);
4276
+ return [
4277
+ // TODO(burdon): Doesn't catch errors in keymap functions.
4278
+ EditorView16.exceptionSink.of((err) => {
4279
+ log4.catch(err, void 0, {
4280
+ F: __dxlog_file5,
4281
+ L: 167,
4282
+ S: void 0,
4283
+ C: (f, a) => f(...a)
4284
+ });
4285
+ }),
4286
+ props.allowMultipleSelections && EditorState2.allowMultipleSelections.of(true),
4287
+ props.bracketMatching && bracketMatching2(),
4288
+ props.closeBrackets && closeBrackets2(),
4289
+ props.crosshairCursor && crosshairCursor(),
4290
+ props.dropCursor && dropCursor2(),
4291
+ props.drawSelection && drawSelection2(),
4292
+ props.highlightActiveLine && highlightActiveLine(),
4293
+ props.history && history2(),
4294
+ props.lineNumbers && lineNumbers(),
4295
+ props.lineWrapping && EditorView16.lineWrapping,
4296
+ props.placeholder && placeholder2(props.placeholder),
4297
+ props.readonly && [
4298
+ EditorState2.readOnly.of(true),
4299
+ EditorView16.editable.of(false)
4300
+ ],
4301
+ props.scrollPastEnd && scrollPastEnd(),
4302
+ props.tabSize && EditorState2.tabSize.of(props.tabSize)
4303
+ ].filter(isNotFalsy3);
4304
+ };
4305
+ var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
4306
+ return [
4307
+ EditorView16.baseTheme(defaultTheme),
4308
+ EditorView16.darkTheme.of(themeMode === "dark"),
4309
+ theme && EditorView16.theme(theme),
4310
+ slots?.editor?.className && EditorView16.editorAttributes.of({
4311
+ class: slots.editor.className
4312
+ }),
4313
+ slots?.content?.className && EditorView16.contentAttributes.of({
4314
+ class: slots.content.className
4315
+ })
4316
+ ].filter(isNotFalsy3);
4317
+ };
4318
+
4319
+ // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
4320
+ import get5 from "lodash.get";
4321
+ import { useState as useState4, useMemo as useMemo2 } from "react";
4322
+ import { generateName } from "@dxos/display-name";
4323
+ import { getRawDoc } from "@dxos/echo-schema";
4324
+ import { invariant as invariant3 } from "@dxos/invariant";
4325
+ import { isAutomergeObject } from "@dxos/react-client/echo";
4326
+ import { hueTokens } from "@dxos/react-ui-theme";
4327
+ import { hexToHue } from "@dxos/util";
4328
+ var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
4329
+ var useTextExtensions = ({ id, text, space, identity }) => {
4330
+ const extensions = [
4331
+ automerge(text)
4332
+ ];
4333
+ const peerId = identity?.identityKey.toHex();
4334
+ const { cursorLightValue, cursorDarkValue } = hueTokens[hexToHue(peerId ?? "0")];
4335
+ if (space && identity) {
4336
+ const awarenessProvider2 = new SpaceAwarenessProvider({
4337
+ space,
4338
+ channel: `awareness.${id}`,
4339
+ peerId: identity.identityKey.toHex(),
4340
+ info: {
4341
+ displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
4342
+ color: cursorDarkValue,
4343
+ lightColor: cursorLightValue
4344
+ }
4345
+ });
4346
+ extensions.push(awareness(awarenessProvider2));
4347
+ }
4348
+ return extensions;
4349
+ };
4350
+ var useTextModel = (props) => useMemo2(() => createModel(props), Object.values(props));
4351
+ var useInMemoryTextModel = ({ id, defaultContent }) => {
4352
+ const [content, setContent] = useState4(defaultContent ?? "");
4353
+ return {
4354
+ id,
4355
+ content,
4356
+ text: () => content,
4357
+ setContent
4358
+ };
4359
+ };
4360
+ var createModel = ({ space, identity, text }) => {
4361
+ if (!text) {
4362
+ return void 0;
4363
+ }
4364
+ invariant3(isAutomergeObject(text), void 0, {
4365
+ F: __dxlog_file6,
4366
+ L: 88,
4367
+ S: void 0,
4368
+ A: [
4369
+ "isAutomergeObject(text)",
4370
+ ""
4371
+ ]
4372
+ });
4373
+ const obj = text;
4374
+ const doc = getRawDoc(obj, [
4375
+ obj.field
4376
+ ]);
4377
+ const peerId = identity?.identityKey.toHex();
4378
+ const { cursorLightValue, cursorDarkValue } = hueTokens[hexToHue(peerId ?? "0")];
4379
+ const awarenessProvider2 = space && new SpaceAwarenessProvider({
4380
+ space,
4381
+ channel: `automerge.awareness.${obj.id}`,
4382
+ info: {
4383
+ displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
4384
+ color: cursorLightValue,
4385
+ lightColor: cursorDarkValue
4386
+ },
4387
+ peerId: identity?.identityKey.toHex() ?? "Anonymous"
4388
+ });
4389
+ const extensions = [
4390
+ automerge({
4391
+ handle: doc.handle,
4392
+ path: doc.path
4393
+ })
4394
+ ];
4395
+ if (awarenessProvider2) {
4396
+ extensions.push(awareness(awarenessProvider2));
4397
+ }
4398
+ return {
4399
+ id: obj.id,
4400
+ content: doc,
4401
+ text: () => get5(doc.handle.docSync(), doc.path),
4402
+ extension: extensions
4403
+ };
4404
+ };
4405
+
3836
4406
  // packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx
3837
- var __dxlog_file4 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
3838
- var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo = EditorView14.scrollIntoView(0), moveToEndOfLine, selection, theme, slots = defaultSlots, extensions = [], scrollPastEnd: _scrollPastEnd, debug }, forwardedRef) => {
4407
+ var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/TextEditor.tsx";
4408
+ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, scrollTo = EditorView17.scrollIntoView(0), moveToEndOfLine, selection, theme, slots = defaultSlots, extensions = [], scrollPastEnd: _scrollPastEnd, debug }, forwardedRef) => {
3839
4409
  const tabsterDOMAttribute = useFocusableGroup({
3840
4410
  tabBehavior: "limited"
3841
4411
  });
3842
4412
  const { themeMode } = useThemeContext();
3843
- const rootRef = useRef(null);
3844
- const [view, setView] = useState2(null);
4413
+ const rootRef = useRef3(null);
4414
+ const [view, setView] = useState5(null);
3845
4415
  useImperativeHandle(forwardedRef, () => view, [
3846
4416
  view
3847
4417
  ]);
3848
- useEffect2(() => {
4418
+ useEffect3(() => {
3849
4419
  if (autoFocus) {
3850
4420
  view?.focus();
3851
4421
  }
@@ -3853,38 +4423,38 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3853
4423
  view,
3854
4424
  autoFocus
3855
4425
  ]);
3856
- useEffect2(() => {
4426
+ useEffect3(() => {
3857
4427
  if (!model || !rootRef.current) {
3858
4428
  return;
3859
4429
  }
3860
- const state = EditorState2.create({
3861
- doc: model.text(),
4430
+ const state = EditorState3.create({
4431
+ doc: typeof model.content === "string" ? model.content : DocAccessor.getValue(model.content),
3862
4432
  selection,
3863
4433
  extensions: [
3864
4434
  // TODO(burdon): Doesn't catch errors in keymap functions.
3865
- EditorView14.exceptionSink.of((err) => {
3866
- log3.catch(err, void 0, {
3867
- F: __dxlog_file4,
3868
- L: 122,
4435
+ EditorView17.exceptionSink.of((err) => {
4436
+ log5.catch(err, void 0, {
4437
+ F: __dxlog_file7,
4438
+ L: 123,
3869
4439
  S: void 0,
3870
4440
  C: (f, a) => f(...a)
3871
4441
  });
3872
4442
  }),
3873
4443
  // Theme.
3874
4444
  // TODO(burdon): Make base theme configurable.
3875
- EditorView14.baseTheme(defaultTheme),
3876
- theme && EditorView14.theme(theme),
3877
- EditorView14.darkTheme.of(themeMode === "dark"),
3878
- slots.editor?.className && EditorView14.editorAttributes.of({
4445
+ EditorView17.baseTheme(defaultTheme),
4446
+ theme && EditorView17.theme(theme),
4447
+ EditorView17.darkTheme.of(themeMode === "dark"),
4448
+ slots.editor?.className && EditorView17.editorAttributes.of({
3879
4449
  class: slots.editor.className
3880
4450
  }),
3881
- slots.content?.className && EditorView14.contentAttributes.of({
4451
+ slots.content?.className && EditorView17.contentAttributes.of({
3882
4452
  class: slots.content.className
3883
4453
  }),
3884
4454
  // NOTE: Assumes default line height.
3885
- _scrollPastEnd && scrollPastEnd(),
4455
+ _scrollPastEnd && scrollPastEnd2(),
3886
4456
  // Focus.
3887
- EditorView14.updateListener.of((update2) => {
4457
+ EditorView17.updateListener.of((update2) => {
3888
4458
  update2.transactions.forEach((transaction) => {
3889
4459
  if (transaction.isUserEvent("focus.container")) {
3890
4460
  rootRef.current?.focus();
@@ -3892,8 +4462,8 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3892
4462
  });
3893
4463
  }),
3894
4464
  // State.
3895
- EditorView14.editable.of(!readonly),
3896
- EditorState2.readOnly.of(!!readonly),
4465
+ EditorView17.editable.of(!readonly),
4466
+ EditorState3.readOnly.of(!!readonly),
3897
4467
  // Storage and replication.
3898
4468
  // NOTE: This must come before user extensions.
3899
4469
  model.extension,
@@ -3901,7 +4471,7 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3901
4471
  ...extensions
3902
4472
  ].filter(isNotFalsy4)
3903
4473
  });
3904
- const view2 = new EditorView14({
4474
+ const view2 = new EditorView17({
3905
4475
  state,
3906
4476
  parent: rootRef.current,
3907
4477
  scrollTo,
@@ -3958,14 +4528,16 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, readonly, autoFocus, s
3958
4528
  ...tabsterDOMAttribute
3959
4529
  });
3960
4530
  });
3961
- var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping, theme = textTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
4531
+ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, lineWrapping = true, theme = textTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
3962
4532
  const { themeMode } = useThemeContext();
3963
- const updatedSlots = defaultsDeep2({}, slots, defaultTextSlots);
3964
- const extensions = useMemo2(() => [
3965
- createBasicBundle({
3966
- themeMode,
3967
- placeholder: placeholder3,
3968
- lineWrapping
4533
+ const updatedSlots = defaultsDeep3({}, slots, defaultTextSlots);
4534
+ const extensions = useMemo3(() => [
4535
+ createBasicExtensions({
4536
+ lineWrapping,
4537
+ placeholder: placeholder3
4538
+ }),
4539
+ createThemeExtensions({
4540
+ themeMode
3969
4541
  }),
3970
4542
  ..._extensions ?? []
3971
4543
  ], [
@@ -3985,8 +4557,8 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholde
3985
4557
  });
3986
4558
  var MarkdownEditor = /* @__PURE__ */ forwardRef(({ readonly, placeholder: placeholder3, theme = markdownTheme, slots, extensions: _extensions, ...props }, forwardedRef) => {
3987
4559
  const { themeMode } = useThemeContext();
3988
- const updatedSlots = defaultsDeep2({}, slots, defaultMarkdownSlots);
3989
- const extensions = useMemo2(() => [
4560
+ const updatedSlots = defaultsDeep3({}, slots, defaultMarkdownSlots);
4561
+ const extensions = useMemo3(() => [
3990
4562
  createMarkdownExtensions({
3991
4563
  themeMode,
3992
4564
  placeholder: placeholder3
@@ -4024,7 +4596,7 @@ var defaultMarkdownSlots = {
4024
4596
  // packages/ui/react-ui-editor/src/components/Toolbar/Toolbar.tsx
4025
4597
  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";
4026
4598
  import { createContext } from "@radix-ui/react-context";
4027
- import React2, { useRef as useRef2, useState as useState3 } from "react";
4599
+ import React2, { useRef as useRef4, useState as useState6 } from "react";
4028
4600
  import { DensityProvider, ElevationProvider, Select, Toolbar as NaturalToolbar, Tooltip, useTranslation } from "@dxos/react-ui";
4029
4601
  import { getSize } from "@dxos/react-ui-theme";
4030
4602
  var tooltipProps = {
@@ -4082,9 +4654,9 @@ var MarkdownHeading = () => {
4082
4654
  const header = blockType && /heading(\d)/.exec(blockType);
4083
4655
  const value = header ? header[1] : blockType === "paragraph" || !blockType ? "0" : void 0;
4084
4656
  const HeadingIcon = HeadingIcons[value ?? "0"];
4085
- const suppressNextTooltip = useRef2(false);
4086
- const [tooltipOpen, setTooltipOpen] = useState3(false);
4087
- const [selectOpen, setSelectOpen] = useState3(false);
4657
+ const suppressNextTooltip = useRef4(false);
4658
+ const [tooltipOpen, setTooltipOpen] = useState6(false);
4659
+ const [selectOpen, setSelectOpen] = useState6(false);
4088
4660
  return /* @__PURE__ */ React2.createElement(Tooltip.Root, {
4089
4661
  open: tooltipOpen,
4090
4662
  onOpenChange: (nextOpen) => {
@@ -4287,378 +4859,6 @@ var Toolbar = {
4287
4859
  Markdown: MarkdownStandard,
4288
4860
  Extended: MarkdownExtended
4289
4861
  };
4290
-
4291
- // packages/ui/react-ui-editor/src/hooks/awareness-provider.ts
4292
- import { DeferredTask, Event as Event2, sleep } from "@dxos/async";
4293
- import { Context as Context2 } from "@dxos/context";
4294
- import { invariant as invariant2 } from "@dxos/invariant";
4295
- import { log as log4 } from "@dxos/log";
4296
- var __dxlog_file5 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/awareness-provider.ts";
4297
- var DEBOUNCE_INTERVAL = 100;
4298
- var SpaceAwarenessProvider = class {
4299
- constructor(params) {
4300
- this._remoteStates = /* @__PURE__ */ new Map();
4301
- this.remoteStateChange = new Event2();
4302
- this._space = params.space;
4303
- this._channel = params.channel;
4304
- this._peerId = params.peerId;
4305
- this._info = params.info;
4306
- }
4307
- open() {
4308
- this._ctx = new Context2();
4309
- this._postTask = new DeferredTask(this._ctx, async () => {
4310
- if (this._localState) {
4311
- await this._space.postMessage(this._channel, {
4312
- kind: "post",
4313
- state: this._localState
4314
- });
4315
- await sleep(DEBOUNCE_INTERVAL);
4316
- }
4317
- });
4318
- this._ctx.onDispose(this._space.listen(this._channel, (message) => {
4319
- switch (message.payload.kind) {
4320
- case "query": {
4321
- this._handleQueryMessage();
4322
- break;
4323
- }
4324
- case "post": {
4325
- this._handlePostMessage(message.payload);
4326
- break;
4327
- }
4328
- }
4329
- }));
4330
- void this._space.postMessage(this._channel, {
4331
- kind: "query"
4332
- }).catch((err) => {
4333
- log4.debug("failed to query awareness", {
4334
- err
4335
- }, {
4336
- F: __dxlog_file5,
4337
- L: 89,
4338
- S: this,
4339
- C: (f, a) => f(...a)
4340
- });
4341
- });
4342
- }
4343
- close() {
4344
- void this._ctx?.dispose();
4345
- this._ctx = void 0;
4346
- this._postTask = void 0;
4347
- }
4348
- getRemoteStates() {
4349
- return Array.from(this._remoteStates.values());
4350
- }
4351
- update(position) {
4352
- invariant2(this._postTask, void 0, {
4353
- F: __dxlog_file5,
4354
- L: 104,
4355
- S: this,
4356
- A: [
4357
- "this._postTask",
4358
- ""
4359
- ]
4360
- });
4361
- this._localState = {
4362
- peerId: this._peerId,
4363
- position,
4364
- info: this._info
4365
- };
4366
- this._postTask.schedule();
4367
- }
4368
- _handleQueryMessage() {
4369
- invariant2(this._postTask, void 0, {
4370
- F: __dxlog_file5,
4371
- L: 115,
4372
- S: this,
4373
- A: [
4374
- "this._postTask",
4375
- ""
4376
- ]
4377
- });
4378
- this._postTask.schedule();
4379
- }
4380
- _handlePostMessage(message) {
4381
- invariant2(message.kind === "post", void 0, {
4382
- F: __dxlog_file5,
4383
- L: 120,
4384
- S: this,
4385
- A: [
4386
- "message.kind === 'post'",
4387
- ""
4388
- ]
4389
- });
4390
- this._remoteStates.set(message.state.peerId, message.state);
4391
- this.remoteStateChange.emit();
4392
- }
4393
- };
4394
-
4395
- // packages/ui/react-ui-editor/src/hooks/defs.ts
4396
- import { StateField as StateField6 } from "@codemirror/state";
4397
- var modelState = StateField6.define({
4398
- create: () => void 0,
4399
- update: (model) => model
4400
- });
4401
-
4402
- // packages/ui/react-ui-editor/src/hooks/useActionHandler.ts
4403
- var useActionHandler = (view) => {
4404
- return (action) => {
4405
- if (!view) {
4406
- return;
4407
- }
4408
- let inlineType, listType;
4409
- switch (action.type) {
4410
- case "heading":
4411
- setHeading(parseInt(action.data))(view);
4412
- break;
4413
- case "strong":
4414
- case "emphasis":
4415
- case "strikethrough":
4416
- case "code":
4417
- inlineType = action.type === "strong" ? Inline.Strong : action.type === "emphasis" ? Inline.Emphasis : action.type === "strikethrough" ? Inline.Strikethrough : Inline.Code;
4418
- (typeof action.data === "boolean" ? setStyle(inlineType, action.data) : toggleStyle(inlineType))(view);
4419
- break;
4420
- case "list-ordered":
4421
- case "list-bullet":
4422
- case "list-task":
4423
- listType = action.type === "list-ordered" ? List.Ordered : action.type === "list-bullet" ? List.Bullet : List.Task;
4424
- (action.data === false ? removeList(listType) : action.data === true ? addList(listType) : toggleList(listType))(view);
4425
- break;
4426
- case "blockquote":
4427
- (action.data === false ? removeBlockquote : action.data === true ? addBlockquote : toggleBlockquote)(view);
4428
- break;
4429
- case "codeblock":
4430
- (action.data === false ? removeCodeblock : addCodeblock)(view);
4431
- break;
4432
- case "table":
4433
- insertTable(view);
4434
- break;
4435
- case "link":
4436
- (action.data === false ? removeLink : addLink)(view);
4437
- break;
4438
- case "comment":
4439
- createComment(view);
4440
- break;
4441
- }
4442
- setTimeout(() => {
4443
- if (!view.hasFocus) {
4444
- view.focus();
4445
- }
4446
- });
4447
- };
4448
- };
4449
-
4450
- // packages/ui/react-ui-editor/src/hooks/useEditorView.ts
4451
- import { useRef as useRef3, useState as useState4 } from "react";
4452
- var useEditorView = (id) => {
4453
- const editorRef = useRef3(null);
4454
- const [prev, setPrev] = useState4([
4455
- null,
4456
- ""
4457
- ]);
4458
- if (prev[0] !== editorRef.current) {
4459
- setPrev([
4460
- editorRef.current,
4461
- id
4462
- ]);
4463
- }
4464
- return [
4465
- editorRef,
4466
- prev[1] !== id
4467
- ];
4468
- };
4469
-
4470
- // packages/ui/react-ui-editor/src/hooks/useTextEditor.ts
4471
- import { EditorSelection as EditorSelection2, EditorState as EditorState3 } from "@codemirror/state";
4472
- import { EditorView as EditorView15 } from "@codemirror/view";
4473
- import { useEffect as useEffect3, useRef as useRef4, useState as useState5 } from "react";
4474
- import { log as log5 } from "@dxos/log";
4475
- import { isNotFalsy as isNotFalsy5 } from "@dxos/util";
4476
- var __dxlog_file6 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextEditor.ts";
4477
- var useTextEditor = ({ autoFocus, scrollTo, debug, doc, selection, extensions } = {}, deps) => {
4478
- const onUpdate = useRef4();
4479
- const [view, setView] = useState5();
4480
- const parentRef = useRef4(null);
4481
- useEffect3(() => {
4482
- let view2;
4483
- if (parentRef.current) {
4484
- const state = EditorState3.create({
4485
- doc,
4486
- selection,
4487
- extensions: [
4488
- // TODO(burdon): Doesn't catch errors in keymap functions.
4489
- EditorView15.exceptionSink.of((err) => {
4490
- log5.catch(err, void 0, {
4491
- F: __dxlog_file6,
4492
- L: 57,
4493
- S: void 0,
4494
- C: (f, a) => f(...a)
4495
- });
4496
- }),
4497
- extensions,
4498
- EditorView15.updateListener.of(() => {
4499
- onUpdate.current?.();
4500
- })
4501
- ].filter(isNotFalsy5)
4502
- });
4503
- view2 = new EditorView15({
4504
- parent: parentRef.current,
4505
- scrollTo,
4506
- state,
4507
- // NOTE: Uncomment to debug/monitor all transactions.
4508
- // https://codemirror.net/docs/ref/#view.EditorView.dispatch
4509
- dispatchTransactions: (trs, view3) => {
4510
- if (debug) {
4511
- logChanges(trs);
4512
- }
4513
- view3.update(trs);
4514
- }
4515
- });
4516
- setView(view2);
4517
- }
4518
- return () => {
4519
- view2?.destroy();
4520
- };
4521
- }, deps);
4522
- useEffect3(() => {
4523
- if (view) {
4524
- if (!selection && !view.state.selection.main.anchor) {
4525
- selection = EditorSelection2.single(view.state.doc.line(1).to);
4526
- }
4527
- if (selection || scrollTo) {
4528
- onUpdate.current = () => {
4529
- onUpdate.current = void 0;
4530
- view.dispatch({
4531
- selection,
4532
- effects: scrollTo && [
4533
- scrollTo
4534
- ],
4535
- scrollIntoView: !scrollTo
4536
- });
4537
- };
4538
- }
4539
- if (autoFocus) {
4540
- view.focus();
4541
- }
4542
- }
4543
- }, [
4544
- view,
4545
- autoFocus,
4546
- selection,
4547
- scrollTo
4548
- ]);
4549
- return {
4550
- parentRef,
4551
- view
4552
- };
4553
- };
4554
- var createDataExtensions = ({ readonly = false } = {}) => {
4555
- return [
4556
- //
4557
- EditorState3.readOnly.of(readonly),
4558
- EditorView15.editable.of(!readonly)
4559
- ];
4560
- };
4561
- var createThemeExtensions = ({ theme, themeMode, slots } = {}) => {
4562
- return [
4563
- //
4564
- EditorView15.baseTheme(defaultTheme),
4565
- theme && EditorView15.theme(theme),
4566
- EditorView15.darkTheme.of(themeMode === "dark"),
4567
- EditorView15.editorAttributes.of({
4568
- class: slots?.editor?.className ?? ""
4569
- }),
4570
- EditorView15.contentAttributes.of({
4571
- class: slots?.content?.className ?? ""
4572
- })
4573
- ].filter(isNotFalsy5);
4574
- };
4575
-
4576
- // packages/ui/react-ui-editor/src/hooks/useTextModel.ts
4577
- import get5 from "lodash.get";
4578
- import { useState as useState6, useMemo as useMemo3 } from "react";
4579
- import { generateName } from "@dxos/display-name";
4580
- import { getRawDoc } from "@dxos/echo-schema";
4581
- import { invariant as invariant3 } from "@dxos/invariant";
4582
- import { isAutomergeObject } from "@dxos/react-client/echo";
4583
- var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
4584
- var useTextExtensions = ({ id, text, space, identity }) => {
4585
- const extensions = [
4586
- automerge(text)
4587
- ];
4588
- if (space && identity) {
4589
- const awarenessProvider2 = new SpaceAwarenessProvider({
4590
- space,
4591
- channel: `awareness.${id}`,
4592
- peerId: identity.identityKey.toHex(),
4593
- info: {
4594
- displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
4595
- color: cursorColor.color,
4596
- lightColor: cursorColor.light
4597
- }
4598
- });
4599
- extensions.push(awareness(awarenessProvider2));
4600
- }
4601
- return extensions;
4602
- };
4603
- var useTextModel = (props) => useMemo3(() => createModel(props), Object.values(props));
4604
- var useInMemoryTextModel = ({ id, defaultContent }) => {
4605
- const [content, setContent] = useState6(defaultContent ?? "");
4606
- return {
4607
- id,
4608
- content,
4609
- setContent,
4610
- text: () => content
4611
- };
4612
- };
4613
- var createModel = ({ space, identity, text }) => {
4614
- if (!text) {
4615
- return void 0;
4616
- }
4617
- invariant3(isAutomergeObject(text), void 0, {
4618
- F: __dxlog_file7,
4619
- L: 83,
4620
- S: void 0,
4621
- A: [
4622
- "isAutomergeObject(text)",
4623
- ""
4624
- ]
4625
- });
4626
- const obj = text;
4627
- const doc = getRawDoc(obj, [
4628
- obj.field
4629
- ]);
4630
- const awarenessProvider2 = space && new SpaceAwarenessProvider({
4631
- space,
4632
- channel: `automerge.awareness.${obj.id}`,
4633
- info: {
4634
- displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
4635
- color: cursorColor.color,
4636
- lightColor: cursorColor.light
4637
- },
4638
- peerId: identity?.identityKey.toHex() ?? "Anonymous"
4639
- });
4640
- const extensions = [
4641
- modelState.init(() => model),
4642
- automerge({
4643
- handle: doc.handle,
4644
- path: doc.path
4645
- })
4646
- ];
4647
- if (awarenessProvider2) {
4648
- extensions.push(awareness(awarenessProvider2));
4649
- }
4650
- const model = {
4651
- id: obj.id,
4652
- content: doc,
4653
- text: () => get5(doc.handle.docSync(), doc.path),
4654
- extension: extensions,
4655
- peer: identity ? {
4656
- id: identity.identityKey.toHex(),
4657
- name: identity.profile?.displayName
4658
- } : void 0
4659
- };
4660
- return model;
4661
- };
4662
4862
  export {
4663
4863
  BaseTextEditor,
4664
4864
  Cursor,
@@ -4687,11 +4887,11 @@ export {
4687
4887
  blast,
4688
4888
  callbackWrapper,
4689
4889
  codeTheme,
4890
+ command,
4690
4891
  comments,
4691
4892
  compareFormatting,
4692
- createBasicBundle,
4893
+ createBasicExtensions,
4693
4894
  createComment,
4694
- createDataExtensions,
4695
4895
  createMarkdownExtensions,
4696
4896
  createThemeExtensions,
4697
4897
  cursorLineMargin,
@@ -4702,6 +4902,7 @@ export {
4702
4902
  defaultSlots,
4703
4903
  defaultTextSlots,
4704
4904
  defaultTheme,
4905
+ dnd,
4705
4906
  editorFillLayoutEditor,
4706
4907
  editorFillLayoutRoot,
4707
4908
  editorMode,
@@ -4712,7 +4913,7 @@ export {
4712
4913
  getToken,
4713
4914
  image,
4714
4915
  insertTable,
4715
- keymap8 as keymap,
4916
+ keymap9 as keymap,
4716
4917
  linkTooltip,
4717
4918
  listener,
4718
4919
  logChanges,
@@ -4721,7 +4922,6 @@ export {
4721
4922
  markdownTagsExtensions,
4722
4923
  markdownTheme,
4723
4924
  mention,
4724
- modelState,
4725
4925
  outliner,
4726
4926
  removeBlockquote,
4727
4927
  removeCodeblock,