@dxos/react-ui-editor 0.3.11-main.4eab977 → 0.3.11-main.4faaf44

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 (163) hide show
  1. package/dist/lib/browser/index.mjs +1134 -1241
  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 +16 -13
  5. package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
  6. package/dist/types/src/components/TextEditor/TextEditor.d.ts +20 -17
  7. package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
  8. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +6 -6
  9. package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
  10. package/dist/types/src/components/TextEditor/comments.stories.d.ts +26 -0
  11. package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -0
  12. package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
  13. package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
  14. package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
  15. package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
  16. package/dist/types/src/extensions/automerge/defs.d.ts +7 -9
  17. package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
  18. package/dist/types/src/extensions/automerge/index.d.ts +0 -1
  19. package/dist/types/src/extensions/automerge/index.d.ts.map +1 -1
  20. package/dist/types/src/extensions/automerge/semaphore.d.ts +7 -12
  21. package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
  22. package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -2
  23. package/dist/types/src/extensions/awareness.d.ts +1 -1
  24. package/dist/types/src/extensions/awareness.d.ts.map +1 -1
  25. package/dist/types/src/extensions/basic.d.ts +4 -5
  26. package/dist/types/src/extensions/basic.d.ts.map +1 -1
  27. package/dist/types/src/extensions/comments.d.ts +32 -19
  28. package/dist/types/src/extensions/comments.d.ts.map +1 -1
  29. package/dist/types/src/{util → extensions}/cursor.d.ts +10 -2
  30. package/dist/types/src/extensions/cursor.d.ts.map +1 -0
  31. package/dist/types/src/extensions/index.d.ts +2 -7
  32. package/dist/types/src/extensions/index.d.ts.map +1 -1
  33. package/dist/types/src/extensions/markdown/bundle.d.ts +3 -6
  34. package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
  35. package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
  36. package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
  37. package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
  38. package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
  39. package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
  40. package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
  41. package/dist/types/src/extensions/markdown/index.d.ts +7 -0
  42. package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
  43. package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
  44. package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
  45. package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
  46. package/dist/types/src/extensions/mention.d.ts.map +1 -1
  47. package/dist/types/src/extensions/outliner.d.ts +4 -0
  48. package/dist/types/src/extensions/outliner.d.ts.map +1 -0
  49. package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
  50. package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
  51. package/dist/types/src/hooks/defs.d.ts +25 -0
  52. package/dist/types/src/hooks/defs.d.ts.map +1 -0
  53. package/dist/types/src/hooks/index.d.ts +2 -2
  54. package/dist/types/src/hooks/index.d.ts.map +1 -1
  55. package/dist/types/src/hooks/useTextEditor.d.ts +17 -0
  56. package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
  57. package/dist/types/src/hooks/useTextModel.d.ts +2 -32
  58. package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
  59. package/dist/types/src/index.d.ts +1 -0
  60. package/dist/types/src/index.d.ts.map +1 -1
  61. package/dist/types/src/styles/markdown.d.ts +2 -2
  62. package/dist/types/src/styles/markdown.d.ts.map +1 -1
  63. package/dist/types/src/themes/default.d.ts.map +1 -1
  64. package/dist/types/src/util.d.ts +7 -0
  65. package/dist/types/src/util.d.ts.map +1 -0
  66. package/package.json +34 -36
  67. package/src/components/TextEditor/MarkdownEditor.stories.tsx +82 -82
  68. package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
  69. package/src/components/TextEditor/TextEditor.tsx +122 -93
  70. package/src/components/TextEditor/comments.stories.tsx +357 -0
  71. package/src/extensions/autocomplete.ts +6 -3
  72. package/src/extensions/automerge/automerge.ts +40 -46
  73. package/src/extensions/automerge/cursor.ts +2 -1
  74. package/src/extensions/automerge/defs.ts +10 -31
  75. package/src/extensions/automerge/index.ts +0 -1
  76. package/src/extensions/automerge/semaphore.ts +23 -20
  77. package/src/extensions/automerge/update-automerge.ts +2 -2
  78. package/src/extensions/awareness.ts +40 -46
  79. package/src/extensions/basic.ts +22 -17
  80. package/src/extensions/comments.ts +246 -238
  81. package/src/extensions/cursor.ts +50 -0
  82. package/src/extensions/index.ts +2 -7
  83. package/src/extensions/markdown/bundle.ts +20 -30
  84. package/src/extensions/markdown/code.ts +127 -0
  85. package/src/extensions/markdown/heading.ts +59 -0
  86. package/src/extensions/markdown/highlight.ts +9 -23
  87. package/src/extensions/markdown/hr.ts +71 -0
  88. package/src/extensions/{image.ts → markdown/image.ts} +2 -2
  89. package/src/extensions/markdown/index.ts +7 -0
  90. package/src/extensions/{link.ts → markdown/link.ts} +8 -9
  91. package/src/extensions/{table.ts → markdown/table.ts} +2 -2
  92. package/src/extensions/markdown/tasklist.ts +110 -0
  93. package/src/extensions/mention.ts +9 -2
  94. package/src/extensions/outliner.ts +12 -0
  95. package/src/hooks/awareness-provider.ts +24 -20
  96. package/src/hooks/defs.ts +42 -0
  97. package/src/hooks/index.ts +3 -2
  98. package/src/hooks/useTextEditor.ts +29 -0
  99. package/src/hooks/useTextModel.ts +48 -60
  100. package/src/index.ts +1 -0
  101. package/src/styles/markdown.ts +9 -12
  102. package/src/themes/default.ts +15 -50
  103. package/src/util.ts +41 -0
  104. package/dist/types/src/components/TextEditor/codemirror.stories.d.ts +0 -12
  105. package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
  106. package/dist/types/src/components/TextEditor/yjs.stories.d.ts +0 -12
  107. package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
  108. package/dist/types/src/extensions/code.d.ts.map +0 -1
  109. package/dist/types/src/extensions/hr.d.ts.map +0 -1
  110. package/dist/types/src/extensions/image.d.ts.map +0 -1
  111. package/dist/types/src/extensions/link.d.ts.map +0 -1
  112. package/dist/types/src/extensions/table.d.ts.map +0 -1
  113. package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
  114. package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
  115. package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
  116. package/dist/types/src/extensions/yjs/index.d.ts +0 -2
  117. package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
  118. package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
  119. package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
  120. package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
  121. package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
  122. package/dist/types/src/hooks/automerge.d.ts +0 -3
  123. package/dist/types/src/hooks/automerge.d.ts.map +0 -1
  124. package/dist/types/src/hooks/yjs.d.ts +0 -27
  125. package/dist/types/src/hooks/yjs.d.ts.map +0 -1
  126. package/dist/types/src/testing/index.d.ts +0 -3
  127. package/dist/types/src/testing/index.d.ts.map +0 -1
  128. package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
  129. package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
  130. package/dist/types/src/testing/proto/index.d.ts +0 -2
  131. package/dist/types/src/testing/proto/index.d.ts.map +0 -1
  132. package/dist/types/src/testing/replicator.d.ts +0 -45
  133. package/dist/types/src/testing/replicator.d.ts.map +0 -1
  134. package/dist/types/src/util/cursor.d.ts.map +0 -1
  135. package/dist/types/src/util/index.d.ts +0 -3
  136. package/dist/types/src/util/index.d.ts.map +0 -1
  137. package/dist/types/src/util/util.d.ts +0 -5
  138. package/dist/types/src/util/util.d.ts.map +0 -1
  139. package/src/components/TextEditor/codemirror.stories.ts +0 -115
  140. package/src/components/TextEditor/yjs.stories.tsx +0 -56
  141. package/src/extensions/code.ts +0 -98
  142. package/src/extensions/hr.ts +0 -73
  143. package/src/extensions/tasklist.ts +0 -119
  144. package/src/extensions/yjs/cursor.ts +0 -21
  145. package/src/extensions/yjs/index.ts +0 -5
  146. package/src/extensions/yjs/yjs.test.ts +0 -35
  147. package/src/extensions/yjs/yjs.ts +0 -16
  148. package/src/hooks/automerge.ts +0 -52
  149. package/src/hooks/yjs.ts +0 -178
  150. package/src/testing/index.ts +0 -6
  151. package/src/testing/proto/gen/schema.ts +0 -49
  152. package/src/testing/proto/index.ts +0 -5
  153. package/src/testing/proto/schema.proto +0 -15
  154. package/src/testing/replicator.ts +0 -184
  155. package/src/util/cursor.ts +0 -29
  156. package/src/util/index.ts +0 -6
  157. package/src/util/util.ts +0 -18
  158. /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
  159. /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
  160. /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
  161. /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
  162. /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
  163. /package/dist/types/src/extensions/{tasklist.d.ts → markdown/tasklist.d.ts} +0 -0
@@ -2,7 +2,7 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
- import { EditorState, type Extension } from '@codemirror/state';
5
+ import { EditorState, type Extension, type StateEffect } from '@codemirror/state';
6
6
  import { EditorView } from '@codemirror/view';
7
7
  import { useFocusableGroup } from '@fluentui/react-tabster';
8
8
  import { vim } from '@replit/codemirror-vim';
@@ -14,18 +14,21 @@ import React, {
14
14
  useCallback,
15
15
  useEffect,
16
16
  useImperativeHandle,
17
+ useRef,
17
18
  useState,
18
19
  } from 'react';
19
20
 
20
- import { generateName } from '@dxos/display-name';
21
+ import { log } from '@dxos/log';
21
22
  import { useThemeContext } from '@dxos/react-ui';
22
- import { getColorForValue, inputSurface, mx } from '@dxos/react-ui-theme';
23
+ import { attentionSurface, mx } from '@dxos/react-ui-theme';
23
24
 
24
- import { basicBundle, markdownBundle, setCommentRange } from '../../extensions';
25
- import { type CommentRange, type EditorModel } from '../../hooks';
25
+ import { basicBundle, markdownBundle } from '../../extensions';
26
+ import { type EditorModel } from '../../hooks';
26
27
  import { type ThemeStyles } from '../../styles';
27
28
  import { defaultTheme, markdownTheme, textTheme } from '../../themes';
29
+ import { logChanges } from '../../util';
28
30
 
31
+ // TODO(burdon): Change to enum?
29
32
  export const EditorModes = ['default', 'vim'] as const;
30
33
  export type EditorMode = (typeof EditorModes)[number];
31
34
 
@@ -34,133 +37,157 @@ export type CursorInfo = {
34
37
  to: number;
35
38
  line: number;
36
39
  lines: number;
40
+ length: number;
37
41
  after?: string;
38
42
  };
39
43
 
40
- export type TextEditorRef = {
41
- root: HTMLDivElement | null;
42
- state?: EditorState;
43
- view?: EditorView;
44
- };
45
-
46
44
  export type TextEditorSlots = {
47
45
  root?: Omit<ComponentProps<'div'>, 'ref'>;
48
46
  editor?: {
49
47
  className?: string;
50
- placeholder?: string;
51
- spellCheck?: boolean;
52
- tabIndex?: number;
53
- theme?: ThemeStyles;
48
+ };
49
+ content?: {
50
+ className?: string;
54
51
  };
55
52
  };
56
53
 
54
+ // TODO(burdon): Spellcheck?
57
55
  export type TextEditorProps = {
58
- model: EditorModel;
56
+ model: EditorModel; // TODO(burdon): Optional (e.g., just provide content if readonly).
59
57
  readonly?: boolean; // TODO(burdon): Move into model.
60
- comments?: CommentRange[]; // TODO(burdon): Move into extension.
61
- extensions?: Extension[];
62
- editorMode?: EditorMode;
58
+ autoFocus?: boolean;
59
+ lineWrapping?: boolean;
60
+ scrollTo?: StateEffect<any>; // TODO(burdon): Restore scroll position: scrollTo EditorView.scrollSnapshot().
61
+ selection?: { anchor: number; head?: number };
62
+ editorMode?: EditorMode; // TODO(burdon): Factor out.
63
+ placeholder?: string;
64
+ theme?: ThemeStyles;
63
65
  slots?: TextEditorSlots;
66
+ extensions?: Extension[];
67
+ debug?: boolean;
64
68
  };
65
69
 
66
70
  /**
67
71
  * Base text editor.
68
- * NOTE: Rather than adding properties, try to create extensions that can be reused.
69
72
  */
70
- export const BaseTextEditor = forwardRef<TextEditorRef, TextEditorProps>(
71
- ({ model, readonly, comments, extensions = [], editorMode, slots = defaultSlots }, forwardedRef) => {
72
- const { themeMode } = useThemeContext();
73
+ export const BaseTextEditor = forwardRef<EditorView, TextEditorProps>(
74
+ (
75
+ {
76
+ model,
77
+ readonly,
78
+ autoFocus,
79
+ scrollTo,
80
+ selection,
81
+ editorMode,
82
+ theme,
83
+ slots = defaultSlots,
84
+ extensions = [],
85
+ debug,
86
+ },
87
+ forwardedRef,
88
+ ) => {
73
89
  const tabsterDOMAttribute = useFocusableGroup({ tabBehavior: 'limited' });
74
- const [root, setRoot] = useState<HTMLDivElement | null>(null);
75
- const [{ state = undefined, view = undefined } = {}, setEditor] = useState<
76
- { state?: EditorState; view?: EditorView } | undefined
77
- >();
78
- useImperativeHandle(forwardedRef, () => ({ root, state, view }), [view, state, root]);
79
-
80
- // TODO(burdon): Factor out as extension.
81
- const { awareness, peer } = model;
82
- useEffect(() => {
83
- if (awareness && peer) {
84
- awareness.setLocalStateField('user', {
85
- name: peer.name ?? generateName(peer.id),
86
- color: getColorForValue({ value: peer.id, type: 'color' }),
87
- colorLight: getColorForValue({ value: peer.id, themeMode, type: 'highlight' }),
88
- });
89
- }
90
- }, [awareness, peer, themeMode]);
90
+ const { themeMode } = useThemeContext();
91
+
92
+ const rootRef = useRef<HTMLDivElement>(null);
93
+ const [view, setView] = useState<EditorView | null>(null);
94
+
95
+ // The view ref can be used to focus the editor.
96
+ // NOTE: This does not cause the parent to re-render, so the ref is not available immediately.
97
+ useImperativeHandle<EditorView | null, EditorView | null>(forwardedRef, () => view, [view]);
91
98
 
92
- // TODO(burdon): Factor out as extension.
99
+ // Set focus.
93
100
  useEffect(() => {
94
- if (view && comments?.length) {
95
- view.dispatch({
96
- effects: setCommentRange.of({ model, comments }),
97
- });
101
+ if (autoFocus) {
102
+ view?.focus();
98
103
  }
99
- }, [view, comments]);
104
+ }, [view, autoFocus]);
100
105
 
106
+ // Create editor state and view.
107
+ // The view is recreated if the model or extensions are changed.
101
108
  useEffect(() => {
102
- if (!root) {
109
+ if (!model || !rootRef.current) {
103
110
  return;
104
111
  }
105
112
 
106
- // TODO(burdon): Remember cursor position.
113
+ //
114
+ // EditorState
107
115
  // https://codemirror.net/docs/ref/#state.EditorStateConfig
116
+ //
108
117
  const state = EditorState.create({
109
118
  doc: model.text(),
119
+ selection,
110
120
  extensions: [
111
- readonly && EditorState.readOnly.of(readonly),
112
-
113
- // TODO(burdon): Factor out VIM mode? (manage via MarkdownPlugin).
114
- editorMode === 'vim' && vim(),
121
+ // TODO(burdon): Doesn't catch errors in keymap functions.
122
+ EditorView.exceptionSink.of((err) => {
123
+ log.catch(err);
124
+ }),
115
125
 
116
126
  // Theme.
117
- // TODO(burdon): Make theme configurable.
127
+ // TODO(burdon): Make configurable.
118
128
  EditorView.baseTheme(defaultTheme),
119
- EditorView.theme(slots?.editor?.theme ?? {}),
129
+ EditorView.theme(theme ?? {}),
120
130
  EditorView.darkTheme.of(themeMode === 'dark'),
131
+ EditorView.editorAttributes.of({ class: slots.editor?.className ?? '' }),
132
+ EditorView.contentAttributes.of({ class: slots.content?.className ?? '' }),
133
+
134
+ // State.
135
+ EditorState.readOnly.of(!!readonly),
121
136
 
122
137
  // Storage and replication.
138
+ // NOTE: This must come before user extensions.
123
139
  model.extension,
124
140
 
141
+ // TODO(burdon): Factor out (requires special handling for Escape/focus).
142
+ editorMode === 'vim' && vim(),
143
+
125
144
  // Custom.
126
145
  ...extensions,
127
146
  ].filter(Boolean) as Extension[],
128
147
  });
129
148
 
130
- // NOTE: This repaints the editor.
131
- // If the new state is derived from the old state, it will likely not be visible other than the cursor resetting.
132
- // Ideally this should not happen except when changing between text objects.
133
- view?.destroy();
134
- setEditor({
149
+ //
150
+ // EditorView
151
+ // https://codemirror.net/docs/ref/#view.EditorViewConfig
152
+ //
153
+ const newView = new EditorView({
135
154
  state,
136
- view: new EditorView({
137
- state,
138
- parent: root,
139
- // NOTE: Uncomment to spy on all transactions.
140
- // https://codemirror.net/docs/ref/#view.EditorView.dispatch
141
- // dispatch: (transaction, view) => {
142
- // view.update([transaction]);
143
- // },
144
- }),
155
+ parent: rootRef.current,
156
+ scrollTo,
157
+ // NOTE: Uncomment to debug/monitor all transactions.
158
+ // https://codemirror.net/docs/ref/#view.EditorView.dispatch
159
+ dispatchTransactions: (trs, view) => {
160
+ if (debug) {
161
+ logChanges(trs);
162
+ }
163
+ view.update(trs);
164
+ },
145
165
  });
146
166
 
167
+ view?.destroy();
168
+ setView(newView);
169
+
147
170
  return () => {
148
- view?.destroy();
149
- setEditor(undefined);
171
+ newView?.destroy();
172
+ setView(null);
150
173
  };
151
- }, [root, model, readonly, editorMode, themeMode]);
174
+ }, [rootRef, model, readonly, editorMode, themeMode]);
152
175
 
176
+ // Handles tab/focus.
177
+ // Pressing Escape focuses the outer div (to support tab navigation); pressing Enter refocuses the editor.
153
178
  const handleKeyUp = useCallback(
154
179
  (event: KeyboardEvent) => {
155
180
  const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
156
181
  switch (key) {
157
182
  case 'Enter': {
158
- view?.contentDOM.focus();
183
+ view?.focus();
159
184
  break;
160
185
  }
161
186
 
162
187
  case 'Escape': {
163
- editorMode === 'vim' && (altKey || shiftKey || metaKey || ctrlKey) && root?.focus();
188
+ if (editorMode === 'vim' && (altKey || shiftKey || metaKey || ctrlKey)) {
189
+ rootRef.current?.focus();
190
+ }
164
191
  break;
165
192
  }
166
193
  }
@@ -171,42 +198,46 @@ export const BaseTextEditor = forwardRef<TextEditorRef, TextEditorProps>(
171
198
  return (
172
199
  <div
173
200
  key={model.id}
174
- ref={setRoot}
201
+ role='none'
175
202
  tabIndex={0}
176
- {...slots?.root}
177
- {...(editorMode !== 'vim' && tabsterDOMAttribute)}
178
203
  onKeyUp={handleKeyUp}
204
+ {...slots.root}
205
+ {...(editorMode !== 'vim' && tabsterDOMAttribute)}
206
+ ref={rootRef}
179
207
  />
180
208
  );
181
209
  },
182
210
  );
183
211
 
184
- export const TextEditor = forwardRef<TextEditorRef, TextEditorProps>(
185
- ({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
212
+ // TODO(burdon): Single-line/scroll.
213
+ export const TextEditor = forwardRef<EditorView, TextEditorProps>(
214
+ ({ readonly, placeholder, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
186
215
  const { themeMode } = useThemeContext();
187
- const slots = defaultsDeep({}, _slots, defaultTextSlots);
216
+ const updatedSlots = defaultsDeep({}, slots, defaultTextSlots);
188
217
  return (
189
218
  <BaseTextEditor
190
219
  ref={forwardedRef}
191
220
  readonly={readonly}
192
- extensions={[basicBundle({ readonly, themeMode, placeholder: slots?.editor?.placeholder }), ...extensions]}
193
- slots={slots}
221
+ extensions={[basicBundle({ themeMode, placeholder, lineWrapping }), ...extensions]}
222
+ theme={theme}
223
+ slots={updatedSlots}
194
224
  {...props}
195
225
  />
196
226
  );
197
227
  },
198
228
  );
199
229
 
200
- export const MarkdownEditor = forwardRef<TextEditorRef, TextEditorProps>(
201
- ({ readonly, extensions = [], slots: _slots, ...props }, forwardedRef) => {
230
+ export const MarkdownEditor = forwardRef<EditorView, TextEditorProps>(
231
+ ({ readonly, placeholder, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
202
232
  const { themeMode } = useThemeContext();
203
- const slots = defaultsDeep({}, _slots, defaultMarkdownSlots);
233
+ const updatedSlots = defaultsDeep({}, slots, defaultMarkdownSlots);
204
234
  return (
205
235
  <BaseTextEditor
206
236
  ref={forwardedRef}
207
237
  readonly={readonly}
208
- extensions={[markdownBundle({ readonly, themeMode, placeholder: slots?.editor?.placeholder }), ...extensions]}
209
- slots={slots}
238
+ extensions={[markdownBundle({ themeMode, placeholder }), ...extensions]}
239
+ theme={theme}
240
+ slots={updatedSlots}
210
241
  {...props}
211
242
  />
212
243
  );
@@ -215,20 +246,18 @@ export const MarkdownEditor = forwardRef<TextEditorRef, TextEditorProps>(
215
246
 
216
247
  export const defaultSlots: TextEditorSlots = {
217
248
  root: {
218
- className: mx('p-2', inputSurface),
249
+ // TODO(burdon): Add focusRing by default/as property?
250
+ className: mx('flex flex-col grow overflow-y-auto', attentionSurface),
251
+ },
252
+ editor: {
253
+ className: 'h-full p-2',
219
254
  },
220
255
  };
221
256
 
222
257
  export const defaultTextSlots: TextEditorSlots = {
223
258
  ...defaultSlots,
224
- editor: {
225
- theme: textTheme,
226
- },
227
259
  };
228
260
 
229
261
  export const defaultMarkdownSlots: TextEditorSlots = {
230
262
  ...defaultSlots,
231
- editor: {
232
- theme: markdownTheme,
233
- },
234
263
  };