@lexical/yjs 0.44.1-nightly.20260518.0 → 0.45.0

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 (37) hide show
  1. package/{LexicalYjs.dev.js → dist/LexicalYjs.dev.js} +1 -1
  2. package/{LexicalYjs.dev.mjs → dist/LexicalYjs.dev.mjs} +1 -1
  3. package/{RenderSnapshot.d.ts → dist/RenderSnapshot.d.ts} +0 -7
  4. package/dist/simpleDiffWithCursor.d.ts +12 -0
  5. package/package.json +31 -16
  6. package/src/Bindings.ts +135 -0
  7. package/src/CollabDecoratorNode.ts +112 -0
  8. package/src/CollabElementNode.ts +696 -0
  9. package/src/CollabLineBreakNode.ts +70 -0
  10. package/src/CollabTextNode.ts +179 -0
  11. package/src/CollabV2Mapping.ts +117 -0
  12. package/src/RenderSnapshot.ts +97 -0
  13. package/src/SyncCursors.ts +823 -0
  14. package/src/SyncEditorStates.ts +469 -0
  15. package/src/SyncV2.ts +871 -0
  16. package/src/Utils.ts +648 -0
  17. package/src/index.ts +151 -0
  18. package/src/simpleDiffWithCursor.ts +49 -0
  19. package/src/types.ts +27 -0
  20. /package/{Bindings.d.ts → dist/Bindings.d.ts} +0 -0
  21. /package/{CollabDecoratorNode.d.ts → dist/CollabDecoratorNode.d.ts} +0 -0
  22. /package/{CollabElementNode.d.ts → dist/CollabElementNode.d.ts} +0 -0
  23. /package/{CollabLineBreakNode.d.ts → dist/CollabLineBreakNode.d.ts} +0 -0
  24. /package/{CollabTextNode.d.ts → dist/CollabTextNode.d.ts} +0 -0
  25. /package/{CollabV2Mapping.d.ts → dist/CollabV2Mapping.d.ts} +0 -0
  26. /package/{LexicalYjs.js → dist/LexicalYjs.js} +0 -0
  27. /package/{LexicalYjs.js.flow → dist/LexicalYjs.js.flow} +0 -0
  28. /package/{LexicalYjs.mjs → dist/LexicalYjs.mjs} +0 -0
  29. /package/{LexicalYjs.node.mjs → dist/LexicalYjs.node.mjs} +0 -0
  30. /package/{LexicalYjs.prod.js → dist/LexicalYjs.prod.js} +0 -0
  31. /package/{LexicalYjs.prod.mjs → dist/LexicalYjs.prod.mjs} +0 -0
  32. /package/{SyncCursors.d.ts → dist/SyncCursors.d.ts} +0 -0
  33. /package/{SyncEditorStates.d.ts → dist/SyncEditorStates.d.ts} +0 -0
  34. /package/{SyncV2.d.ts → dist/SyncV2.d.ts} +0 -0
  35. /package/{Utils.d.ts → dist/Utils.d.ts} +0 -0
  36. /package/{index.d.ts → dist/index.d.ts} +0 -0
  37. /package/{types.d.ts → dist/types.d.ts} +0 -0
@@ -1837,7 +1837,7 @@ const renderSnapshot__EXPERIMENTAL = (binding, snapshot = yjs.snapshot(binding.d
1837
1837
  }
1838
1838
  doc.transact(transaction => {
1839
1839
  // Before rendering, we are going to sanitize ops and split deleted ops
1840
- // if they were deleted by seperate users.
1840
+ // if they were deleted by separate users.
1841
1841
  const pud = new yjs.PermanentUserData(doc);
1842
1842
  if (pud) {
1843
1843
  pud.dss.forEach(ds => {
@@ -1835,7 +1835,7 @@ const renderSnapshot__EXPERIMENTAL = (binding, snapshot$1 = snapshot(binding.doc
1835
1835
  }
1836
1836
  doc.transact(transaction => {
1837
1837
  // Before rendering, we are going to sanitize ops and split deleted ops
1838
- // if they were deleted by seperate users.
1838
+ // if they were deleted by separate users.
1839
1839
  const pud = new PermanentUserData(doc);
1840
1840
  if (pud) {
1841
1841
  pud.dss.forEach(ds => {
@@ -1,10 +1,3 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- */
8
1
  import { LexicalNode } from 'lexical';
9
2
  import { ID, Snapshot } from 'yjs';
10
3
  import { BindingV2 } from './Bindings';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+ export default function simpleDiffWithCursor(a: string, b: string, cursor: number): {
9
+ index: number;
10
+ insert: string;
11
+ remove: number;
12
+ };
package/package.json CHANGED
@@ -11,12 +11,13 @@
11
11
  "crdt"
12
12
  ],
13
13
  "license": "MIT",
14
- "version": "0.44.1-nightly.20260518.0",
15
- "main": "LexicalYjs.js",
16
- "types": "index.d.ts",
14
+ "version": "0.45.0",
15
+ "main": "./dist/LexicalYjs.js",
16
+ "types": "./dist/index.d.ts",
17
17
  "dependencies": {
18
- "@lexical/selection": "0.44.1-nightly.20260518.0",
19
- "lexical": "0.44.1-nightly.20260518.0"
18
+ "@lexical/internal": "0.45.0",
19
+ "@lexical/selection": "0.45.0",
20
+ "lexical": "0.45.0"
20
21
  },
21
22
  "devDependencies": {
22
23
  "yjs": "^13.6.30"
@@ -29,23 +30,37 @@
29
30
  "url": "git+https://github.com/facebook/lexical.git",
30
31
  "directory": "packages/lexical-yjs"
31
32
  },
32
- "module": "LexicalYjs.mjs",
33
+ "module": "./dist/LexicalYjs.mjs",
33
34
  "sideEffects": false,
34
35
  "exports": {
35
36
  ".": {
37
+ "source": "./src/index.ts",
36
38
  "import": {
37
- "types": "./index.d.ts",
38
- "development": "./LexicalYjs.dev.mjs",
39
- "production": "./LexicalYjs.prod.mjs",
40
- "node": "./LexicalYjs.node.mjs",
41
- "default": "./LexicalYjs.mjs"
39
+ "types": "./dist/index.d.ts",
40
+ "development": "./dist/LexicalYjs.dev.mjs",
41
+ "production": "./dist/LexicalYjs.prod.mjs",
42
+ "node": "./dist/LexicalYjs.node.mjs",
43
+ "default": "./dist/LexicalYjs.mjs"
42
44
  },
43
45
  "require": {
44
- "types": "./index.d.ts",
45
- "development": "./LexicalYjs.dev.js",
46
- "production": "./LexicalYjs.prod.js",
47
- "default": "./LexicalYjs.js"
46
+ "types": "./dist/index.d.ts",
47
+ "development": "./dist/LexicalYjs.dev.js",
48
+ "production": "./dist/LexicalYjs.prod.js",
49
+ "default": "./dist/LexicalYjs.js"
48
50
  }
49
51
  }
50
- }
52
+ },
53
+ "files": [
54
+ "dist",
55
+ "src",
56
+ "!src/__tests__",
57
+ "!src/__bench__",
58
+ "!src/__mocks__",
59
+ "!src/**/*.test.ts",
60
+ "!src/**/*.test.tsx",
61
+ "!src/**/*.bench.ts",
62
+ "!src/**/*.bench.tsx",
63
+ "README.md",
64
+ "LICENSE"
65
+ ]
51
66
  }
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import type {CollabDecoratorNode} from './CollabDecoratorNode';
10
+ import type {CollabElementNode} from './CollabElementNode';
11
+ import type {CollabLineBreakNode} from './CollabLineBreakNode';
12
+ import type {CollabTextNode} from './CollabTextNode';
13
+ import type {Cursor} from './SyncCursors';
14
+ import type {LexicalEditor, NodeKey} from 'lexical';
15
+
16
+ import invariant from '@lexical/internal/invariant';
17
+ import {Klass, LexicalNode} from 'lexical';
18
+ import {Doc, XmlElement, XmlText} from 'yjs';
19
+
20
+ import {Provider} from '.';
21
+ import {$createCollabElementNode} from './CollabElementNode';
22
+ import {CollabV2Mapping} from './CollabV2Mapping';
23
+ import {initializeNodeProperties} from './Utils';
24
+
25
+ export type ClientID = number;
26
+ export interface BaseBinding {
27
+ clientID: number;
28
+ cursors: Map<ClientID, Cursor>;
29
+ cursorsContainer: null | HTMLElement;
30
+ doc: Doc;
31
+ docMap: Map<string, Doc>;
32
+ editor: LexicalEditor;
33
+ id: string;
34
+ nodeProperties: Map<string, {[property: string]: unknown}>; // node type to property to default value
35
+ excludedProperties: ExcludedProperties;
36
+ }
37
+
38
+ export interface Binding extends BaseBinding {
39
+ collabNodeMap: Map<
40
+ NodeKey,
41
+ | CollabElementNode
42
+ | CollabTextNode
43
+ | CollabDecoratorNode
44
+ | CollabLineBreakNode
45
+ >;
46
+ root: CollabElementNode;
47
+ }
48
+
49
+ export interface BindingV2 extends BaseBinding {
50
+ mapping: CollabV2Mapping;
51
+ root: XmlElement;
52
+ }
53
+
54
+ export type AnyBinding = Binding | BindingV2;
55
+
56
+ export type ExcludedProperties = Map<Klass<LexicalNode>, Set<string>>;
57
+
58
+ function createBaseBinding(
59
+ editor: LexicalEditor,
60
+ id: string,
61
+ doc: Doc | null | undefined,
62
+ docMap: Map<string, Doc>,
63
+ excludedProperties?: ExcludedProperties,
64
+ ): BaseBinding {
65
+ invariant(
66
+ doc !== undefined && doc !== null,
67
+ 'createBinding: doc is null or undefined',
68
+ );
69
+ const binding = {
70
+ clientID: doc.clientID,
71
+ cursors: new Map(),
72
+ cursorsContainer: null,
73
+ doc,
74
+ docMap,
75
+ editor,
76
+ excludedProperties: excludedProperties || new Map(),
77
+ id,
78
+ nodeProperties: new Map(),
79
+ };
80
+ initializeNodeProperties(binding);
81
+ return binding;
82
+ }
83
+
84
+ export function createBinding(
85
+ editor: LexicalEditor,
86
+ provider: Provider,
87
+ id: string,
88
+ doc: Doc | null | undefined,
89
+ docMap: Map<string, Doc>,
90
+ excludedProperties?: ExcludedProperties,
91
+ ): Binding {
92
+ invariant(
93
+ doc !== undefined && doc !== null,
94
+ 'createBinding: doc is null or undefined',
95
+ );
96
+ const rootXmlText = doc.get('root', XmlText) as XmlText;
97
+ const root: CollabElementNode = $createCollabElementNode(
98
+ rootXmlText,
99
+ null,
100
+ 'root',
101
+ );
102
+ root._key = 'root';
103
+ return {
104
+ ...createBaseBinding(editor, id, doc, docMap, excludedProperties),
105
+ collabNodeMap: new Map(),
106
+ root,
107
+ };
108
+ }
109
+
110
+ export function createBindingV2__EXPERIMENTAL(
111
+ editor: LexicalEditor,
112
+ id: string,
113
+ doc: Doc | null | undefined,
114
+ docMap: Map<string, Doc>,
115
+ options: {excludedProperties?: ExcludedProperties; rootName?: string} = {},
116
+ ): BindingV2 {
117
+ invariant(
118
+ doc !== undefined && doc !== null,
119
+ 'createBinding: doc is null or undefined',
120
+ );
121
+ const {excludedProperties, rootName = 'root-v2'} = options;
122
+ return {
123
+ ...createBaseBinding(editor, id, doc, docMap, excludedProperties),
124
+ mapping: new CollabV2Mapping(),
125
+ root: doc.get(rootName, XmlElement) as XmlElement,
126
+ };
127
+ }
128
+
129
+ export function isBindingV1(binding: BaseBinding): binding is Binding {
130
+ return Object.prototype.hasOwnProperty.call(binding, 'collabNodeMap');
131
+ }
132
+
133
+ export function isBindingV2(binding: BaseBinding): binding is BindingV2 {
134
+ return Object.prototype.hasOwnProperty.call(binding, 'mapping');
135
+ }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import type {Binding} from '.';
10
+ import type {CollabElementNode} from './CollabElementNode';
11
+ import type {DecoratorNode, NodeKey, NodeMap} from 'lexical';
12
+ import type {XmlElement} from 'yjs';
13
+
14
+ import invariant from '@lexical/internal/invariant';
15
+ import {$getNodeByKey, $isDecoratorNode} from 'lexical';
16
+
17
+ import {$syncPropertiesFromYjs, syncPropertiesFromLexical} from './Utils';
18
+
19
+ export class CollabDecoratorNode {
20
+ _xmlElem: XmlElement;
21
+ _key: NodeKey;
22
+ _parent: CollabElementNode;
23
+ _type: string;
24
+
25
+ constructor(xmlElem: XmlElement, parent: CollabElementNode, type: string) {
26
+ this._key = '';
27
+ this._xmlElem = xmlElem;
28
+ this._parent = parent;
29
+ this._type = type;
30
+ }
31
+
32
+ getPrevNode(nodeMap: null | NodeMap): null | DecoratorNode<unknown> {
33
+ if (nodeMap === null) {
34
+ return null;
35
+ }
36
+
37
+ const node = nodeMap.get(this._key);
38
+ return $isDecoratorNode(node) ? node : null;
39
+ }
40
+
41
+ getNode(): null | DecoratorNode<unknown> {
42
+ const node = $getNodeByKey(this._key);
43
+ return $isDecoratorNode(node) ? node : null;
44
+ }
45
+
46
+ getSharedType(): XmlElement {
47
+ return this._xmlElem;
48
+ }
49
+
50
+ getType(): string {
51
+ return this._type;
52
+ }
53
+
54
+ getKey(): NodeKey {
55
+ return this._key;
56
+ }
57
+
58
+ getSize(): number {
59
+ return 1;
60
+ }
61
+
62
+ getOffset(): number {
63
+ const collabElementNode = this._parent;
64
+ return collabElementNode.getChildOffset(this);
65
+ }
66
+
67
+ syncPropertiesFromLexical(
68
+ binding: Binding,
69
+ nextLexicalNode: DecoratorNode<unknown>,
70
+ prevNodeMap: null | NodeMap,
71
+ ): void {
72
+ const prevLexicalNode = this.getPrevNode(prevNodeMap);
73
+ const xmlElem = this._xmlElem;
74
+
75
+ syncPropertiesFromLexical(
76
+ binding,
77
+ xmlElem,
78
+ prevLexicalNode,
79
+ nextLexicalNode,
80
+ );
81
+ }
82
+
83
+ syncPropertiesFromYjs(
84
+ binding: Binding,
85
+ keysChanged: null | Set<string>,
86
+ ): void {
87
+ const lexicalNode = this.getNode();
88
+ invariant(
89
+ lexicalNode !== null,
90
+ 'syncPropertiesFromYjs: could not find decorator node',
91
+ );
92
+ const xmlElem = this._xmlElem;
93
+ $syncPropertiesFromYjs(binding, xmlElem, lexicalNode, keysChanged);
94
+ }
95
+
96
+ destroy(binding: Binding): void {
97
+ const collabNodeMap = binding.collabNodeMap;
98
+ if (collabNodeMap.get(this._key) === this) {
99
+ collabNodeMap.delete(this._key);
100
+ }
101
+ }
102
+ }
103
+
104
+ export function $createCollabDecoratorNode(
105
+ xmlElem: XmlElement,
106
+ parent: CollabElementNode,
107
+ type: string,
108
+ ): CollabDecoratorNode {
109
+ const collabNode = new CollabDecoratorNode(xmlElem, parent, type);
110
+ xmlElem._collabNode = collabNode;
111
+ return collabNode;
112
+ }