@dxos/react-ui-editor 0.3.11-main.6f25445 → 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.
- package/dist/lib/browser/index.mjs +1430 -1335
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts +16 -13
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts +20 -17
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +6 -6
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/comments.stories.d.ts +26 -0
- package/dist/types/src/components/TextEditor/comments.stories.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts +9 -0
- package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +14 -0
- package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -0
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts +1 -1
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/defs.d.ts +7 -9
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/semaphore.d.ts +7 -12
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +2 -2
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -1
- package/dist/types/src/extensions/awareness.d.ts +1 -1
- package/dist/types/src/extensions/awareness.d.ts.map +1 -1
- package/dist/types/src/extensions/basic.d.ts +4 -5
- package/dist/types/src/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/extensions/comments.d.ts +37 -20
- package/dist/types/src/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/{util → extensions}/cursor.d.ts +10 -2
- package/dist/types/src/extensions/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +2 -8
- package/dist/types/src/extensions/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/bundle.d.ts +3 -6
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/code.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts +11 -0
- package/dist/types/src/extensions/markdown/formatting.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/heading.d.ts +6 -0
- package/dist/types/src/extensions/markdown/heading.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/hr.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/image.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/index.d.ts +8 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -1
- package/dist/types/src/extensions/markdown/link.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/table.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/tasklist.d.ts.map +1 -0
- package/dist/types/src/extensions/mention.d.ts.map +1 -1
- package/dist/types/src/extensions/outliner.d.ts +4 -0
- package/dist/types/src/extensions/outliner.d.ts.map +1 -0
- package/dist/types/src/hooks/awareness-provider.d.ts +7 -4
- package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -1
- package/dist/types/src/hooks/defs.d.ts +25 -0
- package/dist/types/src/hooks/defs.d.ts.map +1 -0
- package/dist/types/src/hooks/index.d.ts +3 -2
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useActionHandler.d.ts +4 -0
- package/dist/types/src/hooks/useActionHandler.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextEditor.d.ts +17 -0
- package/dist/types/src/hooks/useTextEditor.d.ts.map +1 -0
- package/dist/types/src/hooks/useTextModel.d.ts +2 -32
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts +2 -2
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/styles/tokens.d.ts +1 -0
- package/dist/types/src/styles/tokens.d.ts.map +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +7 -0
- package/dist/types/src/util.d.ts.map +1 -0
- package/package.json +34 -36
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +83 -89
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -46
- package/src/components/TextEditor/TextEditor.tsx +123 -93
- package/src/components/TextEditor/comments.stories.tsx +357 -0
- package/src/components/Toolbar/Toolbar.stories.tsx +86 -0
- package/src/components/Toolbar/Toolbar.tsx +115 -0
- package/src/extensions/autocomplete.ts +23 -19
- package/src/extensions/automerge/automerge.ts +40 -47
- package/src/extensions/automerge/cursor.ts +2 -1
- package/src/extensions/automerge/defs.ts +10 -31
- package/src/extensions/automerge/semaphore.ts +23 -20
- package/src/extensions/automerge/update-automerge.ts +14 -8
- package/src/extensions/awareness.ts +40 -46
- package/src/extensions/basic.ts +22 -17
- package/src/extensions/comments.ts +278 -267
- package/src/extensions/cursor.ts +50 -0
- package/src/extensions/index.ts +2 -8
- package/src/extensions/markdown/bundle.ts +20 -30
- package/src/extensions/markdown/code.ts +142 -0
- package/src/extensions/markdown/formatting.ts +159 -0
- package/src/extensions/markdown/heading.ts +59 -0
- package/src/extensions/markdown/highlight.ts +11 -26
- package/src/extensions/markdown/hr.ts +71 -0
- package/src/extensions/markdown/image.ts +87 -0
- package/src/extensions/markdown/index.ts +8 -0
- package/src/extensions/{link.ts → markdown/link.ts} +87 -86
- package/src/extensions/{table.ts → markdown/table.ts} +10 -4
- package/src/extensions/markdown/tasklist.ts +110 -0
- package/src/extensions/mention.ts +9 -2
- package/src/extensions/outliner.ts +12 -0
- package/src/hooks/awareness-provider.ts +24 -20
- package/src/hooks/defs.ts +42 -0
- package/src/hooks/index.ts +4 -2
- package/src/hooks/useActionHandler.ts +45 -0
- package/src/hooks/useTextEditor.ts +29 -0
- package/src/hooks/useTextModel.ts +48 -60
- package/src/index.ts +3 -0
- package/src/styles/markdown.ts +9 -12
- package/src/styles/tokens.ts +3 -0
- package/src/themes/default.ts +50 -79
- package/src/util.ts +41 -0
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/codemirror.stories.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts +0 -12
- package/dist/types/src/components/TextEditor/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/extensions/code.d.ts.map +0 -1
- package/dist/types/src/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/extensions/image.d.ts.map +0 -1
- package/dist/types/src/extensions/link.d.ts.map +0 -1
- package/dist/types/src/extensions/mermaid.d.ts +0 -3
- package/dist/types/src/extensions/mermaid.d.ts.map +0 -1
- package/dist/types/src/extensions/table.d.ts.map +0 -1
- package/dist/types/src/extensions/tasklist.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/cursor.d.ts +0 -4
- package/dist/types/src/extensions/yjs/cursor.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/index.d.ts +0 -2
- package/dist/types/src/extensions/yjs/index.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.d.ts +0 -4
- package/dist/types/src/extensions/yjs/yjs.d.ts.map +0 -1
- package/dist/types/src/extensions/yjs/yjs.test.d.ts +0 -2
- package/dist/types/src/extensions/yjs/yjs.test.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge.d.ts +0 -3
- package/dist/types/src/hooks/automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs.d.ts +0 -27
- package/dist/types/src/hooks/yjs.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -3
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/dist/types/src/testing/proto/gen/schema.d.ts +0 -15
- package/dist/types/src/testing/proto/gen/schema.d.ts.map +0 -1
- package/dist/types/src/testing/proto/index.d.ts +0 -2
- package/dist/types/src/testing/proto/index.d.ts.map +0 -1
- package/dist/types/src/testing/replicator.d.ts +0 -45
- package/dist/types/src/testing/replicator.d.ts.map +0 -1
- package/dist/types/src/util/cursor.d.ts.map +0 -1
- package/dist/types/src/util/index.d.ts +0 -3
- package/dist/types/src/util/index.d.ts.map +0 -1
- package/dist/types/src/util/util.d.ts +0 -5
- package/dist/types/src/util/util.d.ts.map +0 -1
- package/src/components/TextEditor/codemirror.stories.ts +0 -115
- package/src/components/TextEditor/yjs.stories.tsx +0 -56
- package/src/extensions/code.ts +0 -99
- package/src/extensions/hr.ts +0 -74
- package/src/extensions/image.ts +0 -69
- package/src/extensions/mermaid.ts +0 -11
- package/src/extensions/tasklist.ts +0 -121
- package/src/extensions/yjs/cursor.ts +0 -21
- package/src/extensions/yjs/index.ts +0 -5
- package/src/extensions/yjs/yjs.test.ts +0 -35
- package/src/extensions/yjs/yjs.ts +0 -16
- package/src/hooks/automerge.ts +0 -52
- package/src/hooks/yjs.ts +0 -178
- package/src/testing/index.ts +0 -6
- package/src/testing/proto/gen/schema.ts +0 -49
- package/src/testing/proto/index.ts +0 -5
- package/src/testing/proto/schema.proto +0 -15
- package/src/testing/replicator.ts +0 -184
- package/src/util/cursor.ts +0 -29
- package/src/util/index.ts +0 -6
- package/src/util/util.ts +0 -18
- /package/dist/types/src/extensions/{code.d.ts → markdown/code.d.ts} +0 -0
- /package/dist/types/src/extensions/{hr.d.ts → markdown/hr.d.ts} +0 -0
- /package/dist/types/src/extensions/{image.d.ts → markdown/image.d.ts} +0 -0
- /package/dist/types/src/extensions/{link.d.ts → markdown/link.d.ts} +0 -0
- /package/dist/types/src/extensions/{table.d.ts → markdown/table.d.ts} +0 -0
- /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 {
|
|
21
|
+
import { log } from '@dxos/log';
|
|
21
22
|
import { useThemeContext } from '@dxos/react-ui';
|
|
22
|
-
import {
|
|
23
|
+
import { attentionSurface, mx } from '@dxos/react-ui-theme';
|
|
23
24
|
|
|
24
|
-
import { basicBundle, markdownBundle
|
|
25
|
-
import { type
|
|
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,158 @@ 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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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<
|
|
71
|
-
(
|
|
72
|
-
|
|
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
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
>();
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
//
|
|
81
|
-
|
|
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
|
-
//
|
|
99
|
+
// Set focus.
|
|
93
100
|
useEffect(() => {
|
|
94
|
-
if (
|
|
95
|
-
view
|
|
96
|
-
effects: setCommentRange.of({ model, comments }),
|
|
97
|
-
});
|
|
101
|
+
if (autoFocus) {
|
|
102
|
+
view?.focus();
|
|
98
103
|
}
|
|
99
|
-
}, [view,
|
|
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 (!
|
|
109
|
+
if (!model || !rootRef.current) {
|
|
103
110
|
return;
|
|
104
111
|
}
|
|
105
112
|
|
|
106
|
-
//
|
|
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
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
|
127
|
+
// TODO(burdon): Make configurable.
|
|
118
128
|
EditorView.baseTheme(defaultTheme),
|
|
119
|
-
EditorView.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
|
+
EditorView.editable.of(!readonly),
|
|
136
|
+
EditorState.readOnly.of(!!readonly),
|
|
121
137
|
|
|
122
138
|
// Storage and replication.
|
|
139
|
+
// NOTE: This must come before user extensions.
|
|
123
140
|
model.extension,
|
|
124
141
|
|
|
142
|
+
// TODO(burdon): Factor out (requires special handling for Escape/focus).
|
|
143
|
+
editorMode === 'vim' && vim(),
|
|
144
|
+
|
|
125
145
|
// Custom.
|
|
126
146
|
...extensions,
|
|
127
147
|
].filter(Boolean) as Extension[],
|
|
128
148
|
});
|
|
129
149
|
|
|
130
|
-
//
|
|
131
|
-
//
|
|
132
|
-
//
|
|
133
|
-
|
|
134
|
-
|
|
150
|
+
//
|
|
151
|
+
// EditorView
|
|
152
|
+
// https://codemirror.net/docs/ref/#view.EditorViewConfig
|
|
153
|
+
//
|
|
154
|
+
const newView = new EditorView({
|
|
135
155
|
state,
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
156
|
+
parent: rootRef.current,
|
|
157
|
+
scrollTo,
|
|
158
|
+
// NOTE: Uncomment to debug/monitor all transactions.
|
|
159
|
+
// https://codemirror.net/docs/ref/#view.EditorView.dispatch
|
|
160
|
+
dispatchTransactions: (trs, view) => {
|
|
161
|
+
if (debug) {
|
|
162
|
+
logChanges(trs);
|
|
163
|
+
}
|
|
164
|
+
view.update(trs);
|
|
165
|
+
},
|
|
145
166
|
});
|
|
146
167
|
|
|
168
|
+
view?.destroy();
|
|
169
|
+
setView(newView);
|
|
170
|
+
|
|
147
171
|
return () => {
|
|
148
|
-
|
|
149
|
-
|
|
172
|
+
newView?.destroy();
|
|
173
|
+
setView(null);
|
|
150
174
|
};
|
|
151
|
-
}, [
|
|
175
|
+
}, [rootRef, model, readonly, editorMode, themeMode]);
|
|
152
176
|
|
|
177
|
+
// Handles tab/focus.
|
|
178
|
+
// Pressing Escape focuses the outer div (to support tab navigation); pressing Enter refocuses the editor.
|
|
153
179
|
const handleKeyUp = useCallback(
|
|
154
180
|
(event: KeyboardEvent) => {
|
|
155
181
|
const { key, altKey, shiftKey, metaKey, ctrlKey } = event;
|
|
156
182
|
switch (key) {
|
|
157
183
|
case 'Enter': {
|
|
158
|
-
view?.
|
|
184
|
+
view?.focus();
|
|
159
185
|
break;
|
|
160
186
|
}
|
|
161
187
|
|
|
162
188
|
case 'Escape': {
|
|
163
|
-
editorMode === 'vim' && (altKey || shiftKey || metaKey || ctrlKey)
|
|
189
|
+
if (editorMode === 'vim' && (altKey || shiftKey || metaKey || ctrlKey)) {
|
|
190
|
+
rootRef.current?.focus();
|
|
191
|
+
}
|
|
164
192
|
break;
|
|
165
193
|
}
|
|
166
194
|
}
|
|
@@ -171,42 +199,46 @@ export const BaseTextEditor = forwardRef<TextEditorRef, TextEditorProps>(
|
|
|
171
199
|
return (
|
|
172
200
|
<div
|
|
173
201
|
key={model.id}
|
|
174
|
-
|
|
202
|
+
role='none'
|
|
175
203
|
tabIndex={0}
|
|
176
|
-
{...slots?.root}
|
|
177
|
-
{...(editorMode !== 'vim' && tabsterDOMAttribute)}
|
|
178
204
|
onKeyUp={handleKeyUp}
|
|
205
|
+
{...slots.root}
|
|
206
|
+
{...(editorMode !== 'vim' && tabsterDOMAttribute)}
|
|
207
|
+
ref={rootRef}
|
|
179
208
|
/>
|
|
180
209
|
);
|
|
181
210
|
},
|
|
182
211
|
);
|
|
183
212
|
|
|
184
|
-
|
|
185
|
-
|
|
213
|
+
// TODO(burdon): Single-line/scroll.
|
|
214
|
+
export const TextEditor = forwardRef<EditorView, TextEditorProps>(
|
|
215
|
+
({ readonly, placeholder, lineWrapping, theme = textTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
186
216
|
const { themeMode } = useThemeContext();
|
|
187
|
-
const
|
|
217
|
+
const updatedSlots = defaultsDeep({}, slots, defaultTextSlots);
|
|
188
218
|
return (
|
|
189
219
|
<BaseTextEditor
|
|
190
220
|
ref={forwardedRef}
|
|
191
221
|
readonly={readonly}
|
|
192
|
-
extensions={[basicBundle({
|
|
193
|
-
|
|
222
|
+
extensions={[basicBundle({ themeMode, placeholder, lineWrapping }), ...extensions]}
|
|
223
|
+
theme={theme}
|
|
224
|
+
slots={updatedSlots}
|
|
194
225
|
{...props}
|
|
195
226
|
/>
|
|
196
227
|
);
|
|
197
228
|
},
|
|
198
229
|
);
|
|
199
230
|
|
|
200
|
-
export const MarkdownEditor = forwardRef<
|
|
201
|
-
({ readonly,
|
|
231
|
+
export const MarkdownEditor = forwardRef<EditorView, TextEditorProps>(
|
|
232
|
+
({ readonly, placeholder, theme = markdownTheme, slots, extensions = [], ...props }, forwardedRef) => {
|
|
202
233
|
const { themeMode } = useThemeContext();
|
|
203
|
-
const
|
|
234
|
+
const updatedSlots = defaultsDeep({}, slots, defaultMarkdownSlots);
|
|
204
235
|
return (
|
|
205
236
|
<BaseTextEditor
|
|
206
237
|
ref={forwardedRef}
|
|
207
238
|
readonly={readonly}
|
|
208
|
-
extensions={[markdownBundle({
|
|
209
|
-
|
|
239
|
+
extensions={[markdownBundle({ themeMode, placeholder }), ...extensions]}
|
|
240
|
+
theme={theme}
|
|
241
|
+
slots={updatedSlots}
|
|
210
242
|
{...props}
|
|
211
243
|
/>
|
|
212
244
|
);
|
|
@@ -215,20 +247,18 @@ export const MarkdownEditor = forwardRef<TextEditorRef, TextEditorProps>(
|
|
|
215
247
|
|
|
216
248
|
export const defaultSlots: TextEditorSlots = {
|
|
217
249
|
root: {
|
|
218
|
-
|
|
250
|
+
// TODO(burdon): Add focusRing by default/as property?
|
|
251
|
+
className: mx('flex flex-col grow overflow-y-auto', attentionSurface),
|
|
252
|
+
},
|
|
253
|
+
editor: {
|
|
254
|
+
className: 'h-full p-2',
|
|
219
255
|
},
|
|
220
256
|
};
|
|
221
257
|
|
|
222
258
|
export const defaultTextSlots: TextEditorSlots = {
|
|
223
259
|
...defaultSlots,
|
|
224
|
-
editor: {
|
|
225
|
-
theme: textTheme,
|
|
226
|
-
},
|
|
227
260
|
};
|
|
228
261
|
|
|
229
262
|
export const defaultMarkdownSlots: TextEditorSlots = {
|
|
230
263
|
...defaultSlots,
|
|
231
|
-
editor: {
|
|
232
|
-
theme: markdownTheme,
|
|
233
|
-
},
|
|
234
264
|
};
|