@dxos/react-ui-editor 0.3.10-main.6ba804d → 0.3.10-main.74608f1

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 (46) hide show
  1. package/dist/lib/browser/index.mjs +126 -37
  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.map +1 -1
  5. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/extensions/comments.d.ts +10 -6
  7. package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/extensions/demo.d.ts +10 -0
  9. package/dist/types/src/components/TextEditor/extensions/demo.d.ts.map +1 -0
  10. package/dist/types/src/components/TextEditor/extensions/index.d.ts +1 -0
  11. package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -1
  12. package/dist/types/src/components/TextEditor/extensions/listener.d.ts +4 -2
  13. package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +1 -1
  14. package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -1
  15. package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts +3 -0
  16. package/dist/types/src/hooks/automerge/PatchSemaphore.d.ts.map +1 -1
  17. package/dist/types/src/hooks/automerge/automerge.stories.d.ts +8 -1
  18. package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -1
  19. package/dist/types/src/hooks/automerge/index.d.ts +1 -1
  20. package/dist/types/src/hooks/automerge/index.d.ts.map +1 -1
  21. package/dist/types/src/hooks/automerge/plugin.d.ts.map +1 -1
  22. package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts +5 -0
  23. package/dist/types/src/hooks/automerge/translation/automerge-to-codemirror.d.ts.map +1 -0
  24. package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts +6 -0
  25. package/dist/types/src/hooks/automerge/translation/codemirror-to-automerge.d.ts.map +1 -0
  26. package/dist/types/src/hooks/automerge/translation/index.d.ts +3 -0
  27. package/dist/types/src/hooks/automerge/translation/index.d.ts.map +1 -0
  28. package/package.json +20 -19
  29. package/src/components/TextEditor/MarkdownEditor.stories.tsx +4 -2
  30. package/src/components/TextEditor/TextEditor.tsx +18 -4
  31. package/src/components/TextEditor/extensions/comments.ts +48 -31
  32. package/src/components/TextEditor/extensions/demo.ts +66 -0
  33. package/src/components/TextEditor/extensions/index.ts +1 -0
  34. package/src/components/TextEditor/extensions/listener.ts +2 -2
  35. package/src/components/TextEditor/extensions/markdown/bundle.ts +9 -6
  36. package/src/hooks/automerge/PatchSemaphore.ts +12 -9
  37. package/src/hooks/automerge/automerge.stories.tsx +3 -2
  38. package/src/hooks/automerge/index.ts +1 -1
  39. package/src/hooks/automerge/plugin.ts +1 -0
  40. package/src/hooks/automerge/{amToCodemirror.ts → translation/automerge-to-codemirror.ts} +10 -2
  41. package/src/hooks/automerge/{codeMirrorToAm.ts → translation/codemirror-to-automerge.ts} +7 -4
  42. package/src/hooks/automerge/translation/index.ts +6 -0
  43. package/dist/types/src/hooks/automerge/amToCodemirror.d.ts +0 -6
  44. package/dist/types/src/hooks/automerge/amToCodemirror.d.ts.map +0 -1
  45. package/dist/types/src/hooks/automerge/codeMirrorToAm.d.ts +0 -7
  46. package/dist/types/src/hooks/automerge/codeMirrorToAm.d.ts.map +0 -1
@@ -54,8 +54,66 @@ var basicBundle = ({ themeMode, placeholder: _placeholder }) => [
54
54
  themeMode === "dark" ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle)
55
55
  ].filter(Boolean);
56
56
 
57
+ // packages/ui/react-ui-editor/src/components/TextEditor/extensions/demo.ts
58
+ import { keymap as keymap2 } from "@codemirror/view";
59
+ var defaultItems = [
60
+ "hello world!",
61
+ "this is a test.",
62
+ "this is [DXOS](https://dxos.org)"
63
+ ];
64
+ var demo = ({ delay = 75, items = defaultItems } = {}) => {
65
+ let t;
66
+ let idx = 0;
67
+ return [
68
+ keymap2.of([
69
+ {
70
+ // Reset.
71
+ key: "alt-meta-'",
72
+ run: (view) => {
73
+ clearTimeout(t);
74
+ idx = 0;
75
+ return true;
76
+ }
77
+ },
78
+ {
79
+ // Next prompt.
80
+ // TODO(burdon): Press 1-9 to select prompt?
81
+ key: "shift-meta-'",
82
+ run: (view) => {
83
+ clearTimeout(t);
84
+ const text = items[idx++];
85
+ if (idx === items?.length) {
86
+ idx = 0;
87
+ }
88
+ let i = 0;
89
+ const insert = (d = 0) => {
90
+ t = setTimeout(() => {
91
+ const pos = view.state.selection.main.head;
92
+ view.dispatch({
93
+ changes: {
94
+ from: pos,
95
+ insert: text[i++]
96
+ },
97
+ selection: {
98
+ anchor: pos + 1
99
+ }
100
+ });
101
+ if (i < text.length) {
102
+ insert(Math.random() * delay * (text[i] === " " ? 2 : 1));
103
+ }
104
+ }, d);
105
+ };
106
+ insert();
107
+ return true;
108
+ }
109
+ }
110
+ ])
111
+ ];
112
+ };
113
+
57
114
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts
58
- import { Decoration, EditorView as EditorView2, keymap as keymap2, MatchDecorator, ViewPlugin, WidgetType } from "@codemirror/view";
115
+ import { keymap as keymap3, Decoration, EditorView as EditorView2, MatchDecorator, ViewPlugin, WidgetType } from "@codemirror/view";
116
+ import { debounce } from "@dxos/async";
59
117
  import { invariant } from "@dxos/invariant";
60
118
  var __dxlog_file = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/components/TextEditor/extensions/comments.ts";
61
119
  var BookmarkWidget = class extends WidgetType {
@@ -65,7 +123,7 @@ var BookmarkWidget = class extends WidgetType {
65
123
  this._id = _id;
66
124
  invariant(this._id, void 0, {
67
125
  F: __dxlog_file,
68
- L: 40,
126
+ L: 41,
69
127
  S: this,
70
128
  A: [
71
129
  "this._id",
@@ -76,7 +134,6 @@ var BookmarkWidget = class extends WidgetType {
76
134
  eq(other) {
77
135
  return this._id === other._id;
78
136
  }
79
- // TODO(burdon): Click to select.
80
137
  toDOM() {
81
138
  const span = document.createElement("span");
82
139
  span.className = "cm-bookmark";
@@ -90,9 +147,13 @@ var styles = EditorView2.baseTheme({
90
147
  margin: "4px",
91
148
  padding: "4px",
92
149
  backgroundColor: "yellow"
150
+ },
151
+ "& .cm-bookmark-selected": {
152
+ backgroundColor: "orange"
93
153
  }
94
154
  });
95
155
  var comments = (options = {}) => {
156
+ let active;
96
157
  const bookmarkMatcher = new MatchDecorator({
97
158
  regexp: /\[\^(\w+)\]/g,
98
159
  decoration: (match, view, pos) => {
@@ -116,10 +177,13 @@ var comments = (options = {}) => {
116
177
  return view.plugin(plugin)?.bookmarks || Decoration.none;
117
178
  })
118
179
  });
180
+ const doUpdate = debounce((data) => {
181
+ options.onUpdate?.(data);
182
+ }, 200);
119
183
  return [
120
- keymap2.of([
184
+ keymap3.of([
121
185
  {
122
- key: options?.key ?? "alt-meta-c",
186
+ key: options?.key ?? "shift-meta-c",
123
187
  run: (view) => {
124
188
  const id = options.onCreate?.();
125
189
  if (id) {
@@ -143,30 +207,40 @@ var comments = (options = {}) => {
143
207
  bookmarks,
144
208
  // Monitor cursor movement.
145
209
  EditorView2.updateListener.of((update2) => {
210
+ active = void 0;
211
+ if (!options.onUpdate) {
212
+ return;
213
+ }
146
214
  const view = update2.view;
147
215
  const pos = view.state.selection.main.head;
148
216
  const decorations = [];
149
217
  const rangeSet = view.plugin(bookmarks)?.bookmarks;
150
- rangeSet?.between(pos, pos + 1, (from, to, value) => {
151
- if (value.spec.widget) {
152
- decorations.push({
153
- from,
154
- to,
155
- value
156
- });
218
+ let closest = Infinity;
219
+ const { from, to } = view.visibleRanges?.[0] ?? {
220
+ from: 0,
221
+ to: view.state.doc.length
222
+ };
223
+ rangeSet?.between(from, to, (from2, to2, value) => {
224
+ decorations.push({
225
+ from: from2,
226
+ to: to2,
227
+ value
228
+ });
229
+ const d = Math.min(Math.abs(pos - from2), Math.abs(pos - to2));
230
+ if (d < closest) {
231
+ active = value.spec.id;
232
+ closest = d;
157
233
  }
158
234
  });
159
235
  if (decorations.length) {
160
- const { from, value: { spec: { id } } } = decorations[0];
161
- const location = view.coordsAtPos(from);
162
- if (location) {
163
- options.onUpdate?.({
164
- items: decorations.map(({ value: { spec: { id: id2 } } }) => id2),
165
- active: id,
166
- pos,
167
- location
168
- });
169
- }
236
+ doUpdate({
237
+ active,
238
+ items: decorations.map(({ from: from2, value: { spec: { id } } }) => ({
239
+ id,
240
+ pos: from2,
241
+ location: view.coordsAtPos(from2)
242
+ }))
243
+ });
170
244
  }
171
245
  }),
172
246
  styles
@@ -262,7 +336,7 @@ var link = (options = {}) => {
262
336
 
263
337
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/listener.ts
264
338
  import { StateField as StateField2 } from "@codemirror/state";
265
- var listener = (onChange) => StateField2.define({
339
+ var listener = ({ onChange }) => StateField2.define({
266
340
  create: () => null,
267
341
  update: (_value, transaction) => {
268
342
  if (transaction.docChanged && onChange) {
@@ -274,14 +348,14 @@ var listener = (onChange) => StateField2.define({
274
348
 
275
349
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/bundle.ts
276
350
  import { closeBrackets as closeBrackets2, closeBracketsKeymap } from "@codemirror/autocomplete";
277
- import { defaultKeymap, history, indentWithTab } from "@codemirror/commands";
351
+ import { defaultKeymap, history, historyKeymap, indentWithTab } from "@codemirror/commands";
278
352
  import { markdownLanguage as markdownLanguage2, markdown } from "@codemirror/lang-markdown";
279
353
  import { bracketMatching as bracketMatching2, defaultHighlightStyle as defaultHighlightStyle2, indentOnInput, syntaxHighlighting as syntaxHighlighting2 } from "@codemirror/language";
280
354
  import { languages } from "@codemirror/language-data";
281
355
  import { highlightSelectionMatches, searchKeymap } from "@codemirror/search";
282
356
  import { EditorState } from "@codemirror/state";
283
357
  import { oneDarkHighlightStyle as oneDarkHighlightStyle2 } from "@codemirror/theme-one-dark";
284
- import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView4, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap as keymap3, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
358
+ import { crosshairCursor, drawSelection, dropCursor, EditorView as EditorView4, highlightActiveLine, highlightActiveLineGutter, highlightSpecialChars, keymap as keymap4, placeholder as placeholder2, rectangularSelection } from "@codemirror/view";
285
359
 
286
360
  // packages/ui/react-ui-editor/src/components/TextEditor/extensions/markdown/highlight.ts
287
361
  import { markdownLanguage } from "@codemirror/lang-markdown";
@@ -490,14 +564,17 @@ var markdownBundle = ({ themeMode, placeholder: _placeholder }) => {
490
564
  history(),
491
565
  indentOnInput(),
492
566
  rectangularSelection(),
493
- // TODO(burdon): Review.
494
- keymap3.of([
495
- ...closeBracketsKeymap,
567
+ // https://codemirror.net/docs/ref/#view.keymap
568
+ keymap4.of([
569
+ // https://codemirror.net/docs/ref/#commands.defaultKeymap
496
570
  ...defaultKeymap,
497
- // ...foldKeymap,
498
- // ...historyKeymap,
499
- // ...lintKeymap,
571
+ // https://codemirror.net/docs/ref/#commands.historyKeymap
572
+ ...historyKeymap,
573
+ // https://codemirror.net/docs/ref/#autocomplete.closeBracketsKeymap
574
+ ...closeBracketsKeymap,
575
+ // https://codemirror.net/docs/ref/#search.searchKeymap
500
576
  ...searchKeymap,
577
+ // https://codemirror.net/docs/ref/#commands.indentWithTab
501
578
  indentWithTab
502
579
  ]),
503
580
  // Main extension.
@@ -926,6 +1003,15 @@ var BaseTextEditor = /* @__PURE__ */ forwardRef(({ model, extensions = [], slots
926
1003
  onKeyUp: handleKeyUp
927
1004
  });
928
1005
  });
1006
+ var maybeDebug = () => {
1007
+ const items = localStorage.getItem("dxos.composer.demo");
1008
+ if (items) {
1009
+ return demo({
1010
+ items: items.split(",")
1011
+ });
1012
+ }
1013
+ return [];
1014
+ };
929
1015
  var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, ...props }, forwardedRef) => {
930
1016
  const { themeMode } = useThemeContext();
931
1017
  const slots = defaultsDeep({}, _slots, defaultTextSlots);
@@ -936,6 +1022,7 @@ var TextEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slots, .
936
1022
  themeMode,
937
1023
  placeholder: slots?.editor?.placeholder
938
1024
  }),
1025
+ maybeDebug(),
939
1026
  ...extensions
940
1027
  ],
941
1028
  slots,
@@ -952,6 +1039,7 @@ var MarkdownEditor = /* @__PURE__ */ forwardRef(({ extensions = [], slots: _slot
952
1039
  themeMode,
953
1040
  placeholder: slots?.editor?.placeholder
954
1041
  }),
1042
+ maybeDebug(),
955
1043
  ...extensions
956
1044
  ],
957
1045
  slots,
@@ -991,9 +1079,9 @@ import * as automerge2 from "@dxos/automerge/automerge";
991
1079
  // packages/ui/react-ui-editor/src/hooks/automerge/PatchSemaphore.ts
992
1080
  import { next as automerge } from "@dxos/automerge/automerge";
993
1081
 
994
- // packages/ui/react-ui-editor/src/hooks/automerge/amToCodemirror.ts
1082
+ // packages/ui/react-ui-editor/src/hooks/automerge/translation/automerge-to-codemirror.ts
995
1083
  import { ChangeSet } from "@codemirror/state";
996
- var amToCodemirror_default = (view, selection, target, patches) => {
1084
+ var automergeToCodemirror = (view, selection, target, patches) => {
997
1085
  for (const patch of patches) {
998
1086
  const changeSpec = handlePatch(patch, target, view.state);
999
1087
  if (changeSpec != null) {
@@ -1098,9 +1186,9 @@ var charPath = (textPath, candidatePath) => {
1098
1186
  return null;
1099
1187
  };
1100
1188
 
1101
- // packages/ui/react-ui-editor/src/hooks/automerge/codeMirrorToAm.ts
1189
+ // packages/ui/react-ui-editor/src/hooks/automerge/translation/codemirror-to-automerge.ts
1102
1190
  import { next as am } from "@dxos/automerge/automerge";
1103
- var codeMirrorToAm_default = (field, handle, transactions, state) => {
1191
+ var codemirrorToAutomerge = (field, handle, transactions, state) => {
1104
1192
  const { lastHeads, path } = state.field(field);
1105
1193
  let hasChanges = false;
1106
1194
  for (const tr of transactions) {
@@ -1144,12 +1232,12 @@ var PatchSemaphore = class {
1144
1232
  annotations: reconcileAnnotationType.of(true)
1145
1233
  });
1146
1234
  }
1147
- let newHeads = codeMirrorToAm_default(this._field, handle, transactions, view.state);
1235
+ let newHeads = codemirrorToAutomerge(this._field, handle, transactions, view.state);
1148
1236
  if (newHeads === null || newHeads === void 0) {
1149
1237
  newHeads = automerge.getHeads(handle.docSync());
1150
1238
  }
1151
1239
  const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync(), oldHeads, newHeads);
1152
- amToCodemirror_default(view, selection, path, diff);
1240
+ automergeToCodemirror(view, selection, path, diff);
1153
1241
  view.dispatch({
1154
1242
  effects: updateHeads(newHeads),
1155
1243
  annotations: reconcileAnnotationType.of({})
@@ -1465,6 +1553,7 @@ export {
1465
1553
  defaultSlots,
1466
1554
  defaultTextSlots,
1467
1555
  defaultTheme,
1556
+ demo,
1468
1557
  link,
1469
1558
  listener,
1470
1559
  markdownBundle,