AI agents: fetch the documentation index at llms.txt. Markdown versions are available by appending .md to any page URL, including this page's markdown.
YjsPresenceManager
Manages presence signaling, view/edit tracking, and session state for collaborative editing.
Tracks which documents you're viewing and editing, signals state to the server, and receives session updates with active participants.
Creating an instance
Use the same clientId and connId values as your YjsDocumentManager.
import { YjsPresenceManager } from "@stratasync/y-doc";
const presenceManager = new YjsPresenceManager({
clientId: "client-abc-123",
connId: "conn-xyz-456",
});PresenceManagerConfig
| Property | Type | Description |
|---|---|---|
clientId | string | Logical client identity for attribution. |
connId | string | Connection-scoped identity for echo suppression and ownership. |
Setting the transport
Set before signaling presence. See YjsDocumentManager for transport setup.
presenceManager.setTransport(yjsTransport);Listens for session_state messages and sends doc_view and doc_focus messages.
API reference
startViewing
Signals that you opened a document.
import type { DocumentKey } from "@stratasync/y-doc";
const docKey: DocumentKey = {
entityType: "Task",
entityId: "task-123",
fieldName: "description",
};
presenceManager.startViewing(docKey);Signature: startViewing(docKey: DocumentKey): void
Duplicate calls for the same document are ignored.
stopViewing
Signals that you closed a document. Auto-calls blur if editing.
presenceManager.stopViewing(docKey);Signature: stopViewing(docKey: DocumentKey): void
focus
Signals editor focus. Auto-calls startViewing if not already viewing.
presenceManager.focus(docKey);Signature: focus(docKey: DocumentKey): void
Sends a doc_focus message with state "focus".
blur
Signals editor blur.
presenceManager.blur(docKey);Signature: blur(docKey: DocumentKey): void
Sends a doc_focus message with state "blur".
isViewing
Returns whether you're viewing a document.
const viewing: boolean = presenceManager.isViewing(docKey);Signature: isViewing(docKey: DocumentKey): boolean
isEditing
Returns whether you're editing a document.
const editing: boolean = presenceManager.isEditing(docKey);Signature: isEditing(docKey: DocumentKey): boolean
getSessionState
Returns session state with active participants.
import type { SessionState } from "@stratasync/y-doc";
const session: SessionState | null = presenceManager.getSessionState(docKey);
if (session) {
const activeCount = session.participants.filter((p) => p.isEditing).length;
}Signature: getSessionState(docKey: DocumentKey): SessionState | null
Returns null if no session state has been received yet.
SessionState
interface SessionState {
active: boolean;
participants: SessionParticipant[];
}| Property | Type | Description |
|---|---|---|
active | boolean | Whether the session is active (at least one participant). |
participants | SessionParticipant[] | List of participants. |
SessionParticipant
interface SessionParticipant {
userId: string;
isEditing: boolean;
}| Property | Type | Description |
|---|---|---|
userId | string | The participant's user ID. |
isEditing | boolean | Whether the participant is editing (focused). |
onSessionStateChange
Fires with current state, then on each change.
const unsubscribe = presenceManager.onSessionStateChange(docKey, (session) => {
updateParticipantList(session.participants);
showCollaborationBadge(session.active);
});
unsubscribe();Signature: onSessionStateChange(docKey: DocumentKey, callback: (state: SessionState) => void): () => void
Returns an unsubscribe function.
cleanup
Stops viewing all documents and clears state.
presenceManager.cleanup();Signature: cleanup(): void
Presence lifecycle
User opens document --> startViewing() --> doc_view "start" sent
User clicks editor --> focus() --> doc_focus "focus" sent
User clicks elsewhere --> blur() --> doc_focus "blur" sent
User closes document --> stopViewing() --> doc_view "stop" sent
The server aggregates signals into SessionState updates and broadcasts to all participants.
Full example
import { YjsPresenceManager } from "@stratasync/y-doc";
import type { DocumentKey } from "@stratasync/y-doc";
const presenceManager = new YjsPresenceManager({
clientId: "client-123",
connId: "conn-456",
});
presenceManager.setTransport(yjsTransport);
const docKey: DocumentKey = {
entityType: "Task",
entityId: "task-abc",
fieldName: "description",
};
const unsubscribe = presenceManager.onSessionStateChange(docKey, (session) => {
const editors = session.participants.filter((p) => p.isEditing);
updateUI({ activeEditors: editors.length, isActive: session.active });
});
presenceManager.startViewing(docKey);
presenceManager.focus(docKey);
presenceManager.blur(docKey);
presenceManager.stopViewing(docKey);
unsubscribe();