@voltro/local-first 0.52.0 → 0.54.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.
package/dist/react.js CHANGED
@@ -1,19 +1,19 @@
1
- import { a as e, c as t, f as n, i as r, l as i, n as a, r as o, s, t as c } from "./room-wFNUwEgi.js";
1
+ import { a as e, c as t, i as n, l as r, n as i, p as a, r as o, s, t as c } from "./room-24dGMM80.js";
2
2
  import { useCallback as l, useEffect as u, useMemo as d, useReducer as f, useRef as p, useState as m } from "react";
3
3
  //#region src/react/useSyncQueue.ts
4
4
  var h = (e = !0) => {
5
- let [n, r] = f(i, e, s), a = l((e) => {
6
- r({
5
+ let [n, i] = f(r, e, s), a = l((e) => {
6
+ i({
7
7
  type: "enqueue",
8
8
  write: e
9
9
  });
10
10
  }, []), o = l((e) => {
11
- r(e ? { type: "online" } : { type: "offline" });
12
- }, []), c = l(() => r({ type: "drain-start" }), []), u = l((e) => r({
11
+ i(e ? { type: "online" } : { type: "offline" });
12
+ }, []), c = l(() => i({ type: "drain-start" }), []), u = l((e) => i({
13
13
  type: "ack",
14
14
  id: e
15
15
  }), []), p = l((e, t) => {
16
- r({
16
+ i({
17
17
  type: "fail",
18
18
  id: e,
19
19
  error: t
@@ -37,7 +37,7 @@ var h = (e = !0) => {
37
37
  p
38
38
  ]);
39
39
  }, g = () => typeof navigator > "u" || navigator.onLine ? "online" : "offline", _ = (t = 0) => {
40
- let [n, i] = f(o, void 0, () => e(g()));
40
+ let [r, i] = f(o, void 0, () => e(g()));
41
41
  u(() => {
42
42
  if (typeof window > "u") return;
43
43
  let e = () => i({ type: "network-up" }), t = () => i({ type: "network-down" });
@@ -45,15 +45,15 @@ var h = (e = !0) => {
45
45
  window.removeEventListener("online", e), window.removeEventListener("offline", t);
46
46
  };
47
47
  }, []);
48
- let a = l(() => i({ type: "confirmed" }), []), s = l(() => i({ type: "confirm-failed" }), []), c = r(n.phase, t);
48
+ let a = l(() => i({ type: "confirmed" }), []), s = l(() => i({ type: "confirm-failed" }), []), c = n(r.phase, t);
49
49
  return d(() => ({
50
- state: n,
51
- phase: n.phase,
50
+ state: r,
51
+ phase: r.phase,
52
52
  status: c,
53
53
  confirm: a,
54
54
  confirmFailed: s
55
55
  }), [
56
- n,
56
+ r,
57
57
  c,
58
58
  a,
59
59
  s
@@ -97,7 +97,43 @@ var h = (e = !0) => {
97
97
  _,
98
98
  f
99
99
  ]);
100
- }, x = (e, t) => {
100
+ }, x = (e) => {
101
+ let { cell: t } = e, n = null, r = i({
102
+ transport: {
103
+ kind: "sync-transport",
104
+ push: async (t) => {
105
+ await e.push({
106
+ table: t.payload.table,
107
+ id: t.payload.id,
108
+ column: t.payload.column,
109
+ update: t.payload.update,
110
+ attempts: t.attempts
111
+ });
112
+ },
113
+ onRemoteState: (e) => (n = (n) => {
114
+ e({
115
+ ...t,
116
+ state: n
117
+ });
118
+ }, () => {
119
+ n = null;
120
+ })
121
+ },
122
+ ...e.adapter === void 0 ? {} : { adapter: e.adapter },
123
+ ...e.backend === void 0 ? {} : { backend: e.backend },
124
+ ...e.online === void 0 ? {} : { online: e.online },
125
+ ...e.maxAttempts === void 0 ? {} : { maxAttempts: e.maxAttempts }
126
+ });
127
+ return {
128
+ client: r,
129
+ deliverRemote: (e) => {
130
+ n?.(e);
131
+ },
132
+ close: () => {
133
+ r.close();
134
+ }
135
+ };
136
+ }, S = (e) => `${e.table}\u0000${e.id}\u0000${e.column}`, C = (e, t) => {
101
137
  if (e === t) return null;
102
138
  let n = Math.min(e.length, t.length), r = 0;
103
139
  for (; r < n && e[r] === t[r];) r += 1;
@@ -108,71 +144,53 @@ var h = (e = !0) => {
108
144
  deleteLength: e.length - r - i,
109
145
  insert: t.slice(r, t.length - i)
110
146
  };
111
- }, S = (e) => `${e.table}\u0000${e.id}\u0000${e.column}`, C = {
147
+ }, w = {
112
148
  text: "",
113
149
  state: void 0,
114
150
  outstanding: 0
115
- }, w = (e) => {
116
- let { cell: t, remote: r, adapter: i, online: o, maxAttempts: s } = e, c = e.backend ?? n, f = S(t), h = p(e.push);
117
- h.current = e.push;
118
- let g = p(t);
119
- g.current = t;
120
- let _ = p(null), v = p(null), y = p(null), [b, w] = m(C);
151
+ }, T = (e) => {
152
+ let { cell: t, remote: n, adapter: r, online: i, maxAttempts: o } = e, s = e.backend ?? a, c = S(t), f = p(e.push);
153
+ f.current = e.push;
154
+ let h = p(t);
155
+ h.current = t;
156
+ let g = p(null), _ = p(null), v = p(null), [y, b] = m(w);
121
157
  u(() => {
122
- let t = g.current, n = a({
123
- transport: {
124
- kind: "sync-transport",
125
- push: async (e) => {
126
- await h.current({
127
- table: e.payload.table,
128
- id: e.payload.id,
129
- column: e.payload.column,
130
- update: e.payload.update,
131
- attempts: e.attempts
132
- });
133
- },
134
- onRemoteState: (e) => (v.current = (n) => {
135
- e({
136
- ...t,
137
- state: n
138
- });
139
- }, () => {
140
- v.current = null;
141
- })
142
- },
143
- ...i === void 0 ? {} : { adapter: i },
158
+ let t = h.current, n = x({
159
+ cell: t,
160
+ push: (e) => f.current(e),
161
+ ...r === void 0 ? {} : { adapter: r },
144
162
  ...e.backend === void 0 ? {} : { backend: e.backend },
145
- ...o === void 0 ? {} : { online: o },
146
- ...s === void 0 ? {} : { maxAttempts: s }
147
- });
148
- _.current = n, y.current = c.createText();
149
- let r = () => {
150
- let e = n.getText(t), r = n.outstanding();
151
- w((i) => i.text === e && i.outstanding === r ? i : {
163
+ ...i === void 0 ? {} : { online: i },
164
+ ...o === void 0 ? {} : { maxAttempts: o }
165
+ }), a = n.client;
166
+ g.current = a, _.current = n.deliverRemote, v.current = s.createText();
167
+ let c = () => {
168
+ let e = a.getText(t), n = a.outstanding();
169
+ b((r) => r.text === e && r.outstanding === n ? r : {
152
170
  text: e,
153
- state: n.getState(t),
154
- outstanding: r
171
+ state: a.getState(t),
172
+ outstanding: n
155
173
  });
156
- }, l = n.subscribe(r);
157
- return r(), () => {
158
- l(), n.close(), _.current = null, y.current = null, v.current = null, w(C);
174
+ }, l = a.subscribe(c);
175
+ return c(), () => {
176
+ l(), n.close(), g.current = null, v.current = null, _.current = null, b(w);
159
177
  };
160
178
  }, [
161
- f,
162
- i,
163
179
  c,
180
+ r,
181
+ s,
164
182
  e.backend,
165
- o,
166
- s
183
+ i,
184
+ o
167
185
  ]), u(() => {
168
- r != null && v.current?.(r);
169
- }, [f, r]);
186
+ n != null && _.current?.(n);
187
+ }, [c, n]);
170
188
  let T = l((e) => {
171
- let t = _.current, n = y.current;
189
+ let t = g.current, n = v.current;
172
190
  if (t === null || n === null) return;
173
- let r = t.getState(g.current);
191
+ let r = t.getState(h.current);
174
192
  r !== void 0 && n.applyState(r), e(n), t.enqueue({
175
- ...g.current,
193
+ ...h.current,
176
194
  update: n.encodeState()
177
195
  });
178
196
  }, []), E = l((e, t) => {
@@ -180,31 +198,85 @@ var h = (e = !0) => {
180
198
  }, [T]), D = l((e, t) => {
181
199
  t <= 0 || T((n) => n.delete(e, t));
182
200
  }, [T]), O = l((e) => {
183
- let t = _.current;
201
+ let t = g.current;
184
202
  if (t === null) return;
185
- let n = x(t.getText(g.current), e);
203
+ let n = C(t.getText(h.current), e);
186
204
  n !== null && T((e) => {
187
205
  n.deleteLength > 0 && e.delete(n.index, n.deleteLength), n.insert !== "" && e.insert(n.index, n.insert);
188
206
  });
189
207
  }, [T]), k = l((e) => {
190
- _.current?.setOnline(e);
208
+ g.current?.setOnline(e);
191
209
  }, []);
192
210
  return d(() => ({
193
- text: b.text,
194
- state: b.state,
195
- outstanding: b.outstanding,
196
- synced: b.outstanding === 0,
211
+ text: y.text,
212
+ state: y.state,
213
+ outstanding: y.outstanding,
214
+ synced: y.outstanding === 0,
197
215
  insert: E,
198
216
  delete: D,
199
217
  setText: O,
200
218
  setOnline: k
201
219
  }), [
202
- b,
220
+ y,
203
221
  E,
204
222
  D,
205
223
  O,
206
224
  k
207
225
  ]);
226
+ }, E = (e) => {
227
+ let { cell: t, remote: n, adapter: r, online: i, maxAttempts: o } = e, s = e.backend ?? a, c = S(t), f = p(e.push);
228
+ f.current = e.push;
229
+ let h = p(t);
230
+ h.current = t;
231
+ let g = p(n);
232
+ g.current = n;
233
+ let _ = p(null), v = p(null), y = p(null), [b, C] = m(null), [w, T] = m(!1), [E, D] = m(0);
234
+ u(() => {
235
+ let t = h.current, n = x({
236
+ cell: t,
237
+ push: (e) => f.current(e),
238
+ ...r === void 0 ? {} : { adapter: r },
239
+ ...e.backend === void 0 ? {} : { backend: e.backend },
240
+ ...i === void 0 ? {} : { online: i },
241
+ ...o === void 0 ? {} : { maxAttempts: o }
242
+ }), a = n.client, c = s.createDoc();
243
+ _.current = a, y.current = c, v.current = n.deliverRemote;
244
+ let l = c.onUpdate((e, t) => {
245
+ t.local && a.enqueue({
246
+ ...h.current,
247
+ update: e
248
+ });
249
+ }), u = () => {
250
+ D(a.outstanding());
251
+ }, d = a.subscribe(u), p = g.current;
252
+ return p != null && (n.deliverRemote(p), c.applyState(p), T(!0)), C(c), u(), () => {
253
+ l(), d(), n.close(), _.current = null, y.current = null, v.current = null, C(null), T(!1), D(0);
254
+ };
255
+ }, [
256
+ c,
257
+ r,
258
+ s,
259
+ e.backend,
260
+ i,
261
+ o
262
+ ]), u(() => {
263
+ n != null && (v.current?.(n), y.current?.applyState(n), T(!0));
264
+ }, [c, n]);
265
+ let O = l((e) => {
266
+ _.current?.setOnline(e);
267
+ }, []);
268
+ return d(() => ({
269
+ doc: b,
270
+ loaded: w,
271
+ outstanding: E,
272
+ synced: E === 0,
273
+ setOnline: O
274
+ }), [
275
+ b,
276
+ w,
277
+ E,
278
+ O
279
+ ]);
208
280
  };
209
281
  //#endregion
210
- export { x as crdtTextEdit, _ as useConnectionStatus, w as useCrdtText, b as usePresence, h as useSyncQueue };
282
+ export { C as crdtTextEdit, _ as useConnectionStatus, E as useCrdtDoc, T as useCrdtText, b as usePresence, h as useSyncQueue };
@@ -1,32 +1,72 @@
1
1
  import * as e from "yjs";
2
2
  //#region src/crdt/yjsBackend.ts
3
- var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
3
+ var t = Symbol.for("@voltro/local-first:remote-fold"), n = "t", r = (t) => e.encodeStateAsUpdate(t), i = (t) => {
4
4
  let n = new e.Doc();
5
5
  return t.length > 0 && e.applyUpdate(n, t), n;
6
- }, i = (r) => {
7
- let i = r.getText(t);
6
+ }, a = (t) => {
7
+ let i = t.getText(n);
8
8
  return {
9
9
  toString: () => i.toString(),
10
10
  insert: (e, t) => i.insert(e, t),
11
11
  delete: (e, t) => i.delete(e, t),
12
- encodeState: () => n(r),
13
- applyState: (t) => {
14
- t.length > 0 && e.applyUpdate(r, t);
12
+ encodeState: () => r(t),
13
+ applyState: (n) => {
14
+ n.length > 0 && e.applyUpdate(t, n);
15
15
  }
16
16
  };
17
- }, a = {
17
+ }, o = {
18
18
  name: "yjs",
19
- createText: (n) => {
19
+ createText: (t) => {
20
20
  let r = new e.Doc();
21
- return n !== void 0 && n.length > 0 && r.getText(t).insert(0, n), i(r);
21
+ return t !== void 0 && t.length > 0 && r.getText(n).insert(0, t), a(r);
22
22
  },
23
23
  merge: (t, n) => e.mergeUpdates([t, n]),
24
24
  decodeText: (e) => {
25
- let n = r(e), i = n.getText(t).toString();
26
- return n.destroy(), i;
25
+ let t = i(e), r = t.getText(n).toString();
26
+ return t.destroy(), r;
27
27
  },
28
- emptyState: () => n(new e.Doc())
29
- }, o = a, s = (e, t = o) => {
28
+ emptyState: () => r(new e.Doc()),
29
+ createDoc: (n) => {
30
+ let r = new e.Doc();
31
+ return n !== void 0 && n.length > 0 && e.applyUpdate(r, n), {
32
+ raw: r,
33
+ encodeState: () => e.encodeStateAsUpdate(r),
34
+ stateVector: () => e.encodeStateVector(r),
35
+ encodeUpdateSince: (t) => e.encodeStateAsUpdate(r, t),
36
+ applyState: (n) => {
37
+ n.length > 0 && e.applyUpdate(r, n, t);
38
+ },
39
+ onUpdate: (e) => {
40
+ let n = (n, r) => {
41
+ e(n, { local: r !== t });
42
+ };
43
+ return r.on("update", n), () => {
44
+ r.off("update", n);
45
+ };
46
+ },
47
+ encodeAnchor: (t, n) => {
48
+ let i = e.createRelativePositionFromTypeIndex(r.getText(t), n);
49
+ return e.encodeRelativePosition(i);
50
+ },
51
+ resolveAnchor: (t) => {
52
+ let n = e.createAbsolutePositionFromRelativePosition(e.decodeRelativePosition(t), r);
53
+ return n === null ? void 0 : n.index;
54
+ }
55
+ };
56
+ },
57
+ compact: (t) => {
58
+ let n = i(t), r = e.encodeStateAsUpdate(n);
59
+ return n.destroy(), r;
60
+ },
61
+ rebaseText: (t) => {
62
+ let r = i(t), a = r.getText(n).toString();
63
+ r.destroy();
64
+ let o = new e.Doc();
65
+ a.length > 0 && o.getText(n).insert(0, a);
66
+ let s = e.encodeStateAsUpdate(o);
67
+ return o.destroy(), s;
68
+ }
69
+ }, s = o, c = (e, t = s) => {
30
70
  let n = t.createText(e), r = {
31
71
  backend: t.name,
32
72
  toString: () => n.toString(),
@@ -36,15 +76,22 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
36
76
  encode: () => n.encodeState()
37
77
  };
38
78
  return r;
39
- }, c = (e, t, n = o) => n.merge(e, t), l = (e, t = o) => t.decodeText(e), u = (e = o) => e.emptyState(), d = (e = !0) => ({
79
+ }, l = (e, t, n) => {
80
+ if (!(n instanceof Uint8Array) || !(t instanceof Uint8Array)) return n;
81
+ try {
82
+ return u(t, n);
83
+ } catch {
84
+ return n;
85
+ }
86
+ }, u = (e, t, n = s) => n.merge(e, t), d = (e, t = s) => t.decodeText(e), f = (e = s) => e.emptyState(), p = (e = !0) => ({
40
87
  online: e,
41
88
  pending: [],
42
89
  inFlight: void 0,
43
90
  lastError: void 0
44
- }), f = (e) => e.online && e.inFlight === void 0 && e.pending.length > 0, p = (e) => e.pending.length + (e.inFlight === void 0 ? 0 : 1), m = (e) => ({
91
+ }), m = (e) => e.online && e.inFlight === void 0 && e.pending.length > 0, h = (e) => e.pending.length + (e.inFlight === void 0 ? 0 : 1), g = (e) => ({
45
92
  ...e,
46
93
  attempts: e.attempts + 1
47
- }), h = (e, t) => {
94
+ }), _ = (e, t) => {
48
95
  switch (t.type) {
49
96
  case "enqueue": return {
50
97
  ...e,
@@ -64,7 +111,7 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
64
111
  inFlight: void 0
65
112
  };
66
113
  case "drain-start": {
67
- if (!f(e)) return e;
114
+ if (!m(e)) return e;
68
115
  let [t, ...n] = e.pending;
69
116
  return t === void 0 ? e : {
70
117
  ...e,
@@ -80,15 +127,15 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
80
127
  };
81
128
  case "fail": return e.inFlight === void 0 || e.inFlight.id !== t.id ? e : {
82
129
  ...e,
83
- pending: [m(e.inFlight), ...e.pending],
130
+ pending: [g(e.inFlight), ...e.pending],
84
131
  inFlight: void 0,
85
132
  lastError: t.error
86
133
  };
87
134
  }
88
- }, g = (e = "online") => ({
135
+ }, v = (e = "online") => ({
89
136
  phase: e,
90
137
  attempt: 0
91
- }), _ = (e, t) => {
138
+ }), y = (e, t) => {
92
139
  switch (t.type) {
93
140
  case "network-down": return e.phase === "offline" ? e : {
94
141
  phase: "offline",
@@ -107,87 +154,102 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
107
154
  attempt: e.attempt + 1
108
155
  } : e;
109
156
  }
110
- }, v = (e, t) => e === "offline" ? "offline" : e === "reconnecting" || t > 0 ? "syncing" : "synced", y = (e) => `${e.table}\u0000${e.id}\u0000${e.column}`, b = 0, x = () => {
157
+ }, b = (e, t) => e === "offline" ? "offline" : e === "reconnecting" || t > 0 ? "syncing" : "synced", x = (e) => `${e.table}\u0000${e.id}\u0000${e.column}`, S = 0, C = () => {
111
158
  let e = typeof crypto < "u" ? crypto : void 0;
112
- return e && typeof e.randomUUID == "function" ? e.randomUUID() : `w_${Date.now().toString(36)}_${b += 1}`;
113
- }, S = (e) => {
114
- let { transport: t, adapter: n } = e, r = e.backend ?? o, i = e.now ?? Date.now, a = e.maxAttempts ?? 5, s = d(e.online ?? !0), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Set(), m = () => {
115
- for (let e of u) try {
159
+ return e && typeof e.randomUUID == "function" ? e.randomUUID() : `w_${Date.now().toString(36)}_${S += 1}`;
160
+ }, w = (e) => {
161
+ let { transport: t, adapter: n } = e, r = e.backend ?? s, i = e.now ?? Date.now, a = e.maxAttempts ?? 5, o = p(e.online ?? !0), c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Set(), d = () => {
162
+ for (let e of l) try {
116
163
  e();
117
164
  } catch {}
118
- }, g = (e, t) => {
119
- let i = y(e), a = l.get(i), o = a === void 0 ? t : c(a, t, r);
120
- l.set(i, o), n?.saveCrdtState(e.table, e.id, o).catch(() => void 0);
121
- }, _ = () => {
165
+ }, f = (e, t) => {
166
+ let i = x(e), a = c.get(i), o = a === void 0 ? t : u(a, t, r);
167
+ c.set(i, o), n?.saveCrdtState(e.table, e.id, o).catch(() => void 0);
168
+ }, g = () => {
122
169
  if (n === void 0) return;
123
- let e = s.inFlight === void 0 ? s.pending : [s.inFlight, ...s.pending];
170
+ let e = o.inFlight === void 0 ? o.pending : [o.inFlight, ...o.pending];
124
171
  n.saveQueue(e).catch(() => void 0);
125
- }, v = !1, b = async () => {
172
+ }, v = !1, y = async () => {
126
173
  if (!v) {
127
174
  v = !0;
128
175
  try {
129
- for (; f(s);) {
130
- s = h(s, { type: "drain-start" });
131
- let e = s.inFlight;
176
+ for (; m(o);) {
177
+ o = _(o, { type: "drain-start" });
178
+ let e = o.inFlight;
132
179
  if (e === void 0) break;
133
180
  try {
134
- await t.push(e), s = h(s, {
181
+ await t.push(e), o = _(o, {
135
182
  type: "ack",
136
183
  id: e.id
137
- }), _(), m();
184
+ }), g(), d();
138
185
  } catch (t) {
139
- if (s = h(s, {
186
+ if (o = _(o, {
140
187
  type: "fail",
141
188
  id: e.id,
142
189
  error: t instanceof Error ? t.message : String(t)
143
- }), _(), m(), e.attempts + 1 >= a) break;
190
+ }), g(), d(), e.attempts + 1 >= a) break;
144
191
  }
145
192
  }
146
193
  } finally {
147
194
  v = !1;
148
195
  }
149
196
  }
150
- }, S = t.onRemoteState((e) => {
151
- g(e, e.state), m();
197
+ }, b = t.onRemoteState((e) => {
198
+ f(e, e.state), d();
152
199
  });
153
200
  return {
154
201
  enqueue: (e) => {
155
- g(e, e.update);
156
- let t = {
157
- id: x(),
202
+ f(e, e.update);
203
+ let t = x(e), n = o.pending.findIndex((e) => x(e.payload) === t);
204
+ if (n !== -1) {
205
+ let t = o.pending[n], i = {
206
+ ...t,
207
+ payload: {
208
+ ...t.payload,
209
+ update: u(t.payload.update, e.update, r)
210
+ }
211
+ };
212
+ o = {
213
+ ...o,
214
+ pending: o.pending.map((e, t) => t === n ? i : e)
215
+ }, g(), d(), y();
216
+ return;
217
+ }
218
+ let a = {
219
+ id: C(),
158
220
  payload: e,
159
221
  enqueuedAt: i(),
160
222
  attempts: 0
161
223
  };
162
- s = h(s, {
224
+ o = _(o, {
163
225
  type: "enqueue",
164
- write: t
165
- }), _(), m(), b();
226
+ write: a
227
+ }), g(), d(), y();
166
228
  },
167
229
  setOnline: (e) => {
168
- s = h(s, e ? { type: "online" } : { type: "offline" }), _(), m(), e && b();
230
+ o = _(o, e ? { type: "online" } : { type: "offline" }), g(), d(), e && y();
169
231
  },
170
- queueState: () => s,
171
- outstanding: () => p(s),
232
+ queueState: () => o,
233
+ outstanding: () => h(o),
172
234
  getState: (e) => {
173
- let t = l.get(y(e));
235
+ let t = c.get(x(e));
174
236
  return t === void 0 ? void 0 : t.slice();
175
237
  },
176
238
  getText: (e) => {
177
- let t = l.get(y(e));
239
+ let t = c.get(x(e));
178
240
  return t === void 0 ? "" : r.decodeText(t);
179
241
  },
180
- subscribe: (e) => (u.add(e), () => {
181
- u.delete(e);
242
+ subscribe: (e) => (l.add(e), () => {
243
+ l.delete(e);
182
244
  }),
183
245
  flush: async () => {
184
- await b();
246
+ await y();
185
247
  },
186
248
  close: () => {
187
- S(), u.clear();
249
+ b(), l.clear();
188
250
  }
189
251
  };
190
- }, C = (e) => {
252
+ }, T = (e) => {
191
253
  let { channel: t, roomId: n, peerId: r, initial: i } = e, a = e.ttlMs ?? 3e4, o = e.now ?? Date.now, s = i, c = 0, l = !1, u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Set(), p = () => {
192
254
  for (let e of f) try {
193
255
  e();
@@ -248,4 +310,4 @@ var t = "t", n = (t) => e.encodeStateAsUpdate(t), r = (t) => {
248
310
  };
249
311
  };
250
312
  //#endregion
251
- export { g as a, p as c, l as d, o as f, a as h, v as i, h as l, c as m, S as n, f as o, u as p, _ as r, d as s, C as t, s as u };
313
+ export { v as a, h as c, c as d, d as f, o as g, u as h, b as i, _ as l, f as m, w as n, m as o, s as p, y as r, p as s, T as t, l as u };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@voltro/local-first",
3
- "version": "0.52.0",
4
- "description": "Local-first / CRDT primitives (opt-in): a Yjs-backed crdtText() field and its deterministic merge, the bi-directional sync wire (createSyncClient + the useCrdtText React binding), durable IndexedDB persistence, presence rooms, connection-status state machine, and last-write-wins conflict policy. Remaining seams: the two app-level tags the sync wire is pointed at (the mutation that writes the column, the query that streams the row), the presence channel's broker binding, and an optional wa-sqlite/Turso adapter.",
3
+ "version": "0.54.0",
4
+ "description": "The local-first sync engine (opt-in): Yjs-backed crdtText()/crdtDoc() fields with a deterministic, server-authoritative merge and the Tiptap rich-text binding (useCrdtEditor); a subject+tenant-partitioned query mirror over IndexedDB that renders the last materialised rows offline and delta-resumes on reconnect; a durable offline outbox with declared conflict resolution (resolveWithPolicy) and a per-partition Web-Locks single drainer; the bi-directional sync wire (createSyncClient + useCrdtText); presence rooms over the framework's own presence lane; durable persistence and the connection-status state machine. Pure and browser-safe React bindings behind /react, the editor behind /editor.",
5
5
  "keywords": [
6
6
  "voltro",
7
7
  "typescript",
@@ -28,6 +28,11 @@
28
28
  "import": "./dist/react.js",
29
29
  "default": "./dist/react.js"
30
30
  },
31
+ "./editor": {
32
+ "types": "./dist/editor.d.ts",
33
+ "import": "./dist/editor.js",
34
+ "default": "./dist/editor.js"
35
+ },
31
36
  "./package.json": "./package.json"
32
37
  },
33
38
  "main": "./dist/index.js",
@@ -38,14 +43,31 @@
38
43
  "node": ">=24.0.0"
39
44
  },
40
45
  "dependencies": {
41
- "yjs": "^13.6.32"
46
+ "yjs": "^13.6.32",
47
+ "y-protocols": "^1.0.6"
42
48
  },
43
49
  "peerDependencies": {
44
- "react": "^19.0.0"
50
+ "react": "^19.0.0",
51
+ "@tiptap/react": "^3.0.0",
52
+ "@tiptap/starter-kit": "^3.0.0",
53
+ "@tiptap/extension-collaboration": "^3.0.0",
54
+ "@tiptap/extension-collaboration-caret": "^3.0.0"
45
55
  },
46
56
  "peerDependenciesMeta": {
47
57
  "react": {
48
58
  "optional": true
59
+ },
60
+ "@tiptap/react": {
61
+ "optional": true
62
+ },
63
+ "@tiptap/starter-kit": {
64
+ "optional": true
65
+ },
66
+ "@tiptap/extension-collaboration": {
67
+ "optional": true
68
+ },
69
+ "@tiptap/extension-collaboration-caret": {
70
+ "optional": true
49
71
  }
50
72
  },
51
73
  "publishConfig": {