mobx-keystone-yjs 1.5.4 → 1.5.5
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/CHANGELOG.md +7 -0
- package/dist/mobx-keystone-yjs.esm.js +197 -139
- package/dist/mobx-keystone-yjs.esm.mjs +197 -139
- package/dist/mobx-keystone-yjs.umd.js +197 -139
- package/dist/types/binding/YjsTextModel.d.ts +5 -4
- package/dist/types/binding/applyMobxKeystonePatchToYjsObject.d.ts +1 -1
- package/dist/types/binding/bindYjsToMobxKeystone.d.ts +1 -1
- package/dist/types/binding/convertJsonToYjsData.d.ts +2 -2
- package/dist/types/binding/convertYjsDataToJson.d.ts +1 -1
- package/dist/types/binding/convertYjsEventToPatches.d.ts +1 -1
- package/dist/types/binding/yjsBindingContext.d.ts +2 -2
- package/dist/types/index.d.ts +6 -6
- package/dist/types/utils/isYjsValueDeleted.d.ts +7 -0
- package/package.json +26 -16
- package/src/binding/YjsTextModel.ts +280 -247
- package/src/binding/applyMobxKeystonePatchToYjsObject.ts +6 -1
- package/src/binding/bindYjsToMobxKeystone.ts +19 -9
- package/src/binding/convertJsonToYjsData.ts +29 -32
- package/src/binding/convertYjsDataToJson.ts +1 -1
- package/src/binding/convertYjsEventToPatches.ts +4 -12
- package/src/index.ts +2 -2
- package/src/utils/isYjsValueDeleted.ts +14 -0
|
@@ -1,247 +1,280 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
Frozen,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
model,
|
|
8
|
-
onSnapshot,
|
|
9
|
-
tProp,
|
|
10
|
-
types,
|
|
11
|
-
} from "mobx-keystone"
|
|
12
|
-
import * as Y from "yjs"
|
|
13
|
-
import { failure } from "../utils/error"
|
|
14
|
-
import {
|
|
15
|
-
import { resolveYjsPath } from "./resolveYjsPath"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
*
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
1
|
+
import { computed, createAtom, IAtom, observe, reaction } from "mobx"
|
|
2
|
+
import {
|
|
3
|
+
Frozen,
|
|
4
|
+
frozen,
|
|
5
|
+
getParentToChildPath,
|
|
6
|
+
Model,
|
|
7
|
+
model,
|
|
8
|
+
onSnapshot,
|
|
9
|
+
tProp,
|
|
10
|
+
types,
|
|
11
|
+
} from "mobx-keystone"
|
|
12
|
+
import * as Y from "yjs"
|
|
13
|
+
import { failure } from "../utils/error"
|
|
14
|
+
import { isYjsValueDeleted } from "../utils/isYjsValueDeleted"
|
|
15
|
+
import { resolveYjsPath } from "./resolveYjsPath"
|
|
16
|
+
import { YjsBindingContext, yjsBindingContext } from "./yjsBindingContext"
|
|
17
|
+
|
|
18
|
+
// Delta[][], since each single change is a Delta[]
|
|
19
|
+
// we use frozen so that we can reuse each delta change
|
|
20
|
+
const deltaListType = types.array(types.frozen(types.unchecked<unknown[]>()))
|
|
21
|
+
|
|
22
|
+
export const yjsTextModelId = "mobx-keystone-yjs/YjsTextModel"
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A mobx-keystone model that represents a Yjs.Text object.
|
|
26
|
+
*/
|
|
27
|
+
@model(yjsTextModelId)
|
|
28
|
+
export class YjsTextModel extends Model({
|
|
29
|
+
deltaList: tProp(deltaListType, () => []),
|
|
30
|
+
}) {
|
|
31
|
+
/**
|
|
32
|
+
* Helper function to create a YjsTextModel instance with a simple text.
|
|
33
|
+
*/
|
|
34
|
+
static withText(text: string): YjsTextModel {
|
|
35
|
+
return new DecoratedYjsTextModel({
|
|
36
|
+
deltaList: [
|
|
37
|
+
frozen([
|
|
38
|
+
{
|
|
39
|
+
insert: text,
|
|
40
|
+
},
|
|
41
|
+
]),
|
|
42
|
+
],
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The Y.js path from the bound object to the YjsTextModel instance.
|
|
48
|
+
*/
|
|
49
|
+
@computed
|
|
50
|
+
private get _yjsObjectPath() {
|
|
51
|
+
const ctx = yjsBindingContext.get(this)
|
|
52
|
+
if (ctx?.boundObject == null) {
|
|
53
|
+
throw failure(
|
|
54
|
+
"the YjsTextModel instance must be part of a bound object before it can be accessed"
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const path = getParentToChildPath(ctx.boundObject, this)
|
|
59
|
+
if (!path) {
|
|
60
|
+
throw failure("a path from the bound object to the YjsTextModel instance is not available")
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return path
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The Yjs.Text object present at this mobx-keystone node's path.
|
|
68
|
+
*/
|
|
69
|
+
@computed
|
|
70
|
+
private get _yjsObjectAtPath(): unknown {
|
|
71
|
+
const path = this._yjsObjectPath
|
|
72
|
+
|
|
73
|
+
const ctx = yjsBindingContext.get(this)!
|
|
74
|
+
|
|
75
|
+
return resolveYjsPath(ctx.yjsObject, path)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The Yjs.Text object represented by this mobx-keystone node.
|
|
80
|
+
*/
|
|
81
|
+
@computed
|
|
82
|
+
get yjsText(): Y.Text {
|
|
83
|
+
const yjsObject = this._yjsObjectAtPath
|
|
84
|
+
|
|
85
|
+
if (!(yjsObject instanceof Y.Text)) {
|
|
86
|
+
throw failure(`Y.Text was expected at path ${JSON.stringify(this._yjsObjectPath)}`)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return yjsObject
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Atom that gets changed when the associated Y.js text changes.
|
|
94
|
+
*/
|
|
95
|
+
yjsTextChangedAtom = createAtom("yjsTextChangedAtom")
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* The text value of the Yjs.Text object.
|
|
99
|
+
* Shortcut for `yjsText.toString()`, but computed.
|
|
100
|
+
*/
|
|
101
|
+
@computed
|
|
102
|
+
get text(): string {
|
|
103
|
+
this.yjsTextChangedAtom.reportObserved()
|
|
104
|
+
|
|
105
|
+
const ctx = yjsBindingContext.get(this)
|
|
106
|
+
if (ctx?.boundObject != null) {
|
|
107
|
+
try {
|
|
108
|
+
const yjsTextString = this.yjsText.toString()
|
|
109
|
+
// if the yjsText is detached, toString() returns an empty string
|
|
110
|
+
// in that case we should use the deltaList as a fallback
|
|
111
|
+
if (yjsTextString !== "" || this.deltaList.length === 0) {
|
|
112
|
+
return yjsTextString
|
|
113
|
+
}
|
|
114
|
+
} catch {
|
|
115
|
+
// fall back
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// fall back to deltaList
|
|
120
|
+
return this.deltaListToText()
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private deltaListToText(): string {
|
|
124
|
+
const doc = new Y.Doc()
|
|
125
|
+
const text = doc.getText()
|
|
126
|
+
this.deltaList.forEach((d) => {
|
|
127
|
+
text.applyDelta(d.data)
|
|
128
|
+
})
|
|
129
|
+
return text.toString()
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
protected onInit() {
|
|
133
|
+
const shouldReplicateToYjs = (ctx: YjsBindingContext | undefined): ctx is YjsBindingContext => {
|
|
134
|
+
return !!ctx && !!ctx.boundObject && !ctx.isApplyingYjsChangesToMobxKeystone
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let reapplyDeltasToYjsText = false
|
|
138
|
+
const newDeltas: Frozen<unknown[]>[] = []
|
|
139
|
+
|
|
140
|
+
let disposeObserveDeltaList: (() => void) | undefined
|
|
141
|
+
|
|
142
|
+
const disposeReactionToDeltaListRefChange = reaction(
|
|
143
|
+
() => this.$.deltaList,
|
|
144
|
+
(deltaList) => {
|
|
145
|
+
disposeObserveDeltaList?.()
|
|
146
|
+
disposeObserveDeltaList = undefined
|
|
147
|
+
|
|
148
|
+
disposeObserveDeltaList = observe(deltaList, (change) => {
|
|
149
|
+
if (reapplyDeltasToYjsText) {
|
|
150
|
+
// already gonna replace them all
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
if (!shouldReplicateToYjs(yjsBindingContext.get(this))) {
|
|
154
|
+
// yjs text is already up to date with these changes
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (
|
|
159
|
+
change.type === "splice" &&
|
|
160
|
+
change.removedCount === 0 &&
|
|
161
|
+
change.addedCount > 0 &&
|
|
162
|
+
change.index === this.deltaList.length
|
|
163
|
+
) {
|
|
164
|
+
// optimization, just adding new ones to the end
|
|
165
|
+
newDeltas.push(...change.added)
|
|
166
|
+
} else {
|
|
167
|
+
// any other change, we need to reapply all deltas
|
|
168
|
+
reapplyDeltasToYjsText = true
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
},
|
|
172
|
+
{ fireImmediately: true }
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
const disposeOnSnapshot = onSnapshot(this, () => {
|
|
176
|
+
try {
|
|
177
|
+
if (reapplyDeltasToYjsText) {
|
|
178
|
+
const ctx = yjsBindingContext.get(this)
|
|
179
|
+
|
|
180
|
+
if (shouldReplicateToYjs(ctx)) {
|
|
181
|
+
const { yjsText } = this
|
|
182
|
+
if (isYjsValueDeleted(yjsText)) {
|
|
183
|
+
throw failure("cannot reapply deltas to deleted Yjs.Text")
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
ctx.yjsDoc.transact(() => {
|
|
187
|
+
// didn't find a better way than this to reapply all deltas
|
|
188
|
+
// without having to re-create the Y.Text object
|
|
189
|
+
if (yjsText.length > 0) {
|
|
190
|
+
yjsText.delete(0, yjsText.length)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
this.deltaList.forEach((frozenDeltas) => {
|
|
194
|
+
yjsText.applyDelta(frozenDeltas.data)
|
|
195
|
+
})
|
|
196
|
+
}, ctx.yjsOrigin)
|
|
197
|
+
}
|
|
198
|
+
} else if (newDeltas.length > 0) {
|
|
199
|
+
const ctx = yjsBindingContext.get(this)
|
|
200
|
+
|
|
201
|
+
if (shouldReplicateToYjs(ctx)) {
|
|
202
|
+
const { yjsText } = this
|
|
203
|
+
if (isYjsValueDeleted(yjsText)) {
|
|
204
|
+
throw failure("cannot reapply deltas to deleted Yjs.Text")
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
ctx.yjsDoc.transact(() => {
|
|
208
|
+
newDeltas.forEach((frozenDeltas) => {
|
|
209
|
+
yjsText.applyDelta(frozenDeltas.data)
|
|
210
|
+
})
|
|
211
|
+
}, ctx.yjsOrigin)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
} finally {
|
|
215
|
+
reapplyDeltasToYjsText = false
|
|
216
|
+
newDeltas.length = 0
|
|
217
|
+
}
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
const diposeYjsTextChangedAtom = hookYjsTextChangedAtom(
|
|
221
|
+
() => this.yjsText,
|
|
222
|
+
this.yjsTextChangedAtom
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
return () => {
|
|
226
|
+
disposeOnSnapshot()
|
|
227
|
+
disposeReactionToDeltaListRefChange()
|
|
228
|
+
disposeObserveDeltaList?.()
|
|
229
|
+
disposeObserveDeltaList = undefined
|
|
230
|
+
|
|
231
|
+
diposeYjsTextChangedAtom()
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// we use this trick just to avoid a babel bug that causes classes used inside classes not to be overriden
|
|
237
|
+
// by the decorator
|
|
238
|
+
const DecoratedYjsTextModel = YjsTextModel
|
|
239
|
+
|
|
240
|
+
function hookYjsTextChangedAtom(getYjsText: () => Y.Text, textChangedAtom: IAtom) {
|
|
241
|
+
let disposeObserveYjsText: (() => void) | undefined
|
|
242
|
+
|
|
243
|
+
const observeFn = () => {
|
|
244
|
+
textChangedAtom.reportChanged()
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const disposeReactionToYTextChange = reaction(
|
|
248
|
+
() => {
|
|
249
|
+
try {
|
|
250
|
+
const yjsText = getYjsText()
|
|
251
|
+
return isYjsValueDeleted(yjsText) ? undefined : yjsText
|
|
252
|
+
} catch {
|
|
253
|
+
return undefined
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
(yjsText) => {
|
|
257
|
+
disposeObserveYjsText?.()
|
|
258
|
+
disposeObserveYjsText = undefined
|
|
259
|
+
|
|
260
|
+
if (yjsText) {
|
|
261
|
+
yjsText.observe(observeFn)
|
|
262
|
+
|
|
263
|
+
disposeObserveYjsText = () => {
|
|
264
|
+
yjsText.unobserve(observeFn)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
textChangedAtom.reportChanged()
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
fireImmediately: true,
|
|
272
|
+
}
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
return () => {
|
|
276
|
+
disposeReactionToYTextChange()
|
|
277
|
+
disposeObserveYjsText?.()
|
|
278
|
+
disposeObserveYjsText = undefined
|
|
279
|
+
}
|
|
280
|
+
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { Patch } from "mobx-keystone"
|
|
2
2
|
import * as Y from "yjs"
|
|
3
|
+
import { PlainValue } from "../plainTypes"
|
|
3
4
|
import { failure } from "../utils/error"
|
|
5
|
+
import { isYjsValueDeleted } from "../utils/isYjsValueDeleted"
|
|
4
6
|
import { convertJsonToYjsData } from "./convertJsonToYjsData"
|
|
5
|
-
import { PlainValue } from "../plainTypes"
|
|
6
7
|
|
|
7
8
|
export function applyMobxKeystonePatchToYjsObject(patch: Patch, yjs: unknown): void {
|
|
9
|
+
if (isYjsValueDeleted(yjs)) {
|
|
10
|
+
throw failure("cannot apply patch to deleted Yjs value")
|
|
11
|
+
}
|
|
12
|
+
|
|
8
13
|
if (patch.path.length > 1) {
|
|
9
14
|
const [key, ...rest] = patch.path
|
|
10
15
|
|
|
@@ -3,19 +3,20 @@ import {
|
|
|
3
3
|
AnyDataModel,
|
|
4
4
|
AnyModel,
|
|
5
5
|
AnyStandardType,
|
|
6
|
-
ModelClass,
|
|
7
|
-
Patch,
|
|
8
|
-
SnapshotInOf,
|
|
9
|
-
TypeToData,
|
|
10
6
|
applyPatches,
|
|
11
7
|
fromSnapshot,
|
|
12
8
|
getParentToChildPath,
|
|
9
|
+
ModelClass,
|
|
13
10
|
onGlobalPatches,
|
|
14
11
|
onPatches,
|
|
15
12
|
onSnapshot,
|
|
13
|
+
Patch,
|
|
14
|
+
SnapshotInOf,
|
|
15
|
+
TypeToData,
|
|
16
16
|
} from "mobx-keystone"
|
|
17
17
|
import * as Y from "yjs"
|
|
18
18
|
import { getYjsCollectionAtom } from "../utils/getOrCreateYjsCollectionAtom"
|
|
19
|
+
import { isYjsValueDeleted } from "../utils/isYjsValueDeleted"
|
|
19
20
|
import { applyMobxKeystonePatchToYjsObject } from "./applyMobxKeystonePatchToYjsObject"
|
|
20
21
|
import { convertYjsDataToJson } from "./convertYjsDataToJson"
|
|
21
22
|
import { convertYjsEventToPatches } from "./convertYjsEventToPatches"
|
|
@@ -140,6 +141,10 @@ export function bindYjsToMobxKeystone<
|
|
|
140
141
|
const arrayOfArrayOfPatches = pendingArrayOfArrayOfPatches
|
|
141
142
|
pendingArrayOfArrayOfPatches = []
|
|
142
143
|
|
|
144
|
+
if (isYjsValueDeleted(yjsObject)) {
|
|
145
|
+
return
|
|
146
|
+
}
|
|
147
|
+
|
|
143
148
|
yjsDoc.transact(() => {
|
|
144
149
|
arrayOfArrayOfPatches.forEach((arrayOfPatches) => {
|
|
145
150
|
arrayOfPatches.forEach((patch) => {
|
|
@@ -180,13 +185,18 @@ export function bindYjsToMobxKeystone<
|
|
|
180
185
|
})
|
|
181
186
|
}, yjsOrigin)
|
|
182
187
|
|
|
188
|
+
const dispose = () => {
|
|
189
|
+
yjsDoc.off("destroy", dispose)
|
|
190
|
+
disposeOnPatches()
|
|
191
|
+
disposeOnSnapshot()
|
|
192
|
+
yjsObject.unobserveDeep(observeDeepCb)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
yjsDoc.on("destroy", dispose)
|
|
196
|
+
|
|
183
197
|
return {
|
|
184
198
|
boundObject,
|
|
185
|
-
dispose
|
|
186
|
-
disposeOnPatches()
|
|
187
|
-
disposeOnSnapshot()
|
|
188
|
-
yjsObject.unobserveDeep(observeDeepCb)
|
|
189
|
-
},
|
|
199
|
+
dispose,
|
|
190
200
|
yjsOrigin,
|
|
191
201
|
}
|
|
192
202
|
}
|