@dxos/react-ui-editor 0.3.10-main.cbe7692 → 0.3.10-main.cc91b2d
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 +654 -412
- 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 +6 -3
- package/dist/types/src/components/TextEditor/MarkdownEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +3 -0
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/blast.d.ts +1 -1
- package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/code.d.ts +2 -0
- package/dist/types/src/components/TextEditor/extensions/code.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts +2 -2
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/experimental.d.ts +1 -1
- package/dist/types/src/components/TextEditor/extensions/experimental.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/highlight.d.ts +24 -0
- package/dist/types/src/components/TextEditor/extensions/highlight.d.ts.map +1 -0
- package/dist/types/src/components/TextEditor/extensions/index.d.ts +2 -0
- package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts +8 -0
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts +3 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/themes/default.d.ts.map +1 -1
- package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/useTextModel.d.ts +6 -0
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/hooks/yjs/yjs.stories.d.ts +1 -1
- package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +1 -1
- package/dist/types/src/styles/markdown.d.ts.map +1 -1
- package/dist/types/src/testing/replicator.d.ts.map +1 -1
- package/package.json +22 -20
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +51 -32
- package/src/components/TextEditor/TextEditor.stories.tsx +12 -1
- package/src/components/TextEditor/TextEditor.tsx +21 -23
- package/src/components/TextEditor/extensions/basic.ts +4 -3
- package/src/components/TextEditor/extensions/blast.ts +27 -29
- package/src/components/TextEditor/extensions/code.ts +99 -0
- package/src/components/TextEditor/extensions/comments.ts +29 -46
- package/src/components/TextEditor/extensions/experimental.tsx +15 -36
- package/src/components/TextEditor/extensions/highlight.ts +128 -0
- package/src/components/TextEditor/extensions/image.ts +4 -5
- package/src/components/TextEditor/extensions/index.ts +2 -0
- package/src/components/TextEditor/extensions/link.ts +2 -2
- package/src/components/TextEditor/extensions/markdown/bundle.ts +35 -32
- package/src/components/TextEditor/extensions/markdown/highlight.ts +37 -11
- package/src/components/TextEditor/extensions/table.ts +44 -48
- package/src/components/TextEditor/extensions/tasklist.ts +9 -9
- package/src/components/TextEditor/themes/default.ts +43 -2
- package/src/hooks/automerge/automerge.stories.tsx +1 -0
- package/src/hooks/useTextModel.ts +9 -0
- package/src/hooks/yjs/yjs.stories.tsx +1 -1
- package/src/styles/markdown.ts +5 -4
- package/src/testing/replicator.ts +1 -0
|
@@ -25,61 +25,57 @@ export const table = (options: TableOptions = {}) => {
|
|
|
25
25
|
|
|
26
26
|
type Table = {
|
|
27
27
|
from: number;
|
|
28
|
-
to
|
|
28
|
+
to: number;
|
|
29
29
|
header?: string[];
|
|
30
30
|
rows?: string[][];
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
const update = (state: EditorState, options: TableOptions) => {
|
|
34
34
|
const builder = new RangeSetBuilder();
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
getTable().header?.push(state.sliceDoc(node.from, node.to));
|
|
68
|
-
}
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
case 'TableDelimiter': {
|
|
72
|
-
getTable().to = node.to;
|
|
73
|
-
break;
|
|
35
|
+
const cursor = state.selection.main.head;
|
|
36
|
+
|
|
37
|
+
const tables: Table[] = [];
|
|
38
|
+
const getTable = () => tables[tables.length - 1];
|
|
39
|
+
const getRow = () => {
|
|
40
|
+
const table = getTable();
|
|
41
|
+
return table.rows?.[table.rows.length - 1];
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Parse table.
|
|
45
|
+
syntaxTree(state).iterate({
|
|
46
|
+
enter: (node) => {
|
|
47
|
+
// Check if cursor is inside text.
|
|
48
|
+
switch (node.name) {
|
|
49
|
+
case 'Table': {
|
|
50
|
+
tables.push({ from: node.from, to: node.to });
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
case 'TableHeader': {
|
|
54
|
+
getTable().header = [];
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
case 'TableRow': {
|
|
58
|
+
(getTable().rows ??= []).push([]);
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
case 'TableCell': {
|
|
62
|
+
const row = getRow();
|
|
63
|
+
if (row) {
|
|
64
|
+
row.push(state.sliceDoc(node.from, node.to));
|
|
65
|
+
} else {
|
|
66
|
+
getTable().header?.push(state.sliceDoc(node.from, node.to));
|
|
74
67
|
}
|
|
68
|
+
break;
|
|
75
69
|
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
});
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
);
|
|
82
|
-
|
|
74
|
+
tables.forEach((table) => {
|
|
75
|
+
const hide = state.readOnly || cursor < table.from || cursor > table.to;
|
|
76
|
+
hide && builder.add(table.from, table.to, Decoration.replace({ widget: new TableWidget(table) }));
|
|
77
|
+
builder.add(table.from, table.to, Decoration.mark({ class: 'cm-table' }));
|
|
78
|
+
});
|
|
83
79
|
|
|
84
80
|
return builder.finish();
|
|
85
81
|
};
|
|
@@ -98,11 +94,11 @@ class TableWidget extends WidgetType {
|
|
|
98
94
|
|
|
99
95
|
{
|
|
100
96
|
const header = table.appendChild(document.createElement('thead'));
|
|
101
|
-
const
|
|
97
|
+
const tr = header.appendChild(document.createElement('tr'));
|
|
102
98
|
this._table.header?.forEach((cell) => {
|
|
103
99
|
const th = document.createElement('th');
|
|
104
100
|
th.setAttribute('class', 'cm-table-head');
|
|
105
|
-
|
|
101
|
+
tr.appendChild(th).textContent = cell;
|
|
106
102
|
});
|
|
107
103
|
}
|
|
108
104
|
|
|
@@ -12,6 +12,14 @@ import {
|
|
|
12
12
|
type ViewUpdate,
|
|
13
13
|
} from '@codemirror/view';
|
|
14
14
|
|
|
15
|
+
// TODO(burdon): Reconcile with theme.
|
|
16
|
+
const styles = EditorView.baseTheme({
|
|
17
|
+
'& .cm-task-item': {
|
|
18
|
+
paddingLeft: '4px',
|
|
19
|
+
paddingRight: '8px',
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
15
23
|
class CheckboxWidget extends WidgetType {
|
|
16
24
|
constructor(
|
|
17
25
|
private readonly _pos: number,
|
|
@@ -53,14 +61,6 @@ class CheckboxWidget extends WidgetType {
|
|
|
53
61
|
}
|
|
54
62
|
}
|
|
55
63
|
|
|
56
|
-
// TODO(burdon): Reconcile with theme.
|
|
57
|
-
const styles = EditorView.baseTheme({
|
|
58
|
-
'& .cm-task-item': {
|
|
59
|
-
paddingLeft: '4px',
|
|
60
|
-
paddingRight: '8px',
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
|
|
64
64
|
export type TasklistOptions = {};
|
|
65
65
|
|
|
66
66
|
export const tasklist = (options: TasklistOptions = {}) => {
|
|
@@ -109,7 +109,7 @@ export const tasklist = (options: TasklistOptions = {}) => {
|
|
|
109
109
|
}
|
|
110
110
|
},
|
|
111
111
|
{
|
|
112
|
-
decorations: (
|
|
112
|
+
decorations: (value) => value.tasks,
|
|
113
113
|
provide: (plugin) =>
|
|
114
114
|
EditorView.atomicRanges.of((view) => {
|
|
115
115
|
return view.plugin(plugin)?.tasks || Decoration.none;
|
|
@@ -55,10 +55,10 @@ export const defaultTheme: {
|
|
|
55
55
|
//
|
|
56
56
|
// Cursor
|
|
57
57
|
//
|
|
58
|
-
'&light .cm-cursor': {
|
|
58
|
+
'&light .cm-cursor, &light .cm-dropCursor': {
|
|
59
59
|
borderLeft: '2px solid black',
|
|
60
60
|
},
|
|
61
|
-
'&dark .cm-cursor': {
|
|
61
|
+
'&dark .cm-cursor, &dark .cm-dropCursor': {
|
|
62
62
|
borderLeft: '2px solid white',
|
|
63
63
|
},
|
|
64
64
|
'& .cm-placeholder': {
|
|
@@ -173,6 +173,10 @@ export const defaultTheme: {
|
|
|
173
173
|
//
|
|
174
174
|
// table
|
|
175
175
|
//
|
|
176
|
+
'& .cm-table *': {
|
|
177
|
+
fontFamily: `${get(tokens, 'fontFamily.mono', []).join(',')} !important`,
|
|
178
|
+
textDecoration: 'none !important',
|
|
179
|
+
},
|
|
176
180
|
'& .cm-table-head': {
|
|
177
181
|
padding: '2px 16px 2px 0px',
|
|
178
182
|
borderBottom: `1px solid ${get(tokens, 'extend.colors.neutral.500')}`,
|
|
@@ -203,6 +207,43 @@ export const defaultTheme: {
|
|
|
203
207
|
acc[`& .text-${fontSize} + .cm-widgetBuffer + .cm-ySelectionCaret`] = { height };
|
|
204
208
|
return acc;
|
|
205
209
|
}, {}),
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Panels
|
|
213
|
+
* https://github.com/codemirror/search/blob/main/src/search.ts#L745
|
|
214
|
+
*
|
|
215
|
+
* Find/replace panel.
|
|
216
|
+
* <div class="cm-announced">...</div>
|
|
217
|
+
* <div class="cm-scroller">...</div>
|
|
218
|
+
* <div class="cm-panels cm-panels-bottom">
|
|
219
|
+
* <div class="cm-search cm-panel">
|
|
220
|
+
* <input class="cm-textfield" />
|
|
221
|
+
* <button class="cm-button">...</button>
|
|
222
|
+
* <label><input type="checkbox" />...</label>
|
|
223
|
+
* </div>
|
|
224
|
+
* </div
|
|
225
|
+
*/
|
|
226
|
+
'& .cm-panels': {
|
|
227
|
+
border: `1px solid ${get(tokens, 'extend.colors.neutral.200')}`,
|
|
228
|
+
borderBottom: 'none',
|
|
229
|
+
},
|
|
230
|
+
'& .cm-panel': {
|
|
231
|
+
background: get(tokens, 'extend.colors.neutral.50'),
|
|
232
|
+
fontFamily: get(tokens, 'fontFamily.body', []).join(','),
|
|
233
|
+
},
|
|
234
|
+
'& .cm-button': {
|
|
235
|
+
margin: '4px',
|
|
236
|
+
fontFamily: get(tokens, 'fontFamily.body', []).join(','),
|
|
237
|
+
background: get(tokens, 'extend.colors.neutral.100'),
|
|
238
|
+
border: 'none',
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
'& .cm-searchMatch': {
|
|
242
|
+
backgroundColor: get(tokens, 'extend.colors.yellow.100'),
|
|
243
|
+
},
|
|
244
|
+
'& .cm-searchMatch.cm-searchMatch-selected': {
|
|
245
|
+
backgroundColor: get(tokens, 'extend.colors.primary.100'),
|
|
246
|
+
},
|
|
206
247
|
};
|
|
207
248
|
|
|
208
249
|
export const textTheme: {
|
|
@@ -9,6 +9,7 @@ import { basicSetup } from 'codemirror';
|
|
|
9
9
|
import get from 'lodash.get';
|
|
10
10
|
import React, { useEffect, useRef, useState } from 'react';
|
|
11
11
|
|
|
12
|
+
// TODO(burdon): Why separate imports?
|
|
12
13
|
import { type Prop } from '@dxos/automerge/automerge';
|
|
13
14
|
import { type DocHandle, Repo } from '@dxos/automerge/automerge-repo';
|
|
14
15
|
|
|
@@ -26,12 +26,19 @@ import { SpaceAwarenessProvider } from './yjs';
|
|
|
26
26
|
// TODO(burdon): Move.
|
|
27
27
|
type Awareness = awarenessProtocol.Awareness;
|
|
28
28
|
|
|
29
|
+
export type DocumentRange = {
|
|
30
|
+
id: string;
|
|
31
|
+
from: number;
|
|
32
|
+
to: number;
|
|
33
|
+
};
|
|
34
|
+
|
|
29
35
|
// TODO(wittjosiah): Factor out to common package? @dxos/react-client?
|
|
30
36
|
export type EditorModel = {
|
|
31
37
|
id: string;
|
|
32
38
|
// TODO(burdon): Remove.
|
|
33
39
|
content: string | YText | YXmlFragment | DocAccessor;
|
|
34
40
|
text: () => string;
|
|
41
|
+
ranges: DocumentRange[];
|
|
35
42
|
extension?: Extension;
|
|
36
43
|
awareness?: Awareness;
|
|
37
44
|
peer?: {
|
|
@@ -80,6 +87,7 @@ const createYjsModel = ({ identity, space, text }: UseTextModelOptions): EditorM
|
|
|
80
87
|
id: text.doc.guid,
|
|
81
88
|
content: text.content,
|
|
82
89
|
text: () => text.content!.toString(),
|
|
90
|
+
ranges: [],
|
|
83
91
|
extension: yCollab(text.content as YText, provider?.awareness),
|
|
84
92
|
awareness: provider?.awareness,
|
|
85
93
|
peer: identity
|
|
@@ -99,6 +107,7 @@ const createAutomergeModel = ({ identity, text }: UseTextModelOptions): EditorMo
|
|
|
99
107
|
id: obj.id,
|
|
100
108
|
content: doc,
|
|
101
109
|
text: () => get(doc.handle.docSync(), doc.path),
|
|
110
|
+
ranges: [],
|
|
102
111
|
extension: automergePlugin(doc.handle, doc.path),
|
|
103
112
|
peer: identity
|
|
104
113
|
? {
|
|
@@ -16,6 +16,7 @@ import { MarkdownEditor } from '../../components';
|
|
|
16
16
|
import { Replicator, useYjsModel } from '../../testing';
|
|
17
17
|
|
|
18
18
|
export default {
|
|
19
|
+
title: 'react-ui-editor/YJS',
|
|
19
20
|
component: MarkdownEditor,
|
|
20
21
|
decorators: [withTheme],
|
|
21
22
|
};
|
|
@@ -50,7 +51,6 @@ const Story = () => {
|
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
export const Default = {
|
|
53
|
-
title: 'react-ui-editor/YJS',
|
|
54
54
|
// TODO(wittjosiah): Decorator for doing this without clients being initialized?
|
|
55
55
|
render: () => <ClientRepeater count={2} Component={Story} />,
|
|
56
56
|
};
|
package/src/styles/markdown.ts
CHANGED
|
@@ -6,12 +6,13 @@ import { mx } from '@dxos/react-ui-theme';
|
|
|
6
6
|
|
|
7
7
|
export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
8
8
|
|
|
9
|
+
// TODO(burdon): Better way to align vertically than negative margin? Font-specific?
|
|
9
10
|
// https://tailwindcss.com/docs/font-weight
|
|
10
11
|
export const headings: Record<HeadingLevel, string[]> = {
|
|
11
|
-
1: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl', '-ml-
|
|
12
|
-
2: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl', '-ml-
|
|
13
|
-
3: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl', '-ml-
|
|
14
|
-
4: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-xl', '-ml-[
|
|
12
|
+
1: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-4xl', '-ml-[10px]'],
|
|
13
|
+
2: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-3xl', '-ml-[8px]'],
|
|
14
|
+
3: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-2xl', '-ml-[7px]'],
|
|
15
|
+
4: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-xl', '-ml-[6px]'],
|
|
15
16
|
5: ['mbs-4 mbe-2 font-medium text-inherit no-underline text-lg', '-ml-[5px]'],
|
|
16
17
|
6: ['mbs-4 mbe-2 font-medium text-inherit no-underline', '-ml-[4px]'],
|
|
17
18
|
};
|