@dxos/react-ui-editor 0.4.10-main.e158b1a → 0.4.10-main.e2d2318
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 +70 -94
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.d.ts.map +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts +1 -1
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/extensions/automerge/automerge.stories.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/factories.d.ts +1 -1
- package/dist/types/src/extensions/factories.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +0 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/package.json +25 -24
- package/src/components/TextEditor/TextEditor.stories.tsx +8 -6
- package/src/components/TextEditor/TextEditor.tsx +6 -3
- package/src/components/Toolbar/Toolbar.stories.tsx +9 -9
- package/src/extensions/automerge/automerge.stories.tsx +12 -6
- package/src/extensions/automerge/cursor.ts +4 -37
- package/src/extensions/factories.ts +2 -2
- package/src/hooks/index.ts +0 -1
- package/src/hooks/useTextEditor.ts +1 -1
- package/dist/types/src/hooks/useDocAccessor.d.ts +0 -9
- package/dist/types/src/hooks/useDocAccessor.d.ts.map +0 -1
- package/src/hooks/useDocAccessor.ts +0 -27
|
@@ -6,7 +6,8 @@ import '@dxosTheme';
|
|
|
6
6
|
|
|
7
7
|
import React, { type FC, useState } from 'react';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { TextV0Type } from '@braneframe/types';
|
|
10
|
+
import { createDocAccessor, create } from '@dxos/echo-schema';
|
|
10
11
|
import { PublicKey } from '@dxos/keys';
|
|
11
12
|
import { faker } from '@dxos/random';
|
|
12
13
|
import { Tooltip, useThemeContext } from '@dxos/react-ui';
|
|
@@ -28,26 +29,25 @@ import {
|
|
|
28
29
|
useComments,
|
|
29
30
|
useFormattingState,
|
|
30
31
|
} from '../../extensions';
|
|
31
|
-
import { useActionHandler,
|
|
32
|
+
import { useActionHandler, useTextEditor } from '../../hooks';
|
|
32
33
|
import translations from '../../translations';
|
|
33
34
|
|
|
34
35
|
faker.seed(101);
|
|
35
36
|
|
|
36
37
|
const Story: FC<{ content: string }> = ({ content }) => {
|
|
37
38
|
const { themeMode } = useThemeContext();
|
|
38
|
-
const [
|
|
39
|
-
const { id, doc, accessor } = useDocAccessor(item.text);
|
|
39
|
+
const [text] = useState(create(TextV0Type, { content }));
|
|
40
40
|
const [formattingState, formattingObserver] = useFormattingState();
|
|
41
41
|
const { parentRef, view } = useTextEditor(() => {
|
|
42
42
|
return {
|
|
43
|
-
id,
|
|
44
|
-
doc,
|
|
43
|
+
id: text.id,
|
|
44
|
+
doc: text.content,
|
|
45
45
|
extensions: [
|
|
46
46
|
formattingObserver,
|
|
47
47
|
createBasicExtensions(),
|
|
48
48
|
createMarkdownExtensions({ themeMode }),
|
|
49
49
|
createThemeExtensions({ themeMode, slots: { editor: { className: 'p-2' } } }),
|
|
50
|
-
createDataExtensions({ id, text:
|
|
50
|
+
createDataExtensions({ id: text.id, text: createDocAccessor(text, ['content']) }),
|
|
51
51
|
comments({
|
|
52
52
|
onCreate: ({ cursor }) => {
|
|
53
53
|
const id = PublicKey.random().toHex();
|
|
@@ -61,12 +61,12 @@ const Story: FC<{ content: string }> = ({ content }) => {
|
|
|
61
61
|
table(),
|
|
62
62
|
],
|
|
63
63
|
};
|
|
64
|
-
}, [
|
|
64
|
+
}, [text, formattingObserver, themeMode]);
|
|
65
65
|
|
|
66
66
|
const handleAction = useActionHandler(view);
|
|
67
67
|
|
|
68
68
|
const [_comments, setComments] = useState<Comment[]>([]);
|
|
69
|
-
useComments(view, id, _comments);
|
|
69
|
+
useComments(view, text.id, _comments);
|
|
70
70
|
|
|
71
71
|
return (
|
|
72
72
|
<Tooltip.Provider>
|
|
@@ -9,8 +9,14 @@ import '@preact/signals-react';
|
|
|
9
9
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
10
10
|
|
|
11
11
|
import { Repo } from '@dxos/automerge/automerge-repo';
|
|
12
|
-
import {
|
|
13
|
-
|
|
12
|
+
import {
|
|
13
|
+
Filter,
|
|
14
|
+
DocAccessor,
|
|
15
|
+
TextCompatibilitySchema,
|
|
16
|
+
create,
|
|
17
|
+
createDocAccessor,
|
|
18
|
+
type Expando,
|
|
19
|
+
} from '@dxos/echo-schema';
|
|
14
20
|
import { type PublicKey } from '@dxos/keys';
|
|
15
21
|
import { useSpace } from '@dxos/react-client/echo';
|
|
16
22
|
import { ClientRepeater } from '@dxos/react-client/testing';
|
|
@@ -98,9 +104,9 @@ const EchoStory = ({ spaceKey }: { spaceKey: PublicKey }) => {
|
|
|
98
104
|
// const identity = useIdentity();
|
|
99
105
|
const space = useSpace(spaceKey);
|
|
100
106
|
const source = useMemo<DocAccessor | undefined>(() => {
|
|
101
|
-
const { objects = [] } = space?.db.query(Filter.from({ type: 'test' })) ?? {};
|
|
107
|
+
const { objects = [] } = space?.db.query<Expando>(Filter.from({ type: 'test' })) ?? {};
|
|
102
108
|
if (objects.length) {
|
|
103
|
-
return createDocAccessor(objects[0].content);
|
|
109
|
+
return createDocAccessor(objects[0].content, ['content']);
|
|
104
110
|
}
|
|
105
111
|
}, [space]);
|
|
106
112
|
|
|
@@ -125,9 +131,9 @@ export const WithEcho = {
|
|
|
125
131
|
createSpace
|
|
126
132
|
onCreateSpace={async (space) => {
|
|
127
133
|
space.db.add(
|
|
128
|
-
|
|
134
|
+
create({
|
|
129
135
|
type: 'test',
|
|
130
|
-
content:
|
|
136
|
+
content: create(TextCompatibilitySchema, { content: initialContent }),
|
|
131
137
|
}),
|
|
132
138
|
);
|
|
133
139
|
}}
|
|
@@ -2,30 +2,16 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
import { next as A } from '@dxos/automerge/automerge';
|
|
8
|
-
import { type DocAccessor } from '@dxos/echo-schema';
|
|
5
|
+
import { toCursor, type DocAccessor, fromCursor } from '@dxos/echo-schema';
|
|
9
6
|
import { log } from '@dxos/log';
|
|
10
7
|
|
|
11
8
|
import { type CursorConverter } from '../cursor';
|
|
12
9
|
|
|
13
|
-
export const cursorConverter = (
|
|
10
|
+
export const cursorConverter = (accessor: DocAccessor): CursorConverter => ({
|
|
14
11
|
// TODO(burdon): Handle assoc to associate with a previous character.
|
|
15
12
|
toCursor: (pos) => {
|
|
16
|
-
const doc = handle.docSync();
|
|
17
|
-
if (!doc) {
|
|
18
|
-
return '';
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const value = get(doc, path);
|
|
22
|
-
if (typeof value === 'string' && value.length <= pos) {
|
|
23
|
-
return 'end';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
13
|
try {
|
|
27
|
-
|
|
28
|
-
return A.getCursor(doc, path.slice(), pos);
|
|
14
|
+
return toCursor(accessor, pos);
|
|
29
15
|
} catch (err) {
|
|
30
16
|
log.catch(err);
|
|
31
17
|
return ''; // In case of invalid request (e.g., wrong document).
|
|
@@ -33,27 +19,8 @@ export const cursorConverter = ({ handle, path }: DocAccessor): CursorConverter
|
|
|
33
19
|
},
|
|
34
20
|
|
|
35
21
|
fromCursor: (cursor) => {
|
|
36
|
-
if (cursor === '') {
|
|
37
|
-
return 0;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const doc = handle.docSync();
|
|
41
|
-
if (!doc) {
|
|
42
|
-
return 0;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (cursor === 'end') {
|
|
46
|
-
const value = get(doc, path);
|
|
47
|
-
if (typeof value === 'string') {
|
|
48
|
-
return value.length;
|
|
49
|
-
} else {
|
|
50
|
-
return 0;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
22
|
try {
|
|
55
|
-
|
|
56
|
-
return A.getCursorPosition(doc, path.slice(), cursor);
|
|
23
|
+
return fromCursor(accessor, cursor);
|
|
57
24
|
} catch (err) {
|
|
58
25
|
log.catch(err);
|
|
59
26
|
return 0; // In case of invalid request (e.g., wrong document).
|
|
@@ -162,14 +162,14 @@ export const createThemeExtensions = ({ theme, themeMode, slots: _slots }: Theme
|
|
|
162
162
|
|
|
163
163
|
export type DataExtensionsProps = {
|
|
164
164
|
id: string;
|
|
165
|
-
text
|
|
165
|
+
text?: DocAccessor;
|
|
166
166
|
space?: Space;
|
|
167
167
|
identity?: Identity | null;
|
|
168
168
|
};
|
|
169
169
|
|
|
170
170
|
// TODO(burdon): Move out of react-ui-editor (remove echo deps).
|
|
171
171
|
export const createDataExtensions = ({ id, text, space, identity }: DataExtensionsProps): Extension[] => {
|
|
172
|
-
const extensions: Extension[] = [automerge(text)];
|
|
172
|
+
const extensions: Extension[] = text ? [automerge(text)] : [];
|
|
173
173
|
|
|
174
174
|
if (space && identity) {
|
|
175
175
|
const peerId = identity?.identityKey.toHex();
|
package/src/hooks/index.ts
CHANGED
|
@@ -36,9 +36,9 @@ export const useTextEditor = (cb: () => UseTextEditorProps = () => ({}), deps: D
|
|
|
36
36
|
log('create', { id });
|
|
37
37
|
|
|
38
38
|
// https://codemirror.net/docs/ref/#state.EditorStateConfig
|
|
39
|
+
// NOTE: Don't set selection here in case it is invalid (and crashes the state); dispatch below.
|
|
39
40
|
const state = EditorState.create({
|
|
40
41
|
doc,
|
|
41
|
-
selection,
|
|
42
42
|
extensions: [
|
|
43
43
|
id && documentId.of(id),
|
|
44
44
|
// TODO(burdon): Doesn't catch errors in keymap functions.
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type DocAccessor, type TextObject, type EchoReactiveObject } from '@dxos/echo-schema';
|
|
2
|
-
export declare const useDocAccessor: <T = any>(text: TextObject | EchoReactiveObject<{
|
|
3
|
-
content: string;
|
|
4
|
-
}>) => {
|
|
5
|
-
id: string;
|
|
6
|
-
doc: string | undefined;
|
|
7
|
-
accessor: DocAccessor<T>;
|
|
8
|
-
};
|
|
9
|
-
//# sourceMappingURL=useDocAccessor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useDocAccessor.d.ts","sourceRoot":"","sources":["../../../../src/hooks/useDocAccessor.ts"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,WAAW,EAEhB,KAAK,UAAU,EACf,KAAK,kBAAkB,EACxB,MAAM,mBAAmB,CAAC;AAG3B,eAAO,MAAM,cAAc,kBACnB,UAAU,GAAG,mBAAmB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;QACnD,MAAM;SAAO,MAAM,GAAG,SAAS;;CASvC,CAAC"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { useMemo } from 'react';
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
createDocAccessor,
|
|
9
|
-
type DocAccessor,
|
|
10
|
-
getTextContent,
|
|
11
|
-
type TextObject,
|
|
12
|
-
type EchoReactiveObject,
|
|
13
|
-
} from '@dxos/echo-schema';
|
|
14
|
-
|
|
15
|
-
// TODO(burdon): Factor out.
|
|
16
|
-
export const useDocAccessor = <T = any>(
|
|
17
|
-
text: TextObject | EchoReactiveObject<{ content: string }>,
|
|
18
|
-
): { id: string; doc: string | undefined; accessor: DocAccessor<T> } => {
|
|
19
|
-
return useMemo(
|
|
20
|
-
() => ({
|
|
21
|
-
id: text.id,
|
|
22
|
-
doc: getTextContent(text),
|
|
23
|
-
accessor: createDocAccessor<T>(text),
|
|
24
|
-
}),
|
|
25
|
-
[text],
|
|
26
|
-
);
|
|
27
|
-
};
|