@dxos/react-ui-editor 0.3.11-main.668f0ff → 0.3.11-main.674a7f9
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 +2031 -1641
- 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 +14 -14
- 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 -3
- package/dist/types/src/components/TextEditor/TextEditor.stories.d.ts.map +1 -1
- package/dist/types/src/{hooks/automerge → components/TextEditor}/automerge.stories.d.ts +6 -1
- package/dist/types/src/components/TextEditor/automerge.stories.d.ts.map +1 -0
- 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/TextEditor/index.d.ts +0 -2
- package/dist/types/src/components/TextEditor/index.d.ts.map +1 -1
- package/dist/types/src/extensions/autocomplete.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/automerge.d.ts +9 -0
- package/dist/types/src/extensions/automerge/automerge.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/cursor.d.ts +5 -0
- package/dist/types/src/extensions/automerge/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/defs.d.ts +24 -0
- package/dist/types/src/extensions/automerge/defs.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/index.d.ts +3 -0
- package/dist/types/src/extensions/automerge/index.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/semaphore.d.ts +14 -0
- package/dist/types/src/extensions/automerge/semaphore.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/update-automerge.d.ts +5 -0
- package/dist/types/src/extensions/automerge/update-automerge.d.ts.map +1 -0
- package/dist/types/src/extensions/automerge/update-codemirror.d.ts.map +1 -0
- package/dist/types/src/extensions/awareness.d.ts +46 -0
- package/dist/types/src/extensions/awareness.d.ts.map +1 -0
- package/dist/types/src/extensions/basic.d.ts +8 -0
- package/dist/types/src/extensions/basic.d.ts.map +1 -0
- package/dist/types/src/extensions/blast.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor/extensions → extensions}/comments.d.ts +33 -18
- package/dist/types/src/extensions/comments.d.ts.map +1 -0
- package/dist/types/src/extensions/cursor.d.ts +25 -0
- package/dist/types/src/extensions/cursor.d.ts.map +1 -0
- package/dist/types/src/extensions/index.d.ts +13 -0
- package/dist/types/src/extensions/index.d.ts.map +1 -0
- package/dist/types/src/extensions/listener.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/bundle.d.ts +2 -5
- package/dist/types/src/extensions/markdown/bundle.d.ts.map +1 -0
- package/dist/types/src/extensions/markdown/code.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 -0
- 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 +10 -0
- package/dist/types/src/extensions/markdown/index.d.ts.map +1 -0
- package/dist/types/src/{components/TextEditor/extensions → extensions/markdown}/link.d.ts +1 -0
- 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 -0
- 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/extensions/typewriter.d.ts.map +1 -0
- package/dist/types/src/hooks/awareness-provider.d.ts +31 -0
- package/dist/types/src/hooks/awareness-provider.d.ts.map +1 -0
- 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 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- 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 -31
- package/dist/types/src/hooks/useTextModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +5 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/styles/cursors.d.ts.map +1 -0
- package/dist/types/src/styles/index.d.ts +1 -0
- package/dist/types/src/styles/index.d.ts.map +1 -1
- 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/{components/TextEditor/themes → themes}/default.d.ts +1 -1
- package/dist/types/src/themes/default.d.ts.map +1 -0
- package/dist/types/src/themes/index.d.ts.map +1 -0
- package/dist/types/src/util.d.ts +7 -0
- package/dist/types/src/util.d.ts.map +1 -0
- package/package.json +33 -34
- package/src/components/TextEditor/MarkdownEditor.stories.tsx +88 -91
- package/src/components/TextEditor/TextEditor.stories.tsx +13 -34
- package/src/components/TextEditor/TextEditor.tsx +123 -94
- package/src/{hooks/automerge → components/TextEditor}/automerge.stories.tsx +66 -6
- package/src/components/TextEditor/comments.stories.tsx +357 -0
- package/src/components/TextEditor/index.ts +0 -3
- package/src/{components/TextEditor/extensions → extensions}/autocomplete.ts +23 -19
- package/src/extensions/automerge/automerge.ts +88 -0
- package/src/extensions/automerge/cursor.ts +52 -0
- package/src/extensions/automerge/defs.ts +41 -0
- package/src/extensions/automerge/index.ts +6 -0
- package/src/{hooks → extensions}/automerge/semaphore.ts +34 -29
- package/src/{hooks → extensions}/automerge/update-automerge.ts +5 -6
- package/src/{hooks → extensions}/automerge/update-codemirror.ts +13 -5
- package/src/extensions/awareness.ts +310 -0
- package/src/extensions/basic.ts +37 -0
- package/src/extensions/comments.ts +428 -0
- package/src/extensions/cursor.ts +50 -0
- package/src/{components/TextEditor/extensions → extensions}/index.ts +4 -8
- package/src/extensions/listener.ts +35 -0
- package/src/{components/TextEditor/extensions → extensions}/markdown/bundle.ts +18 -24
- package/src/{components/TextEditor/extensions → extensions/markdown}/code.ts +28 -23
- package/src/extensions/markdown/heading.ts +60 -0
- package/src/{components/TextEditor/extensions → extensions}/markdown/highlight.ts +4 -13
- package/src/extensions/markdown/hr.ts +72 -0
- package/src/extensions/markdown/image.ts +87 -0
- package/src/extensions/markdown/index.ts +13 -0
- package/src/{components/TextEditor/extensions → extensions/markdown}/link.ts +116 -62
- package/src/{components/TextEditor/extensions → extensions/markdown}/table.ts +10 -4
- package/src/extensions/markdown/tasklist.ts +111 -0
- package/src/{components/TextEditor/extensions → extensions}/mention.ts +9 -2
- package/src/extensions/outliner.ts +12 -0
- package/src/{components/TextEditor/extensions → extensions}/typewriter.ts +1 -1
- package/src/hooks/awareness-provider.ts +124 -0
- package/src/hooks/defs.ts +42 -0
- package/src/hooks/index.ts +4 -1
- package/src/hooks/useTextEditor.ts +29 -0
- package/src/hooks/useTextModel.ts +30 -115
- package/src/index.ts +5 -0
- package/src/styles/index.ts +1 -0
- package/src/styles/markdown.ts +0 -2
- package/src/styles/tokens.ts +3 -0
- package/src/{components/TextEditor/themes → themes}/default.ts +52 -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/extensions/autocomplete.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/basic.d.ts +0 -9
- package/dist/types/src/components/TextEditor/extensions/basic.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/blast.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/code.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/comments.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/hr.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/image.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/index.d.ts +0 -17
- package/dist/types/src/components/TextEditor/extensions/index.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/link.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/listener.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/bundle.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/highlight.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts +0 -3
- package/dist/types/src/components/TextEditor/extensions/markdown/index.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/mention.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/mermaid.d.ts +0 -3
- package/dist/types/src/components/TextEditor/extensions/mermaid.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/table.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/tasklist.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/tooltip.d.ts +0 -12
- package/dist/types/src/components/TextEditor/extensions/tooltip.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/typewriter.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/extensions/util.d.ts +0 -5
- package/dist/types/src/components/TextEditor/extensions/util.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/themes/default.d.ts.map +0 -1
- package/dist/types/src/components/TextEditor/themes/index.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/automerge.stories.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/handle.d.ts +0 -9
- package/dist/types/src/hooks/automerge/handle.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/index.d.ts +0 -3
- package/dist/types/src/hooks/automerge/index.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/plugin.d.ts +0 -26
- package/dist/types/src/hooks/automerge/plugin.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/semaphore.d.ts +0 -19
- package/dist/types/src/hooks/automerge/semaphore.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/update-automerge.d.ts +0 -6
- package/dist/types/src/hooks/automerge/update-automerge.d.ts.map +0 -1
- package/dist/types/src/hooks/automerge/update-codemirror.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs/cursors.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs/index.d.ts +0 -3
- package/dist/types/src/hooks/yjs/index.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs/space-provider.d.ts +0 -27
- package/dist/types/src/hooks/yjs/space-provider.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs/yjs.stories.d.ts +0 -12
- package/dist/types/src/hooks/yjs/yjs.stories.d.ts.map +0 -1
- package/dist/types/src/hooks/yjs/yjs.test.d.ts +0 -2
- package/dist/types/src/hooks/yjs/yjs.test.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/src/components/TextEditor/codemirror.stories.ts +0 -114
- package/src/components/TextEditor/extensions/basic.ts +0 -32
- package/src/components/TextEditor/extensions/comments.ts +0 -389
- package/src/components/TextEditor/extensions/hr.ts +0 -74
- package/src/components/TextEditor/extensions/image.ts +0 -69
- package/src/components/TextEditor/extensions/listener.ts +0 -39
- package/src/components/TextEditor/extensions/markdown/index.ts +0 -6
- package/src/components/TextEditor/extensions/mermaid.ts +0 -11
- package/src/components/TextEditor/extensions/tasklist.ts +0 -121
- package/src/components/TextEditor/extensions/tooltip.ts +0 -61
- package/src/components/TextEditor/extensions/util.ts +0 -18
- package/src/hooks/automerge/handle.ts +0 -14
- package/src/hooks/automerge/index.ts +0 -6
- package/src/hooks/automerge/plugin.ts +0 -134
- package/src/hooks/yjs/index.ts +0 -6
- package/src/hooks/yjs/space-provider.ts +0 -126
- package/src/hooks/yjs/yjs.stories.tsx +0 -56
- package/src/hooks/yjs/yjs.test.ts +0 -59
- 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 -189
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/autocomplete.d.ts +0 -0
- /package/dist/types/src/{hooks → extensions}/automerge/update-codemirror.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/blast.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/listener.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions/markdown}/code.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/markdown/highlight.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions/markdown}/hr.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions/markdown}/image.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions/markdown}/table.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions/markdown}/tasklist.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/mention.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/extensions → extensions}/typewriter.d.ts +0 -0
- /package/dist/types/src/{hooks/yjs → styles}/cursors.d.ts +0 -0
- /package/dist/types/src/{components/TextEditor/themes → themes}/index.d.ts +0 -0
- /package/src/{components/TextEditor/extensions → extensions}/blast.ts +0 -0
- /package/src/{hooks/yjs → styles}/cursors.ts +0 -0
- /package/src/{components/TextEditor/themes → themes}/index.ts +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"yjs.stories.d.ts","sourceRoot":"","sources":["../../../../../src/hooks/yjs/yjs.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;AAEpB,OAAO,KAAmB,MAAM,OAAO,CAAC;;;;;;AAWxC,wBAIE;AA+BF,eAAO,MAAM,OAAO;;CAGnB,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"yjs.test.d.ts","sourceRoot":"","sources":["../../../../../src/hooks/yjs/yjs.test.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/testing/index.ts"],"names":[],"mappings":"AAIA,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @generated @dxos/echo-typegen src/testing/proto/schema.proto
|
|
3
|
-
**/
|
|
4
|
-
import * as dxos_echo_schema from "@dxos/echo-schema";
|
|
5
|
-
export declare const types: dxos_echo_schema.TypeCollection;
|
|
6
|
-
export type EditorDocumentProps = {
|
|
7
|
-
content: dxos_echo_schema.Text;
|
|
8
|
-
};
|
|
9
|
-
export declare class EditorDocument extends dxos_echo_schema.TypedObject<EditorDocumentProps> {
|
|
10
|
-
static readonly schema: dxos_echo_schema.Schema;
|
|
11
|
-
static filter(filter?: Partial<EditorDocumentProps> | dxos_echo_schema.OperatorFilter<EditorDocument>): dxos_echo_schema.Filter<EditorDocument>;
|
|
12
|
-
constructor(initValues?: Partial<EditorDocumentProps>, opts?: dxos_echo_schema.TypedObjectOptions);
|
|
13
|
-
content: dxos_echo_schema.Text;
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../../../src/testing/proto/gen/schema.ts"],"names":[],"mappings":"AAAA;;IAEI;AAEJ,OAAO,KAAK,gBAAgB,MAAM,mBAAmB,CAAC;AAEtD,eAAO,MAAM,KAAK,iCAAwC,CAAC;AAE3D,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,gBAAgB,CAAC,IAAI,CAAC;CAChC,CAAC;AAEF,qBAAa,cAAe,SAAQ,gBAAgB,CAAC,WAAW,CAAC,mBAAmB,CAAC;IACnF,gBAAwB,MAAM,EAAE,gBAAgB,CAAC,MAAM,CAAC;IAExD,MAAM,CAAC,MAAM,CACX,MAAM,CAAC,EACH,OAAO,CAAC,mBAAmB,CAAC,GAC5B,gBAAgB,CAAC,cAAc,CAAC,cAAc,CAAC,GAClD,gBAAgB,CAAC,MAAM,CAAC,cAAc,CAAC;gBAQxC,UAAU,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,EACzC,IAAI,CAAC,EAAE,gBAAgB,CAAC,kBAAkB;IAIpC,OAAO,EAAE,gBAAgB,CAAC,IAAI,CAAC;CACxC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/testing/proto/index.ts"],"names":[],"mappings":"AAIA,cAAc,cAAc,CAAC"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { Observable } from 'lib0/observable';
|
|
2
|
-
import * as awarenessProtocol from 'y-protocols/awareness';
|
|
3
|
-
import { Doc } from 'yjs';
|
|
4
|
-
import { Event } from '@dxos/async';
|
|
5
|
-
import { TextKind } from '@dxos/protocols/proto/dxos/echo/model/text';
|
|
6
|
-
import { type EditorModel } from '../hooks';
|
|
7
|
-
type Awareness = awarenessProtocol.Awareness;
|
|
8
|
-
/**
|
|
9
|
-
* Yjs awareness provider in-memory.
|
|
10
|
-
*/
|
|
11
|
-
export declare class AwarenessProvider extends Observable<any> {
|
|
12
|
-
private readonly _remoteUpdate;
|
|
13
|
-
private readonly _awareness;
|
|
14
|
-
private readonly _doc;
|
|
15
|
-
constructor({ update, doc, awareness }: {
|
|
16
|
-
update: Event<Uint8Array>;
|
|
17
|
-
doc: Doc;
|
|
18
|
-
awareness?: Awareness;
|
|
19
|
-
});
|
|
20
|
-
get awareness(): Awareness;
|
|
21
|
-
private _handleDocUpdate;
|
|
22
|
-
private _handleAwarenessUpdate;
|
|
23
|
-
private _handleRemoteUpdate;
|
|
24
|
-
private _readMessage;
|
|
25
|
-
private _handleBeforeUnload;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* This mocks the replication across the swarm.
|
|
29
|
-
*/
|
|
30
|
-
export declare class Replicator {
|
|
31
|
-
private readonly _kind;
|
|
32
|
-
private readonly _update;
|
|
33
|
-
private _peers;
|
|
34
|
-
constructor(_kind: TextKind);
|
|
35
|
-
setPeers(peers: EditorModel[]): void;
|
|
36
|
-
createPeer: (id: string, doc?: Doc) => EditorModel;
|
|
37
|
-
}
|
|
38
|
-
export type UseYjsModelOptions = {
|
|
39
|
-
replicator: Replicator;
|
|
40
|
-
id: string;
|
|
41
|
-
doc?: Doc;
|
|
42
|
-
};
|
|
43
|
-
export declare const useYjsModel: ({ replicator, id, doc }: UseYjsModelOptions) => EditorModel;
|
|
44
|
-
export {};
|
|
45
|
-
//# sourceMappingURL=replicator.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"replicator.d.ts","sourceRoot":"","sources":["../../../../src/testing/replicator.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAC;AAE3D,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,OAAO,EAAE,QAAQ,EAAE,MAAM,4CAA4C,CAAC;AAEtE,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,UAAU,CAAC;AAEzD,KAAK,SAAS,GAAG,iBAAiB,CAAC,SAAS,CAAC;AAM7C;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,UAAU,CAAC,GAAG,CAAC;IACpD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoB;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAY;IACvC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAM;gBAEf,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE;QAAE,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QAAC,GAAG,EAAE,GAAG,CAAC;QAAC,SAAS,CAAC,EAAE,SAAS,CAAA;KAAE;IA+BtG,IAAI,SAAS,IAAI,SAAS,CAEzB;IAED,OAAO,CAAC,gBAAgB;IAQxB,OAAO,CAAC,sBAAsB;IAY9B,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,YAAY;IA0CpB,OAAO,CAAC,mBAAmB;CAG5B;AAED;;GAEG;AACH,qBAAa,UAAU;IAIT,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHlC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,MAAM,CAAqB;gBAEN,KAAK,EAAE,QAAQ;IAE5C,QAAQ,CAAC,KAAK,EAAE,WAAW,EAAE;IAI7B,UAAU,OAAQ,MAAM,QAAO,GAAG,KAAe,WAAW,CAoB1D;CACH;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,UAAU,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,GAAG,CAAC;CACX,CAAC;AAEF,eAAO,MAAM,WAAW,4BAA6B,kBAAkB,KAAG,WAEzE,CAAC"}
|
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
|
|
6
|
-
import { EditorState } from '@codemirror/state';
|
|
7
|
-
import { EditorView } from '@codemirror/view';
|
|
8
|
-
import { type StoryObj } from '@storybook/html';
|
|
9
|
-
import { basicSetup } from 'codemirror';
|
|
10
|
-
import { yCollab } from 'y-codemirror.next';
|
|
11
|
-
|
|
12
|
-
import { EventSubscriptions } from '@dxos/async';
|
|
13
|
-
import { generateName } from '@dxos/display-name';
|
|
14
|
-
import { Client, type PublicKey } from '@dxos/react-client';
|
|
15
|
-
import { type Space, TextObject } from '@dxos/react-client/echo';
|
|
16
|
-
import { type Identity } from '@dxos/react-client/halo';
|
|
17
|
-
import { joinCommonSpace, TestBuilder, textGenerator } from '@dxos/react-client/testing';
|
|
18
|
-
import { YText } from '@dxos/text-model';
|
|
19
|
-
|
|
20
|
-
import { cursorColor, SpaceAwarenessProvider } from '../../hooks';
|
|
21
|
-
import { EditorDocument, types as schema } from '../../testing';
|
|
22
|
-
|
|
23
|
-
export default {
|
|
24
|
-
title: 'CodeMirror',
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const testBuilder = new TestBuilder();
|
|
28
|
-
const views: Record<number, EditorView> = {};
|
|
29
|
-
const subscriptions = new EventSubscriptions();
|
|
30
|
-
|
|
31
|
-
const updateEditor = async (id: number, editor: HTMLDivElement, identity: Identity, space: Space, text: TextObject) => {
|
|
32
|
-
const doc = text.doc;
|
|
33
|
-
const ytext = text.content;
|
|
34
|
-
if (!(ytext instanceof YText) || !doc) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const { awareness } = new SpaceAwarenessProvider({ space, doc, channel: `yjs.awareness.${text.id}` });
|
|
39
|
-
awareness.setLocalStateField('user', {
|
|
40
|
-
name: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
|
|
41
|
-
// TODO(wittjosiah): Pick colours from theme based on identity key.
|
|
42
|
-
color: cursorColor.color,
|
|
43
|
-
colorLight: cursorColor.light,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const state = EditorState.create({
|
|
47
|
-
doc: ytext.toString(),
|
|
48
|
-
extensions: [basicSetup, markdown({ base: markdownLanguage }), yCollab(ytext, awareness)],
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const view = views[id];
|
|
52
|
-
if (view) {
|
|
53
|
-
view.setState(state);
|
|
54
|
-
} else {
|
|
55
|
-
views[id] = new EditorView({ state, parent: editor });
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (id === 0) {
|
|
59
|
-
subscriptions.clear();
|
|
60
|
-
subscriptions.add(textGenerator({ text: ytext }));
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
const setupEditor = async (id: number, client: Client, spaceKey: PublicKey, editor: HTMLDivElement) => {
|
|
65
|
-
const space = await client.spaces.get(spaceKey)!;
|
|
66
|
-
const query = space.db.query(EditorDocument.filter());
|
|
67
|
-
query.subscribe(({ objects }) => {
|
|
68
|
-
const text = objects[0]?.content;
|
|
69
|
-
void (text && updateEditor(id, editor, client.halo.identity.get()!, space, text));
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const text = query.objects[0]?.content;
|
|
73
|
-
void (text && updateEditor(id, editor, client.halo.identity.get()!, space, text));
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
const setupSpace = async (count: number) => {
|
|
77
|
-
const clients = [...Array(count)].map(() => new Client({ services: testBuilder.createLocal() }));
|
|
78
|
-
await Promise.all(clients.map((client) => client.initialize()));
|
|
79
|
-
await Promise.all(clients.map((client) => client.halo.createIdentity()));
|
|
80
|
-
clients.map((client) => client.spaces.addSchema(schema));
|
|
81
|
-
|
|
82
|
-
const space = await clients[0].spaces.create();
|
|
83
|
-
const text = new TextObject('Hello, Storybook!');
|
|
84
|
-
const document = new EditorDocument({ content: text });
|
|
85
|
-
await space.db.add(document);
|
|
86
|
-
|
|
87
|
-
await joinCommonSpace(clients, space.key);
|
|
88
|
-
|
|
89
|
-
return { clients, spaceKey: space.key };
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const count = 2;
|
|
93
|
-
|
|
94
|
-
export const Default: StoryObj<{ id: number; client: Client; spaceKey: PublicKey }> = {
|
|
95
|
-
render: ({ id, client, spaceKey }) => {
|
|
96
|
-
const editor = document.createElement('div');
|
|
97
|
-
editor.setAttribute('style', 'min-width: 0; flex: 1; padding: 1rem;');
|
|
98
|
-
void setupEditor(id, client, spaceKey, editor);
|
|
99
|
-
return editor;
|
|
100
|
-
},
|
|
101
|
-
decorators: [
|
|
102
|
-
(story) => {
|
|
103
|
-
const container = document.createElement('div');
|
|
104
|
-
container.setAttribute('style', 'display: flex; justify-content: space-evenly');
|
|
105
|
-
void setupSpace(count).then(({ clients, spaceKey }) => {
|
|
106
|
-
clients.forEach((client, id) => {
|
|
107
|
-
// TODO(wittjosiah): According to the docs these types should be compatible.
|
|
108
|
-
container.appendChild(story({ args: { id, client, spaceKey } }) as HTMLElement);
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
return container;
|
|
112
|
-
},
|
|
113
|
-
],
|
|
114
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { closeBrackets } from '@codemirror/autocomplete';
|
|
6
|
-
import { bracketMatching, defaultHighlightStyle, syntaxHighlighting } from '@codemirror/language';
|
|
7
|
-
import { type Extension } from '@codemirror/state';
|
|
8
|
-
import { oneDarkHighlightStyle } from '@codemirror/theme-one-dark';
|
|
9
|
-
import { drawSelection, EditorView, placeholder } from '@codemirror/view';
|
|
10
|
-
|
|
11
|
-
import type { ThemeMode } from '@dxos/react-ui';
|
|
12
|
-
|
|
13
|
-
export type BasicBundleOptions = {
|
|
14
|
-
readonly?: boolean;
|
|
15
|
-
themeMode?: ThemeMode;
|
|
16
|
-
placeholder?: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const basicBundle = ({ readonly, themeMode, placeholder: _placeholder }: BasicBundleOptions): Extension[] =>
|
|
20
|
-
[
|
|
21
|
-
EditorView.lineWrapping,
|
|
22
|
-
|
|
23
|
-
// TODO(burdon): Compare with minimalSetup.
|
|
24
|
-
// https://codemirror.net/docs/ref/#codemirror.minimalSetup
|
|
25
|
-
bracketMatching(),
|
|
26
|
-
closeBrackets(),
|
|
27
|
-
drawSelection(),
|
|
28
|
-
_placeholder && placeholder(_placeholder),
|
|
29
|
-
|
|
30
|
-
// TODO(burdon): Is this required?
|
|
31
|
-
themeMode === 'dark' ? syntaxHighlighting(oneDarkHighlightStyle) : syntaxHighlighting(defaultHighlightStyle),
|
|
32
|
-
].filter(Boolean) as Extension[];
|
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2023 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type Extension, StateEffect, StateField } from '@codemirror/state';
|
|
6
|
-
import {
|
|
7
|
-
hoverTooltip,
|
|
8
|
-
keymap,
|
|
9
|
-
type Command,
|
|
10
|
-
type DecorationSet,
|
|
11
|
-
type ViewUpdate,
|
|
12
|
-
Decoration,
|
|
13
|
-
EditorView,
|
|
14
|
-
MatchDecorator,
|
|
15
|
-
ViewPlugin,
|
|
16
|
-
WidgetType,
|
|
17
|
-
type Rect,
|
|
18
|
-
} from '@codemirror/view';
|
|
19
|
-
import sortBy from 'lodash.sortby';
|
|
20
|
-
|
|
21
|
-
import { debounce } from '@dxos/async';
|
|
22
|
-
import { invariant } from '@dxos/invariant';
|
|
23
|
-
import { log } from '@dxos/log';
|
|
24
|
-
import { nonNullable } from '@dxos/util';
|
|
25
|
-
|
|
26
|
-
import { callbackWrapper } from './util';
|
|
27
|
-
import { type CommentRange, type EditorModel, modelState, type Range } from '../../../hooks';
|
|
28
|
-
|
|
29
|
-
// TODO(burdon): Handle scroll to.
|
|
30
|
-
// TODO(burdon): Handle delete, cut, copy, and paste (separately) text that includes comment range.
|
|
31
|
-
// TODO(burdon): Consider breaking into separate plugin (since not standalone)? Like mermaid?
|
|
32
|
-
|
|
33
|
-
// TODO(burdon): Reconcile with theme.
|
|
34
|
-
const styles = EditorView.baseTheme({
|
|
35
|
-
'& .cm-bookmark': {
|
|
36
|
-
cursor: 'pointer',
|
|
37
|
-
margin: '4px',
|
|
38
|
-
padding: '4px',
|
|
39
|
-
backgroundColor: 'yellow',
|
|
40
|
-
},
|
|
41
|
-
'& .cm-bookmark-selected': {
|
|
42
|
-
backgroundColor: 'orange',
|
|
43
|
-
},
|
|
44
|
-
'& .cm-comment': {
|
|
45
|
-
backgroundColor: 'yellow',
|
|
46
|
-
},
|
|
47
|
-
'& .cm-comment-active': {
|
|
48
|
-
backgroundColor: 'orange',
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
const marks = {
|
|
53
|
-
highlight: Decoration.mark({ class: 'cm-comment' }),
|
|
54
|
-
highlightActive: Decoration.mark({ class: 'cm-comment-active' }),
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
// TODO(burdon): Should this be part of state?
|
|
58
|
-
type CommentSelected = {
|
|
59
|
-
active?: string;
|
|
60
|
-
closest?: string;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// TODO(burdon): Rename.
|
|
64
|
-
type ExtendedCommentRange = Range &
|
|
65
|
-
CommentRange & {
|
|
66
|
-
// TODO(burdon): Not part of state; just required for callback.
|
|
67
|
-
location?: Rect | null;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
export type CommentsState = CommentSelected & {
|
|
71
|
-
ranges: ExtendedCommentRange[];
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
export const setCommentRange = StateEffect.define<{ model: EditorModel; comments: CommentRange[] }>();
|
|
75
|
-
|
|
76
|
-
const setSelection = StateEffect.define<CommentSelected>();
|
|
77
|
-
|
|
78
|
-
const setCommentState = StateEffect.define<CommentsState>();
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* State field (reducer) that tracks comment ranges.
|
|
82
|
-
* The ranges are tracked as codemirror ranges (i.e., not relative YJS/Automerge positions), and
|
|
83
|
-
* therefore must be updated when the document changes.
|
|
84
|
-
*/
|
|
85
|
-
const commentsStateField = StateField.define<CommentsState>({
|
|
86
|
-
create: () => ({ ranges: [] }),
|
|
87
|
-
update: (value, tr) => {
|
|
88
|
-
for (const effect of tr.effects) {
|
|
89
|
-
// Update selection.
|
|
90
|
-
if (effect.is(setSelection)) {
|
|
91
|
-
return { ...value, ...effect.value };
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Update range from store.
|
|
95
|
-
if (effect.is(setCommentRange)) {
|
|
96
|
-
const { model, comments } = effect.value;
|
|
97
|
-
const ranges: ExtendedCommentRange[] = comments.map((comment) => {
|
|
98
|
-
const range = model.getRangeFromCursor!(comment.cursor)!;
|
|
99
|
-
return { ...comment, ...range };
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
return { ...value, ranges };
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Update entire state.
|
|
106
|
-
if (effect.is(setCommentState)) {
|
|
107
|
-
return effect.value;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return value;
|
|
112
|
-
},
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Decorate ranges.
|
|
117
|
-
*/
|
|
118
|
-
const highlightDecorations = EditorView.decorations.compute([commentsStateField], (state) => {
|
|
119
|
-
const { active, ranges } = state.field(commentsStateField);
|
|
120
|
-
const decorations =
|
|
121
|
-
sortBy(ranges ?? [], (range) => range.from)
|
|
122
|
-
?.flatMap((selection) => {
|
|
123
|
-
// TODO(burdon): Invalid range (e.g., deleted).
|
|
124
|
-
if (selection.from === selection.to) {
|
|
125
|
-
return undefined;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const range = { from: selection.from, to: selection.to };
|
|
129
|
-
if (selection.id === active) {
|
|
130
|
-
return marks.highlightActive.range(range.from, range.to);
|
|
131
|
-
} else {
|
|
132
|
-
return marks.highlight.range(range.from, range.to);
|
|
133
|
-
}
|
|
134
|
-
})
|
|
135
|
-
.filter(nonNullable) ?? [];
|
|
136
|
-
|
|
137
|
-
return Decoration.set(decorations);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Optional bookmark widget at the start/end of the selection.
|
|
142
|
-
* May correspond to a markdown bookmark.
|
|
143
|
-
*/
|
|
144
|
-
class BookmarkWidget extends WidgetType {
|
|
145
|
-
constructor(
|
|
146
|
-
private readonly _anchor: number,
|
|
147
|
-
private readonly _id: string,
|
|
148
|
-
private readonly _handleClick?: () => void,
|
|
149
|
-
) {
|
|
150
|
-
super();
|
|
151
|
-
invariant(this._id);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
override eq(other: BookmarkWidget) {
|
|
155
|
-
return this._anchor === other._anchor && this._id === other._id;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
override toDOM() {
|
|
159
|
-
const span = document.createElement('span');
|
|
160
|
-
span.className = 'cm-bookmark';
|
|
161
|
-
span.textContent = '※';
|
|
162
|
-
if (this._handleClick) {
|
|
163
|
-
span.onclick = () => this._handleClick!();
|
|
164
|
-
}
|
|
165
|
-
return span;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export type CommentsOptions = {
|
|
170
|
-
key?: string;
|
|
171
|
-
footnote?: boolean;
|
|
172
|
-
/**
|
|
173
|
-
* Called to create a new thread and return the thread id.
|
|
174
|
-
*/
|
|
175
|
-
onCreate?: (range: string) => string | undefined;
|
|
176
|
-
/**
|
|
177
|
-
* Called to notify which thread is currently closest to the cursor.
|
|
178
|
-
*/
|
|
179
|
-
onSelect?: (state: CommentsState) => void;
|
|
180
|
-
/**
|
|
181
|
-
* Called to render tooltip.
|
|
182
|
-
*/
|
|
183
|
-
onHover?: (el: Element) => void;
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Comment threads.
|
|
188
|
-
* 1). Updates the EditorModel to store relative selections for a set of comments threads.
|
|
189
|
-
* Since the selections are relative, they do not need to be updated when the document is edited.
|
|
190
|
-
* 2). Implements a StateField to track absolute selections corresponding to the comments (i.e., when the document is edited).
|
|
191
|
-
* 3). Creates decoration marks to apply classes to each selection.
|
|
192
|
-
* 4). Tracks the current cursor position to:
|
|
193
|
-
* a). Update the decoration to show if the cursor is within a current selection.
|
|
194
|
-
* b). Calls a handler to indicate which is the closest selection (e.g., to update the thread sidebar).
|
|
195
|
-
* 5). Optionally, inserts a markdown footnote when creating a comment thread.
|
|
196
|
-
* 6). Optionally, implements a hoverTooltip to show hints when creating a selection range.
|
|
197
|
-
*/
|
|
198
|
-
export const comments = (options: CommentsOptions = {}): Extension => {
|
|
199
|
-
const handleSelect = debounce((state: CommentsState) => options.onSelect?.(state), 200);
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Create comment thread action.
|
|
203
|
-
*/
|
|
204
|
-
const createCommentThread: Command = (view) => {
|
|
205
|
-
invariant(options.onCreate);
|
|
206
|
-
const { head, from, to } = view.state.selection.main;
|
|
207
|
-
if (from === to) {
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const model = view.state.field(modelState);
|
|
212
|
-
const relPos = model?.getCursorFromRange?.({ from, to });
|
|
213
|
-
if (relPos) {
|
|
214
|
-
// Create thread via callback.
|
|
215
|
-
const id = callbackWrapper(options.onCreate)(relPos);
|
|
216
|
-
if (id) {
|
|
217
|
-
// Update range.
|
|
218
|
-
view.dispatch({
|
|
219
|
-
effects: setSelection.of({ active: id }),
|
|
220
|
-
selection: { anchor: from },
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
// Insert footnote.
|
|
224
|
-
if (options.footnote) {
|
|
225
|
-
const tag = `[^${id}]`;
|
|
226
|
-
view.dispatch({
|
|
227
|
-
changes: { from: head, insert: tag },
|
|
228
|
-
selection: { anchor: head + tag.length },
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
return true;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
return false;
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Bookmark widget decoration.
|
|
241
|
-
*/
|
|
242
|
-
const bookmarksViewPlugin = ViewPlugin.fromClass(
|
|
243
|
-
class BookmarkViewPlugin {
|
|
244
|
-
// Match markdown footnotes (option).
|
|
245
|
-
// https://www.markdownguide.org/extended-syntax/#footnotes
|
|
246
|
-
static bookmarkMatcher = new MatchDecorator({
|
|
247
|
-
regexp: /\[\^(\w+)\]/g,
|
|
248
|
-
decoration: (match, view, pos) => {
|
|
249
|
-
const id = match[1];
|
|
250
|
-
return Decoration.replace({
|
|
251
|
-
id,
|
|
252
|
-
widget: new BookmarkWidget(pos, id),
|
|
253
|
-
});
|
|
254
|
-
},
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
bookmarks: DecorationSet;
|
|
258
|
-
constructor(view: EditorView) {
|
|
259
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.createDeco(view);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
update(update: ViewUpdate) {
|
|
263
|
-
this.bookmarks = BookmarkViewPlugin.bookmarkMatcher.updateDeco(update, this.bookmarks);
|
|
264
|
-
}
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
decorations: (instance) => instance.bookmarks,
|
|
268
|
-
provide: (plugin) =>
|
|
269
|
-
EditorView.atomicRanges.of((view) => {
|
|
270
|
-
return view.plugin(plugin)?.bookmarks || Decoration.none;
|
|
271
|
-
}),
|
|
272
|
-
},
|
|
273
|
-
);
|
|
274
|
-
|
|
275
|
-
return [
|
|
276
|
-
bookmarksViewPlugin,
|
|
277
|
-
commentsStateField,
|
|
278
|
-
highlightDecorations,
|
|
279
|
-
styles,
|
|
280
|
-
|
|
281
|
-
//
|
|
282
|
-
// Keymap.
|
|
283
|
-
//
|
|
284
|
-
options.onCreate
|
|
285
|
-
? keymap.of([
|
|
286
|
-
{
|
|
287
|
-
key: options?.key ?? "meta-'",
|
|
288
|
-
run: callbackWrapper(createCommentThread),
|
|
289
|
-
},
|
|
290
|
-
])
|
|
291
|
-
: [],
|
|
292
|
-
|
|
293
|
-
//
|
|
294
|
-
// Hover tooltip (for key shortcut hints, etc.)
|
|
295
|
-
// TODO(burdon): Factor out to generic hints extension for current selection/line.
|
|
296
|
-
//
|
|
297
|
-
options.onHover
|
|
298
|
-
? hoverTooltip(
|
|
299
|
-
(view, pos) => {
|
|
300
|
-
const selection = view.state.selection.main;
|
|
301
|
-
if (selection && pos >= selection.from && pos <= selection.to) {
|
|
302
|
-
return {
|
|
303
|
-
pos: selection.from,
|
|
304
|
-
end: selection.to,
|
|
305
|
-
above: true,
|
|
306
|
-
create: () => {
|
|
307
|
-
// TODO(burdon): Dispatch to react callback to render (or use SSR)?
|
|
308
|
-
const el = document.createElement('div');
|
|
309
|
-
options.onHover?.(el);
|
|
310
|
-
return { dom: el, offset: { x: 0, y: 8 } };
|
|
311
|
-
},
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return null;
|
|
316
|
-
},
|
|
317
|
-
{ hideOnChange: true, hoverTime: 1000 },
|
|
318
|
-
)
|
|
319
|
-
: [],
|
|
320
|
-
|
|
321
|
-
//
|
|
322
|
-
// Monitor cursor movement and text updates.
|
|
323
|
-
// TODO(burdon): Is there a better (finer grained) way to do this?
|
|
324
|
-
//
|
|
325
|
-
EditorView.updateListener.of(({ view, state, startState, changes }) => {
|
|
326
|
-
//
|
|
327
|
-
// Test if need to recompute indexed range if document changes before the end of the range.
|
|
328
|
-
//
|
|
329
|
-
{
|
|
330
|
-
let mod = false;
|
|
331
|
-
const model = state.field(modelState);
|
|
332
|
-
const { active, ranges } = state.field(commentsStateField);
|
|
333
|
-
changes.iterChanges((from, to, from2, to2) => {
|
|
334
|
-
invariant(model);
|
|
335
|
-
ranges.forEach((range) => {
|
|
336
|
-
if (from2 === to2) {
|
|
337
|
-
const newRange = model.getRangeFromCursor!(range.cursor);
|
|
338
|
-
if (newRange.to - newRange.from === 0) {
|
|
339
|
-
// TODO(burdon): Delete range if empty.
|
|
340
|
-
log.info('deleted comment', { thread: range.id });
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
if (from <= range.to) {
|
|
345
|
-
const newRange = model.getRangeFromCursor!(range.cursor);
|
|
346
|
-
Object.assign(range, newRange);
|
|
347
|
-
mod = true;
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
});
|
|
351
|
-
|
|
352
|
-
if (mod) {
|
|
353
|
-
view.dispatch({ effects: setCommentState.of({ active, ranges }) });
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
//
|
|
358
|
-
// Track the current selection.
|
|
359
|
-
//
|
|
360
|
-
{
|
|
361
|
-
const { head } = state.selection.main;
|
|
362
|
-
|
|
363
|
-
let min = Infinity;
|
|
364
|
-
const { active, closest, ranges } = state.field(commentsStateField);
|
|
365
|
-
const selected: CommentSelected = { active: undefined, closest: undefined };
|
|
366
|
-
ranges.forEach((comment) => {
|
|
367
|
-
const d = Math.min(Math.abs(head - comment.from), Math.abs(head - comment.to));
|
|
368
|
-
if (head >= comment.from && head <= comment.to) {
|
|
369
|
-
selected.active = comment.id;
|
|
370
|
-
}
|
|
371
|
-
if (d < min) {
|
|
372
|
-
selected.closest = comment.id;
|
|
373
|
-
min = d;
|
|
374
|
-
}
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
if (selected.active !== active || selected.closest !== closest) {
|
|
378
|
-
view.dispatch({ effects: setSelection.of(selected) });
|
|
379
|
-
|
|
380
|
-
// Update callback.
|
|
381
|
-
handleSelect({
|
|
382
|
-
...selected,
|
|
383
|
-
ranges: ranges.map((range) => ({ ...range, location: view.coordsAtPos(range.from) })),
|
|
384
|
-
});
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}),
|
|
388
|
-
];
|
|
389
|
-
};
|