@stratasync/react 0.2.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/README.md +91 -0
- package/dist/context.d.ts +21 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +27 -0
- package/dist/context.js.map +1 -0
- package/dist/hooks/use-connection-state.d.ts +55 -0
- package/dist/hooks/use-connection-state.d.ts.map +1 -0
- package/dist/hooks/use-connection-state.js +90 -0
- package/dist/hooks/use-connection-state.js.map +1 -0
- package/dist/hooks/use-model.d.ts +22 -0
- package/dist/hooks/use-model.d.ts.map +1 -0
- package/dist/hooks/use-model.js +162 -0
- package/dist/hooks/use-model.js.map +1 -0
- package/dist/hooks/use-query.d.ts +35 -0
- package/dist/hooks/use-query.d.ts.map +1 -0
- package/dist/hooks/use-query.js +302 -0
- package/dist/hooks/use-query.js.map +1 -0
- package/dist/hooks/use-sync-client.d.ts +25 -0
- package/dist/hooks/use-sync-client.d.ts.map +1 -0
- package/dist/hooks/use-sync-client.js +49 -0
- package/dist/hooks/use-sync-client.js.map +1 -0
- package/dist/hooks/use-yjs-document.d.ts +108 -0
- package/dist/hooks/use-yjs-document.d.ts.map +1 -0
- package/dist/hooks/use-yjs-document.js +202 -0
- package/dist/hooks/use-yjs-document.js.map +1 -0
- package/dist/hooks/use-yjs-presence.d.ts +62 -0
- package/dist/hooks/use-yjs-presence.d.ts.map +1 -0
- package/dist/hooks/use-yjs-presence.js +230 -0
- package/dist/hooks/use-yjs-presence.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/provider.d.ts +7 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +117 -0
- package/dist/provider.js.map +1 -0
- package/dist/types.d.ts +107 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for Yjs collaborative document editing.
|
|
3
|
+
*/
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
|
+
import { useSyncClientInstance } from "./use-sync-client.js";
|
|
6
|
+
const toDocumentKeyString = (docKey) => `${docKey.entityType}:${docKey.entityId}:${docKey.fieldName}`;
|
|
7
|
+
/**
|
|
8
|
+
* Hook to manage a Yjs collaborative document.
|
|
9
|
+
*
|
|
10
|
+
* @param docKey - Document key identifying the field
|
|
11
|
+
* @param options - Hook options
|
|
12
|
+
* @returns UseYjsDocumentResult with document, connection state, and controls
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* function TaskDescriptionEditor({ taskId }: { taskId: string }) {
|
|
17
|
+
* const {
|
|
18
|
+
* doc,
|
|
19
|
+
* isSessionActive,
|
|
20
|
+
* participants,
|
|
21
|
+
* } = useYjsDocument(
|
|
22
|
+
* { entityType: 'Task', entityId: taskId, fieldName: 'description' },
|
|
23
|
+
* { autoConnect: true, initialContent: task.description }
|
|
24
|
+
* );
|
|
25
|
+
*
|
|
26
|
+
* // doc becomes available after the first render (even offline).
|
|
27
|
+
* // Initial content is seeded into the local Y.Doc during connect(),
|
|
28
|
+
* // so the editor shows content immediately without waiting for the server.
|
|
29
|
+
* return (
|
|
30
|
+
* <div>
|
|
31
|
+
* {isSessionActive && (
|
|
32
|
+
* <div>
|
|
33
|
+
* Collaborating with: {participants.map(p => p.userId).join(', ')}
|
|
34
|
+
* </div>
|
|
35
|
+
* )}
|
|
36
|
+
* {doc && <TiptapEditor doc={doc} />}
|
|
37
|
+
* </div>
|
|
38
|
+
* );
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export const useYjsDocument = (docKey, options = {}) => {
|
|
43
|
+
const { autoConnect = false, skip = false } = options;
|
|
44
|
+
const client = useSyncClientInstance();
|
|
45
|
+
const [doc, setDoc] = useState(null);
|
|
46
|
+
const [connectionState, setConnectionState] = useState("disconnected");
|
|
47
|
+
const [sessionState, setSessionState] = useState({
|
|
48
|
+
active: false,
|
|
49
|
+
participants: [],
|
|
50
|
+
});
|
|
51
|
+
const [content, setContent] = useState("");
|
|
52
|
+
const [error, setError] = useState(null);
|
|
53
|
+
// Track if we've connected to avoid double connections
|
|
54
|
+
const isConnectedRef = useRef(false);
|
|
55
|
+
const unsubscribeRef = useRef(null);
|
|
56
|
+
const connectedDocKeyRef = useRef(null);
|
|
57
|
+
const previousDocKeyStringRef = useRef(toDocumentKeyString(docKey));
|
|
58
|
+
const docKeyRef = useRef(docKey);
|
|
59
|
+
const optionsRef = useRef(options);
|
|
60
|
+
docKeyRef.current = docKey;
|
|
61
|
+
optionsRef.current = options;
|
|
62
|
+
const connect = useCallback(() => {
|
|
63
|
+
if (skip || isConnectedRef.current) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
// Get Yjs document manager from client if available
|
|
68
|
+
const yjsManager = client.yjs;
|
|
69
|
+
if (!yjsManager) {
|
|
70
|
+
setError(new Error("Yjs document manager not available on client"));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const currentDocKey = docKeyRef.current;
|
|
74
|
+
const currentOptions = optionsRef.current;
|
|
75
|
+
// Get or create document
|
|
76
|
+
const yjsDoc = yjsManager.documentManager.getDocument(currentDocKey);
|
|
77
|
+
setDoc(yjsDoc);
|
|
78
|
+
// Start presence tracking before sync handshake so server can gate
|
|
79
|
+
// sync/update messages to active viewers.
|
|
80
|
+
yjsManager.presenceManager.startViewing(currentDocKey);
|
|
81
|
+
// Connect with options
|
|
82
|
+
yjsManager.documentManager.connect(currentDocKey, {
|
|
83
|
+
editing: currentOptions.editing,
|
|
84
|
+
initialContent: currentOptions.initialContent,
|
|
85
|
+
});
|
|
86
|
+
if (currentOptions.editing) {
|
|
87
|
+
yjsManager.presenceManager.focus(currentDocKey);
|
|
88
|
+
}
|
|
89
|
+
// Subscribe to connection state changes
|
|
90
|
+
const unsubConnection = yjsManager.documentManager.onConnectionStateChange(currentDocKey, (state) => {
|
|
91
|
+
setConnectionState(state);
|
|
92
|
+
});
|
|
93
|
+
// Subscribe to content changes
|
|
94
|
+
const unsubContent = yjsManager.documentManager.onContentChange(currentDocKey, (newContent) => {
|
|
95
|
+
setContent(newContent);
|
|
96
|
+
});
|
|
97
|
+
// Subscribe to session state changes
|
|
98
|
+
const unsubSession = yjsManager.presenceManager.onSessionStateChange(currentDocKey, (state) => {
|
|
99
|
+
setSessionState(state);
|
|
100
|
+
});
|
|
101
|
+
unsubscribeRef.current = () => {
|
|
102
|
+
unsubConnection();
|
|
103
|
+
unsubContent();
|
|
104
|
+
unsubSession();
|
|
105
|
+
};
|
|
106
|
+
isConnectedRef.current = true;
|
|
107
|
+
connectedDocKeyRef.current = currentDocKey;
|
|
108
|
+
}
|
|
109
|
+
catch (connectError) {
|
|
110
|
+
setError(connectError instanceof Error
|
|
111
|
+
? connectError
|
|
112
|
+
: new Error(String(connectError)));
|
|
113
|
+
}
|
|
114
|
+
}, [skip, client]);
|
|
115
|
+
const disconnect = useCallback(() => {
|
|
116
|
+
if (!isConnectedRef.current) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const yjsManager = client.yjs;
|
|
121
|
+
const connectedDocKey = connectedDocKeyRef.current ?? docKeyRef.current;
|
|
122
|
+
if (yjsManager) {
|
|
123
|
+
yjsManager.presenceManager.stopViewing(connectedDocKey);
|
|
124
|
+
yjsManager.documentManager.disconnect(connectedDocKey);
|
|
125
|
+
}
|
|
126
|
+
unsubscribeRef.current?.();
|
|
127
|
+
unsubscribeRef.current = null;
|
|
128
|
+
isConnectedRef.current = false;
|
|
129
|
+
connectedDocKeyRef.current = null;
|
|
130
|
+
setDoc(null);
|
|
131
|
+
setContent("");
|
|
132
|
+
setConnectionState("disconnected");
|
|
133
|
+
setSessionState({ active: false, participants: [] });
|
|
134
|
+
}
|
|
135
|
+
catch (disconnectError) {
|
|
136
|
+
setError(disconnectError instanceof Error
|
|
137
|
+
? disconnectError
|
|
138
|
+
: new Error(String(disconnectError)));
|
|
139
|
+
}
|
|
140
|
+
}, [client]);
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
const currentDocKeyString = toDocumentKeyString(docKey);
|
|
143
|
+
const previousDocKeyString = previousDocKeyStringRef.current;
|
|
144
|
+
if (currentDocKeyString === previousDocKeyString) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
previousDocKeyStringRef.current = currentDocKeyString;
|
|
148
|
+
if (isConnectedRef.current) {
|
|
149
|
+
disconnect();
|
|
150
|
+
}
|
|
151
|
+
if (autoConnect && !skip) {
|
|
152
|
+
connect();
|
|
153
|
+
}
|
|
154
|
+
}, [docKey, autoConnect, skip, connect, disconnect]);
|
|
155
|
+
const focus = useCallback(() => {
|
|
156
|
+
if (skip) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
const yjsManager = client.yjs;
|
|
160
|
+
if (!yjsManager) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const focusDocKey = connectedDocKeyRef.current ?? docKeyRef.current;
|
|
164
|
+
yjsManager.presenceManager.focus(focusDocKey);
|
|
165
|
+
}, [client, skip]);
|
|
166
|
+
const blur = useCallback(() => {
|
|
167
|
+
if (skip) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
const yjsManager = client.yjs;
|
|
171
|
+
if (!yjsManager) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const blurDocKey = connectedDocKeyRef.current ?? docKeyRef.current;
|
|
175
|
+
yjsManager.presenceManager.blur(blurDocKey);
|
|
176
|
+
}, [client, skip]);
|
|
177
|
+
// Auto-connect on mount if enabled
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
if (autoConnect && !skip) {
|
|
180
|
+
connect();
|
|
181
|
+
}
|
|
182
|
+
return () => {
|
|
183
|
+
if (isConnectedRef.current) {
|
|
184
|
+
disconnect();
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
}, [autoConnect, skip, connect, disconnect]);
|
|
188
|
+
return {
|
|
189
|
+
blur,
|
|
190
|
+
connect,
|
|
191
|
+
connectionState,
|
|
192
|
+
content,
|
|
193
|
+
disconnect,
|
|
194
|
+
doc,
|
|
195
|
+
error,
|
|
196
|
+
focus,
|
|
197
|
+
isConnected: connectionState === "connected",
|
|
198
|
+
isSessionActive: sessionState.active,
|
|
199
|
+
participants: sessionState.participants,
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
//# sourceMappingURL=use-yjs-document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-yjs-document.js","sourceRoot":"","sources":["../../src/hooks/use-yjs-document.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hook for Yjs presence management.
|
|
3
|
+
* Handles focus/blur signaling based on component visibility and focus state.
|
|
4
|
+
*/
|
|
5
|
+
import type { DocumentKey } from "./use-yjs-document.js";
|
|
6
|
+
/**
|
|
7
|
+
* Options for useYjsPresence hook.
|
|
8
|
+
*/
|
|
9
|
+
export interface UseYjsPresenceOptions {
|
|
10
|
+
/** Whether to track focus based on element focus events */
|
|
11
|
+
trackFocus?: boolean;
|
|
12
|
+
/** Whether to track visibility based on Intersection Observer */
|
|
13
|
+
trackVisibility?: boolean;
|
|
14
|
+
/** Skip presence tracking */
|
|
15
|
+
skip?: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Result of useYjsPresence hook.
|
|
19
|
+
*/
|
|
20
|
+
export interface UseYjsPresenceResult {
|
|
21
|
+
/** Start viewing the document */
|
|
22
|
+
startViewing: () => void;
|
|
23
|
+
/** Stop viewing the document */
|
|
24
|
+
stopViewing: () => void;
|
|
25
|
+
/** Signal that the user has focused the editor */
|
|
26
|
+
focus: () => void;
|
|
27
|
+
/** Signal that the user has blurred the editor */
|
|
28
|
+
blur: () => void;
|
|
29
|
+
/** Whether the user is currently viewing */
|
|
30
|
+
isViewing: boolean;
|
|
31
|
+
/** Whether the user is currently editing */
|
|
32
|
+
isEditing: boolean;
|
|
33
|
+
/** Get ref callback for auto-tracking focus/visibility */
|
|
34
|
+
getRef: <T extends HTMLElement>() => (element: T | null) => void;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Hook for managing presence signaling in collaborative editing.
|
|
38
|
+
*
|
|
39
|
+
* @param docKey - Document key identifying the field
|
|
40
|
+
* @param options - Hook options
|
|
41
|
+
* @returns UseYjsPresenceResult with presence controls
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```tsx
|
|
45
|
+
* function TaskEditor({ taskId }: { taskId: string }) {
|
|
46
|
+
* const { getRef, isViewing, isEditing } = useYjsPresence(
|
|
47
|
+
* { entityType: 'Task', entityId: taskId, fieldName: 'description' },
|
|
48
|
+
* { trackFocus: true, trackVisibility: true }
|
|
49
|
+
* );
|
|
50
|
+
*
|
|
51
|
+
* return (
|
|
52
|
+
* <div ref={getRef()}>
|
|
53
|
+
* <p>Viewing: {isViewing ? 'Yes' : 'No'}</p>
|
|
54
|
+
* <p>Editing: {isEditing ? 'Yes' : 'No'}</p>
|
|
55
|
+
* <textarea />
|
|
56
|
+
* </div>
|
|
57
|
+
* );
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare const useYjsPresence: (docKey: DocumentKey, options?: UseYjsPresenceOptions) => UseYjsPresenceResult;
|
|
62
|
+
//# sourceMappingURL=use-yjs-presence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-yjs-presence.d.ts","sourceRoot":"","sources":["../../src/hooks/use-yjs-presence.ts"],"names":[],"mappings":"AACA;;;GAGG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,iEAAiE;IACjE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,6BAA6B;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,iCAAiC;IACjC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,gCAAgC;IAChC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,kDAAkD;IAClD,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,kDAAkD;IAClD,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,4CAA4C;IAC5C,SAAS,EAAE,OAAO,CAAC;IACnB,4CAA4C;IAC5C,SAAS,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,MAAM,EAAE,CAAC,CAAC,SAAS,WAAW,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;CAClE;AAOD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,cAAc,GACzB,QAAQ,WAAW,EACnB,UAAS,qBAA0B,KAClC,oBAsPF,CAAC"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// oxlint-disable no-use-before-define -- handleFocusIn/handleFocusOut defined within getRef closure
|
|
2
|
+
/**
|
|
3
|
+
* React hook for Yjs presence management.
|
|
4
|
+
* Handles focus/blur signaling based on component visibility and focus state.
|
|
5
|
+
*/
|
|
6
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
7
|
+
import { useSyncClientInstance, useSyncReady } from "./use-sync-client.js";
|
|
8
|
+
const isSameDocumentKey = (a, b) => a.entityType === b.entityType &&
|
|
9
|
+
a.entityId === b.entityId &&
|
|
10
|
+
a.fieldName === b.fieldName;
|
|
11
|
+
/**
|
|
12
|
+
* Hook for managing presence signaling in collaborative editing.
|
|
13
|
+
*
|
|
14
|
+
* @param docKey - Document key identifying the field
|
|
15
|
+
* @param options - Hook options
|
|
16
|
+
* @returns UseYjsPresenceResult with presence controls
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* function TaskEditor({ taskId }: { taskId: string }) {
|
|
21
|
+
* const { getRef, isViewing, isEditing } = useYjsPresence(
|
|
22
|
+
* { entityType: 'Task', entityId: taskId, fieldName: 'description' },
|
|
23
|
+
* { trackFocus: true, trackVisibility: true }
|
|
24
|
+
* );
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <div ref={getRef()}>
|
|
28
|
+
* <p>Viewing: {isViewing ? 'Yes' : 'No'}</p>
|
|
29
|
+
* <p>Editing: {isEditing ? 'Yes' : 'No'}</p>
|
|
30
|
+
* <textarea />
|
|
31
|
+
* </div>
|
|
32
|
+
* );
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export const useYjsPresence = (docKey, options = {}) => {
|
|
37
|
+
const { trackFocus = false, trackVisibility = false, skip = false } = options;
|
|
38
|
+
const client = useSyncClientInstance();
|
|
39
|
+
const isReady = useSyncReady();
|
|
40
|
+
const docKeyRef = useRef(docKey);
|
|
41
|
+
const previousDocKeyRef = useRef(docKey);
|
|
42
|
+
docKeyRef.current = docKey;
|
|
43
|
+
const elementRef = useRef(null);
|
|
44
|
+
const isViewingRef = useRef(false);
|
|
45
|
+
const isEditingRef = useRef(false);
|
|
46
|
+
const observerRef = useRef(null);
|
|
47
|
+
const [presenceState, setPresenceState] = useState({
|
|
48
|
+
isEditing: false,
|
|
49
|
+
isViewing: false,
|
|
50
|
+
});
|
|
51
|
+
const getPresenceManager = useCallback(() => client.yjs?.presenceManager, [client]);
|
|
52
|
+
const updatePresenceState = useCallback((isViewing, isEditing) => {
|
|
53
|
+
isViewingRef.current = isViewing;
|
|
54
|
+
isEditingRef.current = isEditing;
|
|
55
|
+
setPresenceState((current) => {
|
|
56
|
+
if (current.isViewing === isViewing &&
|
|
57
|
+
current.isEditing === isEditing) {
|
|
58
|
+
return current;
|
|
59
|
+
}
|
|
60
|
+
return { isEditing, isViewing };
|
|
61
|
+
});
|
|
62
|
+
}, []);
|
|
63
|
+
const syncPresenceState = useCallback(() => {
|
|
64
|
+
const presenceManager = getPresenceManager();
|
|
65
|
+
if (!presenceManager) {
|
|
66
|
+
updatePresenceState(false, false);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
updatePresenceState(presenceManager.isViewing(docKeyRef.current), presenceManager.isEditing(docKeyRef.current));
|
|
70
|
+
}, [getPresenceManager, updatePresenceState]);
|
|
71
|
+
const startViewing = useCallback(() => {
|
|
72
|
+
if (!isReady || skip || isViewingRef.current) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const presenceManager = getPresenceManager();
|
|
76
|
+
if (presenceManager) {
|
|
77
|
+
presenceManager.startViewing(docKeyRef.current);
|
|
78
|
+
syncPresenceState();
|
|
79
|
+
}
|
|
80
|
+
}, [isReady, skip, getPresenceManager, syncPresenceState]);
|
|
81
|
+
const stopViewing = useCallback(() => {
|
|
82
|
+
if (!isViewingRef.current) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const presenceManager = getPresenceManager();
|
|
86
|
+
if (presenceManager) {
|
|
87
|
+
presenceManager.stopViewing(docKeyRef.current);
|
|
88
|
+
syncPresenceState();
|
|
89
|
+
}
|
|
90
|
+
}, [getPresenceManager, syncPresenceState]);
|
|
91
|
+
const focus = useCallback(() => {
|
|
92
|
+
if (!isReady || skip) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Start viewing if not already
|
|
96
|
+
if (!isViewingRef.current) {
|
|
97
|
+
startViewing();
|
|
98
|
+
}
|
|
99
|
+
if (isEditingRef.current) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const presenceManager = getPresenceManager();
|
|
103
|
+
if (presenceManager) {
|
|
104
|
+
presenceManager.focus(docKeyRef.current);
|
|
105
|
+
syncPresenceState();
|
|
106
|
+
}
|
|
107
|
+
}, [isReady, skip, getPresenceManager, startViewing, syncPresenceState]);
|
|
108
|
+
const blur = useCallback(() => {
|
|
109
|
+
if (!isEditingRef.current) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const presenceManager = getPresenceManager();
|
|
113
|
+
if (presenceManager) {
|
|
114
|
+
presenceManager.blur(docKeyRef.current);
|
|
115
|
+
syncPresenceState();
|
|
116
|
+
}
|
|
117
|
+
}, [getPresenceManager, syncPresenceState]);
|
|
118
|
+
useEffect(() => {
|
|
119
|
+
syncPresenceState();
|
|
120
|
+
}, [syncPresenceState]);
|
|
121
|
+
useEffect(() => {
|
|
122
|
+
const previousDocKey = previousDocKeyRef.current;
|
|
123
|
+
if (isSameDocumentKey(previousDocKey, docKey)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
previousDocKeyRef.current = docKey;
|
|
127
|
+
const presenceManager = getPresenceManager();
|
|
128
|
+
const wasViewing = isViewingRef.current;
|
|
129
|
+
const wasEditing = isEditingRef.current;
|
|
130
|
+
if (!presenceManager) {
|
|
131
|
+
updatePresenceState(false, false);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if (wasEditing) {
|
|
135
|
+
presenceManager.blur(previousDocKey);
|
|
136
|
+
}
|
|
137
|
+
if (wasViewing) {
|
|
138
|
+
presenceManager.stopViewing(previousDocKey);
|
|
139
|
+
}
|
|
140
|
+
if (!skip && isReady) {
|
|
141
|
+
if (wasEditing) {
|
|
142
|
+
presenceManager.focus(docKey);
|
|
143
|
+
}
|
|
144
|
+
else if (wasViewing) {
|
|
145
|
+
presenceManager.startViewing(docKey);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
syncPresenceState();
|
|
149
|
+
}, [
|
|
150
|
+
docKey,
|
|
151
|
+
getPresenceManager,
|
|
152
|
+
isReady,
|
|
153
|
+
skip,
|
|
154
|
+
syncPresenceState,
|
|
155
|
+
updatePresenceState,
|
|
156
|
+
]);
|
|
157
|
+
// Create ref callback for tracking
|
|
158
|
+
const getRef = useCallback(() => {
|
|
159
|
+
return (element) => {
|
|
160
|
+
// Clean up previous element
|
|
161
|
+
if (elementRef.current && elementRef.current !== element) {
|
|
162
|
+
if (observerRef.current) {
|
|
163
|
+
observerRef.current.disconnect();
|
|
164
|
+
observerRef.current = null;
|
|
165
|
+
}
|
|
166
|
+
elementRef.current.removeEventListener("focusin", handleFocusIn);
|
|
167
|
+
elementRef.current.removeEventListener("focusout", handleFocusOut);
|
|
168
|
+
}
|
|
169
|
+
elementRef.current = element;
|
|
170
|
+
if (!element || skip) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
// Set up focus tracking
|
|
174
|
+
if (trackFocus) {
|
|
175
|
+
element.addEventListener("focusin", handleFocusIn);
|
|
176
|
+
element.addEventListener("focusout", handleFocusOut);
|
|
177
|
+
}
|
|
178
|
+
// Set up visibility tracking
|
|
179
|
+
if (trackVisibility && typeof IntersectionObserver !== "undefined") {
|
|
180
|
+
observerRef.current = new IntersectionObserver((entries) => {
|
|
181
|
+
const isVisible = entries[0]?.isIntersecting ?? false;
|
|
182
|
+
if (isVisible && !isViewingRef.current) {
|
|
183
|
+
startViewing();
|
|
184
|
+
}
|
|
185
|
+
else if (!isVisible && isViewingRef.current) {
|
|
186
|
+
stopViewing();
|
|
187
|
+
}
|
|
188
|
+
}, { threshold: 0.1 });
|
|
189
|
+
observerRef.current.observe(element);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
const handleFocusIn = () => {
|
|
193
|
+
focus();
|
|
194
|
+
};
|
|
195
|
+
const handleFocusOut = (event) => {
|
|
196
|
+
// Only blur if focus is leaving the container entirely
|
|
197
|
+
if (elementRef.current &&
|
|
198
|
+
!elementRef.current.contains(event.relatedTarget)) {
|
|
199
|
+
blur();
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
}, [
|
|
203
|
+
skip,
|
|
204
|
+
trackFocus,
|
|
205
|
+
trackVisibility,
|
|
206
|
+
focus,
|
|
207
|
+
blur,
|
|
208
|
+
startViewing,
|
|
209
|
+
stopViewing,
|
|
210
|
+
]);
|
|
211
|
+
// Clean up on unmount
|
|
212
|
+
useEffect(() => () => {
|
|
213
|
+
if (observerRef.current) {
|
|
214
|
+
observerRef.current.disconnect();
|
|
215
|
+
}
|
|
216
|
+
if (isViewingRef.current) {
|
|
217
|
+
stopViewing();
|
|
218
|
+
}
|
|
219
|
+
}, [stopViewing]);
|
|
220
|
+
return {
|
|
221
|
+
blur,
|
|
222
|
+
focus,
|
|
223
|
+
getRef,
|
|
224
|
+
isEditing: presenceState.isEditing,
|
|
225
|
+
isViewing: presenceState.isViewing,
|
|
226
|
+
startViewing,
|
|
227
|
+
stopViewing,
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
//# sourceMappingURL=use-yjs-presence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-yjs-presence.js","sourceRoot":"","sources":["../../src/hooks/use-yjs-presence.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEjE,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAmC3E,MAAM,iBAAiB,GAAG,CAAC,CAAc,EAAE,CAAc,EAAW,EAAE,CACpE,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU;IAC7B,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;IACzB,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,MAAmB,EACnB,UAAiC,EAAE,EACb,EAAE;IACxB,MAAM,EAAE,UAAU,GAAG,KAAK,EAAE,eAAe,GAAG,KAAK,EAAE,IAAI,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAC9E,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,YAAY,EAAE,CAAC;IAE/B,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACzC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC;IAE3B,MAAM,UAAU,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAC;IACpD,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,MAAM,CAA8B,IAAI,CAAC,CAAC;IAC9D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC;QACjD,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,KAAK;KACjB,CAAC,CAAC;IAEH,MAAM,kBAAkB,GAAG,WAAW,CACpC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,eAAe,EACjC,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,MAAM,mBAAmB,GAAG,WAAW,CACrC,CAAC,SAAkB,EAAE,SAAkB,EAAE,EAAE;QACzC,YAAY,CAAC,OAAO,GAAG,SAAS,CAAC;QACjC,YAAY,CAAC,OAAO,GAAG,SAAS,CAAC;QAEjC,gBAAgB,CAAC,CAAC,OAAO,EAAE,EAAE;YAC3B,IACE,OAAO,CAAC,SAAS,KAAK,SAAS;gBAC/B,OAAO,CAAC,SAAS,KAAK,SAAS,EAC/B,CAAC;gBACD,OAAO,OAAO,CAAC;YACjB,CAAC;YAED,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;QAClC,CAAC,CAAC,CAAC;IACL,CAAC,EACD,EAAE,CACH,CAAC;IAEF,MAAM,iBAAiB,GAAG,WAAW,CAAC,GAAG,EAAE;QACzC,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;QAE7C,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAClC,OAAO;QACT,CAAC;QAED,mBAAmB,CACjB,eAAe,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,EAC5C,eAAe,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAC7C,CAAC;IACJ,CAAC,EAAE,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAE9C,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE;QACpC,IAAI,CAAC,OAAO,IAAI,IAAI,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YAC7C,OAAO;QACT,CAAC;QAED,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;QAC7C,IAAI,eAAe,EAAE,CAAC;YACpB,eAAe,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAChD,iBAAiB,EAAE,CAAC;QACtB,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE3D,MAAM,WAAW,GAAG,WAAW,CAAC,GAAG,EAAE;QACnC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;QAC7C,IAAI,eAAe,EAAE,CAAC;YACpB,eAAe,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YAC/C,iBAAiB,EAAE,CAAC;QACtB,CAAC;IACH,CAAC,EAAE,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE5C,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YAC1B,YAAY,EAAE,CAAC;QACjB,CAAC;QAED,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QAED,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;QAC7C,IAAI,eAAe,EAAE,CAAC;YACpB,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACzC,iBAAiB,EAAE,CAAC;QACtB,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,kBAAkB,EAAE,YAAY,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAEzE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;QAC5B,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;QAC7C,IAAI,eAAe,EAAE,CAAC;YACpB,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACxC,iBAAiB,EAAE,CAAC;QACtB,CAAC;IACH,CAAC,EAAE,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,iBAAiB,EAAE,CAAC;IACtB,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAExB,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,cAAc,GAAG,iBAAiB,CAAC,OAAO,CAAC;QACjD,IAAI,iBAAiB,CAAC,cAAc,EAAE,MAAM,CAAC,EAAE,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,iBAAiB,CAAC,OAAO,GAAG,MAAM,CAAC;QAEnC,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;QAC7C,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC;QACxC,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC;QAExC,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,mBAAmB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAClC,OAAO;QACT,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACvC,CAAC;QACD,IAAI,UAAU,EAAE,CAAC;YACf,eAAe,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC;YACrB,IAAI,UAAU,EAAE,CAAC;gBACf,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;iBAAM,IAAI,UAAU,EAAE,CAAC;gBACtB,eAAe,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QAED,iBAAiB,EAAE,CAAC;IACtB,CAAC,EAAE;QACD,MAAM;QACN,kBAAkB;QAClB,OAAO;QACP,IAAI;QACJ,iBAAiB;QACjB,mBAAmB;KACpB,CAAC,CAAC;IAEH,mCAAmC;IACnC,MAAM,MAAM,GAAG,WAAW,CAAC,GAA0B,EAAE;QACrD,OAAO,CAAC,OAAiB,EAAE,EAAE;YAC3B,4BAA4B;YAC5B,IAAI,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBACzD,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;oBACxB,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;oBACjC,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;gBAC7B,CAAC;gBACD,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;gBACjE,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;YACrE,CAAC;YAED,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;YAE7B,IAAI,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;gBACrB,OAAO;YACT,CAAC;YAED,wBAAwB;YACxB,IAAI,UAAU,EAAE,CAAC;gBACf,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;gBACnD,OAAO,CAAC,gBAAgB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;YACvD,CAAC;YAED,6BAA6B;YAC7B,IAAI,eAAe,IAAI,OAAO,oBAAoB,KAAK,WAAW,EAAE,CAAC;gBACnE,WAAW,CAAC,OAAO,GAAG,IAAI,oBAAoB,CAC5C,CAAC,OAAO,EAAE,EAAE;oBACV,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,IAAI,KAAK,CAAC;oBACtD,IAAI,SAAS,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;wBACvC,YAAY,EAAE,CAAC;oBACjB,CAAC;yBAAM,IAAI,CAAC,SAAS,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;wBAC9C,WAAW,EAAE,CAAC;oBAChB,CAAC;gBACH,CAAC,EACD,EAAE,SAAS,EAAE,GAAG,EAAE,CACnB,CAAC;gBACF,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,aAAa,GAAG,GAAG,EAAE;YACzB,KAAK,EAAE,CAAC;QACV,CAAC,CAAC;QAEF,MAAM,cAAc,GAAG,CAAC,KAAiB,EAAE,EAAE;YAC3C,uDAAuD;YACvD,IACE,UAAU,CAAC,OAAO;gBAClB,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAqB,CAAC,EACzD,CAAC;gBACD,IAAI,EAAE,CAAC;YACT,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE;QACD,IAAI;QACJ,UAAU;QACV,eAAe;QACf,KAAK;QACL,IAAI;QACJ,YAAY;QACZ,WAAW;KACZ,CAAC,CAAC;IAEH,sBAAsB;IACtB,SAAS,CACP,GAAG,EAAE,CAAC,GAAG,EAAE;QACT,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACxB,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACnC,CAAC;QACD,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;YACzB,WAAW,EAAE,CAAC;QAChB,CAAC;IACH,CAAC,EACD,CAAC,WAAW,CAAC,CACd,CAAC;IAEF,OAAO;QACL,IAAI;QACJ,KAAK;QACL,MAAM;QACN,SAAS,EAAE,aAAa,CAAC,SAAS;QAClC,SAAS,EAAE,aAAa,CAAC,SAAS;QAClC,YAAY;QACZ,WAAW;KACZ,CAAC;AACJ,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { SyncBacklogContext, SyncClientContext, SyncContext, SyncStatusContext, } from "./context.js";
|
|
2
|
+
export { useConnectionState, useIsOffline, usePendingCount, useSync, } from "./hooks/use-connection-state.js";
|
|
3
|
+
export { useModel, useModelState } from "./hooks/use-model.js";
|
|
4
|
+
export { useQuery, useQueryAll } from "./hooks/use-query.js";
|
|
5
|
+
export { useSyncClient, useSyncClientInstance, useSyncReady, useSyncState, } from "./hooks/use-sync-client.js";
|
|
6
|
+
export type { UseYjsDocumentOptions, UseYjsDocumentResult, YjsConnectionState, YjsSessionState, } from "./hooks/use-yjs-document.js";
|
|
7
|
+
export { useYjsDocument } from "./hooks/use-yjs-document.js";
|
|
8
|
+
export { SyncProvider } from "./provider.js";
|
|
9
|
+
export type { SyncContextValue, UseModelResult, UseQueryOptions, UseQueryResult, } from "./types.js";
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,OAAO,GACR,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,YAAY,GACb,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,qBAAqB,EACrB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,GAChB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// biome-ignore lint/performance/noBarrelFile: package entry point
|
|
2
|
+
export { SyncBacklogContext, SyncClientContext, SyncContext, SyncStatusContext, } from "./context.js";
|
|
3
|
+
export { useConnectionState, useIsOffline, usePendingCount, useSync, } from "./hooks/use-connection-state.js";
|
|
4
|
+
export { useModel, useModelState } from "./hooks/use-model.js";
|
|
5
|
+
export { useQuery, useQueryAll } from "./hooks/use-query.js";
|
|
6
|
+
export { useSyncClient, useSyncClientInstance, useSyncReady, useSyncState, } from "./hooks/use-sync-client.js";
|
|
7
|
+
export { useYjsDocument } from "./hooks/use-yjs-document.js";
|
|
8
|
+
export { SyncProvider } from "./provider.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,WAAW,EACX,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,OAAO,GACR,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,YAAY,GACb,MAAM,4BAA4B,CAAC;AAOpC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { SyncProviderProps } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Provider component for the sync client
|
|
5
|
+
*/
|
|
6
|
+
export declare const SyncProvider: ({ client, children, autoStart, autoStop, }: SyncProviderProps) => ReactNode;
|
|
7
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQvC,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,4CAK1B,iBAAiB,KAAG,SAsItB,CAAC"}
|