@dxos/react-ui-editor 0.3.11-main.6fccc32 → 0.3.11-main.73ee990

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 (160) hide show
  1. package/dist/lib/browser/index.mjs +1259 -1060
  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 +13 -14
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +14 -6
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +1 -1
  9. package/dist/types/src/components/TextEditor/comments.stories.d.ts +1 -1
  10. package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -1
  11. package/dist/types/src/components/Toolbar/Toolbar.d.ts +9 -0
  12. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
  13. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +14 -0
  14. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -0
  15. package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
  16. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
  17. package/dist/types/src/extensions/automerge/defs.d.ts +7 -9
  18. package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
  19. package/dist/types/src/extensions/automerge/index.d.ts +0 -1
  20. package/dist/types/src/extensions/automerge/index.d.ts.map +1 -1
  21. package/dist/types/src/extensions/automerge/semaphore.d.ts +7 -12
  22. package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
  23. package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -2
  24. package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
  25. package/dist/types/src/extensions/awareness.d.ts +1 -1
  26. package/dist/types/src/extensions/awareness.d.ts.map +1 -1
  27. package/dist/types/src/extensions/basic.d.ts +4 -5
  28. package/dist/types/src/extensions/basic.d.ts.map +1 -1
  29. package/dist/types/src/extensions/comments.d.ts +35 -18
  30. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  31. package/dist/types/src/extensions/cursor.d.ts +3 -3
  32. package/dist/types/src/extensions/cursor.d.ts.map +1 -1
  33. package/dist/types/src/extensions/index.d.ts +1 -7
  34. package/dist/types/src/extensions/index.d.ts.map +1 -1
  35. package/dist/types/src/extensions/markdown/bundle.d.ts +3 -6
  36. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  37. package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
  38. package/dist/types/src/extensions/markdown/formatting.d.ts +11 -0
  39. package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -0
  40. package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
  41. package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
  42. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  43. package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
  44. package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
  45. package/dist/types/src/extensions/markdown/index.d.ts +8 -0
  46. package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
  47. package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
  48. package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
  49. package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
  50. package/dist/types/src/extensions/mention.d.ts.map +1 -1
  51. package/dist/types/src/extensions/outliner.d.ts +4 -0
  52. package/dist/types/src/extensions/outliner.d.ts.map +1 -0
  53. package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
  54. package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
  55. package/dist/types/src/hooks/defs.d.ts +25 -0
  56. package/dist/types/src/hooks/defs.d.ts.map +1 -0
  57. package/dist/types/src/hooks/index.d.ts +3 -2
  58. package/dist/types/src/hooks/index.d.ts.map +1 -1
  59. package/dist/types/src/hooks/useActionHandler.d.ts +4 -0
  60. package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -0
  61. package/dist/types/src/hooks/useTextEditor.d.ts +17 -0
  62. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
  63. package/dist/types/src/hooks/useTextModel.d.ts +2 -27
  64. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  65. package/dist/types/src/styles/markdown.d.ts +2 -2
  66. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  67. package/dist/types/src/themes/default.d.ts.map +1 -1
  68. package/dist/types/src/util.d.ts +2 -0
  69. package/dist/types/src/util.d.ts.map +1 -1
  70. package/package.json +34 -37
  71. package/src/components/TextEditor/MarkdownEditor.stories.tsx +72 -80
  72. package/src/components/TextEditor/TextEditor.tsx +96 -70
  73. package/src/components/TextEditor/comments.stories.tsx +113 -71
  74. package/src/components/Toolbar/Toolbar.stories.tsx +86 -0
  75. package/src/components/Toolbar/Toolbar.tsx +115 -0
  76. package/src/extensions/autocomplete.ts +6 -3
  77. package/src/extensions/automerge/automerge.ts +39 -46
  78. package/src/extensions/automerge/defs.ts +10 -31
  79. package/src/extensions/automerge/index.ts +0 -1
  80. package/src/extensions/automerge/semaphore.ts +23 -20
  81. package/src/extensions/automerge/update-automerge.ts +14 -8
  82. package/src/extensions/awareness.ts +15 -14
  83. package/src/extensions/basic.ts +22 -17
  84. package/src/extensions/comments.ts +269 -162
  85. package/src/extensions/cursor.ts +7 -3
  86. package/src/extensions/index.ts +1 -7
  87. package/src/extensions/markdown/bundle.ts +20 -30
  88. package/src/extensions/markdown/code.ts +142 -0
  89. package/src/extensions/markdown/formatting.ts +159 -0
  90. package/src/extensions/markdown/heading.ts +59 -0
  91. package/src/extensions/markdown/highlight.ts +9 -15
  92. package/src/extensions/markdown/hr.ts +71 -0
  93. package/src/extensions/markdown/index.ts +8 -0
  94. package/src/extensions/{link.ts → markdown/link.ts} +8 -5
  95. package/src/extensions/markdown/tasklist.ts +110 -0
  96. package/src/extensions/mention.ts +9 -2
  97. package/src/extensions/outliner.ts +12 -0
  98. package/src/hooks/awareness-provider.ts +24 -20
  99. package/src/hooks/defs.ts +42 -0
  100. package/src/hooks/index.ts +4 -2
  101. package/src/hooks/useActionHandler.ts +45 -0
  102. package/src/hooks/useTextEditor.ts +29 -0
  103. package/src/hooks/useTextModel.ts +47 -56
  104. package/src/styles/markdown.ts +9 -10
  105. package/src/themes/default.ts +1 -11
  106. package/src/util.ts +26 -3
  107. package/dist/types/src/components/TextEditor/codemirror.stories.d.ts +0 -12
  108. package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
  109. package/dist/types/src/components/TextEditor/yjs.stories.d.ts +0 -12
  110. package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
  111. package/dist/types/src/extensions/code.d.ts.map +0 -1
  112. package/dist/types/src/extensions/hr.d.ts.map +0 -1
  113. package/dist/types/src/extensions/image.d.ts.map +0 -1
  114. package/dist/types/src/extensions/link.d.ts.map +0 -1
  115. package/dist/types/src/extensions/table.d.ts.map +0 -1
  116. package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
  117. package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
  118. package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
  119. package/dist/types/src/extensions/yjs/index.d.ts +0 -2
  120. package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
  121. package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
  122. package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
  123. package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
  124. package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
  125. package/dist/types/src/hooks/automerge.d.ts +0 -3
  126. package/dist/types/src/hooks/automerge.d.ts.map +0 -1
  127. package/dist/types/src/hooks/yjs.d.ts +0 -27
  128. package/dist/types/src/hooks/yjs.d.ts.map +0 -1
  129. package/dist/types/src/testing/index.d.ts +0 -3
  130. package/dist/types/src/testing/index.d.ts.map +0 -1
  131. package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
  132. package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
  133. package/dist/types/src/testing/proto/index.d.ts +0 -2
  134. package/dist/types/src/testing/proto/index.d.ts.map +0 -1
  135. package/dist/types/src/testing/replicator.d.ts +0 -45
  136. package/dist/types/src/testing/replicator.d.ts.map +0 -1
  137. package/src/components/TextEditor/codemirror.stories.ts +0 -115
  138. package/src/components/TextEditor/yjs.stories.tsx +0 -56
  139. package/src/extensions/code.ts +0 -106
  140. package/src/extensions/hr.ts +0 -73
  141. package/src/extensions/tasklist.ts +0 -119
  142. package/src/extensions/yjs/cursor.ts +0 -22
  143. package/src/extensions/yjs/index.ts +0 -5
  144. package/src/extensions/yjs/yjs.test.ts +0 -35
  145. package/src/extensions/yjs/yjs.ts +0 -16
  146. package/src/hooks/automerge.ts +0 -52
  147. package/src/hooks/yjs.ts +0 -156
  148. package/src/testing/index.ts +0 -6
  149. package/src/testing/proto/gen/schema.ts +0 -49
  150. package/src/testing/proto/index.ts +0 -5
  151. package/src/testing/proto/schema.proto +0 -15
  152. package/src/testing/replicator.ts +0 -184
  153. /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
  154. /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
  155. /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
  156. /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
  157. /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
  158. /package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
  159. /package/src/extensions/{image.ts → markdown/image.ts} +0 -0
  160. /package/src/extensions/{table.ts → markdown/table.ts} +0 -0
@@ -1,57 +1,36 @@
1
1
  //
2
2
  // Copyright 2023 DXOS.org
3
+ // Copyright 2024 Automerge
3
4
  // Ref: https://github.com/automerge/automerge-codemirror
4
5
  //
5
6
 
6
- import {
7
- Annotation,
8
- StateEffect,
9
- type StateField,
10
- type EditorState,
11
- type Transaction,
12
- type TransactionSpec,
13
- } from '@codemirror/state';
7
+ import { Annotation, StateEffect, type StateField, type EditorState, type Transaction } from '@codemirror/state';
14
8
 
15
9
  import { type ChangeFn, type ChangeOptions, type Doc, type Heads, type Prop } from '@dxos/automerge/automerge';
16
10
 
17
- export type Value = {
18
- lastHeads: Heads;
11
+ // TODO(burdon): Rename.
12
+ export type State = {
19
13
  path: Prop[];
14
+ lastHeads: Heads;
20
15
  unreconciledTransactions: Transaction[];
21
16
  };
22
17
 
23
- type UpdateHeads = {
18
+ export type UpdateHeads = {
24
19
  newHeads: Heads;
25
20
  };
26
21
 
27
22
  export const effectType = StateEffect.define<UpdateHeads>({});
28
23
 
29
- export const updateHeads = (newHeads: Heads): StateEffect<UpdateHeads> => effectType.of({ newHeads });
24
+ export const reconcileAnnotationType = Annotation.define<unknown>();
30
25
 
31
- export const getLastHeads = (state: EditorState, field: StateField<Value>): Heads => state.field(field).lastHeads;
26
+ export const getPath = (state: EditorState, field: StateField<State>): Prop[] => state.field(field).path;
32
27
 
33
- export const getPath = (state: EditorState, field: StateField<Value>): Prop[] => state.field(field).path;
28
+ export const getLastHeads = (state: EditorState, field: StateField<State>): Heads => state.field(field).lastHeads;
34
29
 
35
- export const reconcileAnnotationType = Annotation.define<unknown>();
30
+ export const updateHeads = (newHeads: Heads): StateEffect<UpdateHeads> => effectType.of({ newHeads });
36
31
 
37
32
  export const isReconcileTx = (tr: Transaction): boolean => !!tr.annotation(reconcileAnnotationType);
38
33
 
39
- export const makeReconcile = (tr: TransactionSpec) => {
40
- if (tr.annotations != null) {
41
- if (tr.annotations instanceof Array) {
42
- tr.annotations = [...tr.annotations, reconcileAnnotationType.of({})];
43
- } else {
44
- tr.annotations = [tr.annotations, reconcileAnnotationType.of({})];
45
- }
46
- } else {
47
- tr.annotations = [reconcileAnnotationType.of({})];
48
- }
49
- // return {
50
- // ...tr,
51
- // annotations: reconcileAnnotationType.of({})
52
- // }
53
- };
54
-
55
34
  export type IDocHandle<T = any> = {
56
35
  docSync(): Doc<T> | undefined;
57
36
  change(callback: ChangeFn<T>, options?: ChangeOptions<T>): void;
@@ -4,4 +4,3 @@
4
4
 
5
5
  export { automerge } from './automerge';
6
6
  export { type IDocHandle } from './defs';
7
- export { cursorConverter } from './cursor';
@@ -16,37 +16,38 @@ import {
16
16
  reconcileAnnotationType,
17
17
  updateHeads,
18
18
  type IDocHandle,
19
- type Value,
19
+ type State,
20
20
  } from './defs';
21
21
  import { updateAutomerge } from './update-automerge';
22
22
  import { updateCodeMirror } from './update-codemirror';
23
23
 
24
- type Doc<T> = automerge.Doc<T>;
25
- type Heads = automerge.Heads;
26
-
27
- type ChangeFn = (atHeads: Heads, change: (doc: Doc<unknown>) => void) => Heads | undefined;
28
-
29
24
  /**
30
- * TODO(burdon): Comment.
25
+ * Implements three-way merge (on each mutation/keystroke).
31
26
  */
32
27
  export class PatchSemaphore {
33
- _inReconcile = false;
34
- _queue: Array<ChangeFn> = [];
28
+ private _inReconcile = false;
35
29
 
36
- constructor(private readonly _field: StateField<Value>) {}
30
+ // prettier-ignore
31
+ constructor(
32
+ private readonly _handle: IDocHandle,
33
+ private readonly _state: StateField<State>
34
+ ) {}
37
35
 
38
- reconcile = (handle: IDocHandle, view: EditorView) => {
36
+ // NOTE: Cannot destruct view.state.
37
+ reconcile(view: EditorView) {
39
38
  if (this._inReconcile) {
40
39
  return;
41
40
  }
42
41
  this._inReconcile = true;
43
42
 
44
- const path = getPath(view.state, this._field);
45
- const oldHeads = getLastHeads(view.state, this._field);
43
+ const path = getPath(view.state, this._state);
44
+
45
+ // Get the heads before the unreconciled transactions are applied.
46
+ const oldHeads = getLastHeads(view.state, this._state);
46
47
  let selection = view.state.selection;
47
48
 
48
49
  // First undo all the unreconciled transactions.
49
- const transactions = view.state.field(this._field).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
50
+ const transactions = view.state.field(this._state).unreconciledTransactions.filter((tx) => !isReconcileTx(tx));
50
51
  const toInvert = transactions.slice().reverse();
51
52
  for (const tx of toInvert) {
52
53
  const inverted = tx.changes.invert(tx.startState.doc);
@@ -58,23 +59,25 @@ export class PatchSemaphore {
58
59
  }
59
60
 
60
61
  // Apply the unreconciled transactions to the document.
61
- let newHeads = updateAutomerge(this._field, handle, transactions, view.state);
62
-
63
62
  // NOTE: null and undefined each come from automerge and repo respectively.
63
+ let newHeads = updateAutomerge(this._state, this._handle, transactions, view.state);
64
64
  if (newHeads === null || newHeads === undefined) {
65
- // TODO: @alexjg this is the call that's resetting the editor state on click
66
- newHeads = automerge.getHeads(handle.docSync()!);
65
+ // TODO(alexjg): this is the call that's resetting the editor state on click.
66
+ newHeads = automerge.getHeads(this._handle.docSync()!);
67
67
  }
68
68
 
69
69
  // Now get the diff between the updated state of the document and the heads and apply that to the codemirror doc.
70
- const diff = automerge.equals(oldHeads, newHeads) ? [] : automerge.diff(handle.docSync()!, oldHeads, newHeads);
70
+ const diff = automerge.equals(oldHeads, newHeads)
71
+ ? []
72
+ : automerge.diff(this._handle.docSync()!, oldHeads, newHeads);
71
73
  updateCodeMirror(view, selection, path, diff);
72
74
 
75
+ // Update automerge state.
73
76
  view.dispatch({
74
77
  effects: updateHeads(newHeads),
75
78
  annotations: reconcileAnnotationType.of({}),
76
79
  });
77
80
 
78
81
  this._inReconcile = false;
79
- };
82
+ }
80
83
  }
@@ -4,17 +4,17 @@
4
4
  // Ref: https://github.com/automerge/automerge-codemirror
5
5
  //
6
6
 
7
- import { type EditorState, type StateField, type Text, type Transaction } from '@codemirror/state';
7
+ import { type EditorState, type StateField, type Transaction } from '@codemirror/state';
8
8
 
9
- import { next as am, type Heads } from '@dxos/automerge/automerge';
9
+ import { next as automerge, type Heads } from '@dxos/automerge/automerge';
10
10
 
11
- import { type IDocHandle, type Value } from './defs';
11
+ import { type IDocHandle, type State } from './defs';
12
12
 
13
13
  export const updateAutomerge = (
14
- field: StateField<Value>,
14
+ field: StateField<State>,
15
15
  handle: IDocHandle,
16
16
  transactions: Transaction[],
17
- state: EditorState,
17
+ state: EditorState, // TODO(burdon): Just pass in the state field value.
18
18
  ): Heads | undefined => {
19
19
  const { lastHeads, path } = state.field(field);
20
20
 
@@ -31,12 +31,18 @@ export const updateAutomerge = (
31
31
  return undefined;
32
32
  }
33
33
 
34
- const newHeads = handle.changeAt(lastHeads, (doc: am.Doc<unknown>) => {
34
+ const newHeads = handle.changeAt(lastHeads, (doc: automerge.Doc<unknown>) => {
35
+ const t: any[] = [];
35
36
  for (const tr of transactions) {
36
- tr.changes.iterChanges((fromA: number, toA: number, _fromB: number, _toB: number, inserted: Text) => {
37
- am.splice(doc, path, fromA, toA - fromA, inserted.toString());
37
+ tr.changes.iterChanges((fromA, toA, _fromB, _toB, insert) => {
38
+ t.push({ fromA, toA, insert });
38
39
  });
39
40
  }
41
+
42
+ // Apply in reverse order to properly apply range.
43
+ t.reverse().forEach(({ fromA, toA, insert }) => {
44
+ automerge.splice(doc, path.slice(), fromA, toA - fromA, insert.toString());
45
+ });
40
46
  });
41
47
 
42
48
  return newHeads ?? undefined;
@@ -24,8 +24,8 @@ export interface AwarenessProvider {
24
24
  open(): void;
25
25
  close(): void;
26
26
 
27
- update(position: AwarenessPosition | undefined): void;
28
27
  getRemoteStates(): AwarenessState[];
28
+ update(position: AwarenessPosition | undefined): void;
29
29
  }
30
30
 
31
31
  const dummyProvider: AwarenessProvider = {
@@ -34,8 +34,8 @@ const dummyProvider: AwarenessProvider = {
34
34
  open: () => {},
35
35
  close: () => {},
36
36
 
37
- update: () => {},
38
37
  getRemoteStates: () => [],
38
+ update: () => {},
39
39
  };
40
40
 
41
41
  export const AwarenessProvider = Facet.define<AwarenessProvider, AwarenessProvider>({
@@ -66,7 +66,6 @@ export type AwarenessState = {
66
66
  /**
67
67
  * Extension provides presence information about other peers.
68
68
  */
69
- // TODO(burdon): Why provide default?
70
69
  export const awareness = (provider = dummyProvider): Extension => {
71
70
  return [
72
71
  AwarenessProvider.of(provider),
@@ -265,39 +264,41 @@ const styles = EditorView.baseTheme({
265
264
  marginRight: '-1px',
266
265
  boxSizing: 'border-box',
267
266
  display: 'inline',
267
+ cursor: 'pointer',
268
268
  },
269
269
  '.cm-collab-selectionCaretDot': {
270
270
  borderRadius: '50%',
271
271
  position: 'absolute',
272
- width: '.4em',
273
- height: '.4em',
274
- top: '-.2em',
275
- left: '-.2em',
272
+ width: '.5em',
273
+ height: '.5em',
274
+ top: '-.25em',
275
+ left: '-.25em',
276
276
  backgroundColor: 'inherit',
277
277
  transition: 'transform .3s ease-in-out',
278
278
  boxSizing: 'border-box',
279
279
  },
280
280
  '.cm-collab-selectionCaret:hover > .cm-collab-selectionCaretDot': {
281
- transformOrigin: 'bottom center',
282
281
  transform: 'scale(0)',
282
+ transformOrigin: 'center',
283
283
  },
284
284
  '.cm-collab-selectionInfo': {
285
285
  position: 'absolute',
286
- top: '-1.05em',
287
- left: '-1px',
286
+ transform: 'translate(-50%, 0)',
287
+ top: '-20px',
288
+ left: 0,
288
289
  fontSize: '.75em',
289
- fontFamily: 'serif',
290
+ fontFamily: 'sans-serif',
290
291
  fontStyle: 'normal',
291
292
  fontWeight: 'normal',
292
293
  lineHeight: 'normal',
293
294
  userSelect: 'none',
294
295
  color: 'white',
295
- paddingLeft: '2px',
296
- paddingRight: '2px',
296
+ padding: '2px',
297
297
  zIndex: 101,
298
298
  transition: 'opacity .3s ease-in-out',
299
299
  backgroundColor: 'inherit',
300
- // these should be separate
300
+ borderRadius: '2px',
301
+ // These should be separate.
301
302
  opacity: 0,
302
303
  transitionDelay: '0s',
303
304
  whiteSpace: 'nowrap',
@@ -3,30 +3,35 @@
3
3
  //
4
4
 
5
5
  import { closeBrackets } from '@codemirror/autocomplete';
6
+ import { history } from '@codemirror/commands';
6
7
  import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
7
8
  import { type Extension } from '@codemirror/state';
8
9
  import { oneDarkHighlightStyle } from '@codemirror/theme-one-dark';
9
- import { drawSelection, EditorView, placeholder } from '@codemirror/view';
10
+ import { drawSelection, EditorView, highlightActiveLine, placeholder } from '@codemirror/view';
10
11
 
11
- import type { ThemeMode } from '@dxos/react-ui';
12
+ import { type ThemeMode } from '@dxos/react-ui';
13
+
14
+ import { type TextEditorProps } from '../components';
12
15
 
13
16
  export type BasicBundleOptions = {
14
- readonly?: boolean;
15
17
  themeMode?: ThemeMode;
16
- placeholder?: string;
17
- };
18
+ } & Pick<TextEditorProps, 'placeholder' | 'lineWrapping'>;
18
19
 
19
- export const basicBundle = ({ readonly, themeMode, placeholder: _placeholder }: BasicBundleOptions): Extension[] =>
20
- [
21
- EditorView.lineWrapping,
20
+ export const basicBundle = ({
21
+ themeMode,
22
+ placeholder: _placeholder,
23
+ lineWrapping = true,
24
+ }: BasicBundleOptions): Extension[] => [
25
+ lineWrapping ? EditorView.lineWrapping : [],
22
26
 
23
- // TODO(burdon): Compare with minimalSetup.
24
- // https://codemirror.net/docs/ref/#codemirror.minimalSetup
25
- bracketMatching(),
26
- closeBrackets(),
27
- drawSelection(),
28
- _placeholder && placeholder(_placeholder),
27
+ // https://codemirror.net/docs/ref/#codemirror.minimalSetup
28
+ bracketMatching(),
29
+ closeBrackets(),
30
+ drawSelection(),
31
+ highlightActiveLine(),
32
+ history(),
33
+ _placeholder ? placeholder(_placeholder) : [],
29
34
 
30
- // TODO(burdon): Is this required?
31
- themeMode === 'dark' ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
32
- ].filter(Boolean) as Extension[];
35
+ // https://github.com/codemirror/theme-one-dark
36
+ themeMode === 'dark' ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
37
+ ];