Collaboration
Connect a Yjs document, report provider status, and release collaboration resources.
Use createYjsCollaborationSession() with a Yjs document and your network provider. Register the session through collaborationModule() when you create the editor. Your application owns transport, authentication, authorization, and persistence.
For support status, see Real-time collaborationNo. Review concurrent editing limits before enabling shared editing.
Install the dependencies
Install the session package and the Yjs dependencies that your host imports:
npm install @pptx-editor.dev/core @pptx-editor.dev/pro yjs y-protocolsAdd your React or Vue adapter separately.
Create one session per editor
This function accepts a provider-connected document and awareness instance. Call it after the provider has loaded the room state. Pass a container with a nonzero height, such as height: 100vh:
import type * as Y from 'yjs';
import type { Awareness } from 'y-protocols/awareness';
import { createPptxEditor } from '@pptx-editor.dev/core/editor';
import '@pptx-editor.dev/core/styles/editor.css';
import { collaborationModule, createYjsCollaborationSession } from '@pptx-editor.dev/pro';
export function openCollaborativeEditor(
bytes: Uint8Array,
container: HTMLElement,
doc: Y.Doc,
awareness: Awareness,
documentId: string,
actorId: string,
name: string
) {
const session = createYjsCollaborationSession({
doc,
awareness,
documentId,
identity: { actorId, name, color: '#2563EB' },
});
const editor = createPptxEditor({
document: bytes,
modules: [collaborationModule({ session })],
});
container.classList.add('pptx-editor');
editor.attach(container);
return {
editor,
session,
destroy() {
editor.destroy();
session.destroy();
},
};
}The first editor seeds an empty room from its presentation. An editor joining an existing room adopts the room content. Use the same documentId for participants in the same presentation and distinct actor identifiers for participants.
In React or Vue, pass [collaborationModule({ session })] through the adapter’s modules prop instead. Keep that list stable. Create a separate session for each editor instance.
Connect your provider
The session does not open a network connection. Your provider synchronizes Yjs document updates and awareness messages. Reuse the provider’s awareness instance so remote names, colors, and selections reach the editor. Without awareness, the session lists only the local participant.
Report connection changes through setConnected():
// Call these from your provider's connection event handlers.
session.setConnected(false); // Disconnected; local edits can continue.
session.setConnected(true); // Connected again.Read session.statusSnapshot() for state and failure details. Subscribe with session.subscribeStatus(listener) and release the returned subscription when your UI unmounts. A connection flag reports transport state; it does not authenticate a participant.
Handle unfinished input during peer edits
An input method composes text before the participant commits it. A peer's edit after an unfinished composition, or in another paragraph, keeps the composition. When a peer's edit changes the text before it, the composition ends and its text is not entered. The editor reports this as lastRejection in editor.snapshot(), with the reason errors.compositionChanged. A composition over selected text ends the same way when that text changes, with the reason errors.compositionRangeChanged. The edit notice of the React and Vue adapters shows the translated message.
lastRejection stays set after later edits, so do not react to every editor.subscribe() notification. Use onEditorEvent(), which calls its handler once for each new rejection. This example uses the editor from Create one session per editor:
import { onEditorEvent } from '@pptx-editor.dev/core/editor';
const off = onEditorEvent(editor, 'rejection', (rejection) => {
const reason = rejection.reason;
if (reason === 'errors.compositionChanged' || reason === 'errors.compositionRangeChanged') {
// Ask the participant to type the text again.
}
});
// Call off() when your UI unmounts.In React, call useEditorEvent('rejection', handler) inside the editor root; in Vue, call useEditorEvent('rejection', handler). Each unsubscribes when its component unmounts. To get the editor instance itself, use usePptxEditor() in React or usePptxEditor() in Vue.
Save and close a room
Save the PPTX through the editor. Persist Yjs room updates separately when you need a durable collaboration room. A saved PPTX does not replace your provider’s room persistence.
Destroy the editor before its session. Then disconnect and destroy provider resources that your application owns, including awareness and the Yjs document. Do not destroy a document shared by another active consumer.
Handle history and access
Undo and redo operate on the local participant’s changes through the collaboration session. Concurrent changes can affect what an undo retains. Review the concurrent editing limits below.
Authenticate users before connecting them to a room. Authorize document access and enforce write permissions in your provider or server. A documentId is an identifier, not an access token. Use encrypted transport and disconnect participants when access ends.
Concurrent editing limits
- Undo and redo. Undo can remove peer text inside a shape, row, or cell that you created. Redo restores that content.
- Text conflicts. Concurrent formatting, paragraph splits, and undo can duplicate or reorder text. Some sequences involving three participants can lose characters.
- Table conflicts. Concurrent cell merges and row or column changes can lose text in some sequences. For example, merging cells while two peers delete covered rows can lose merged text.
- Property conflicts. Concurrent writes to one attribute keep one value. Overlapping fills or effects can reveal the other version when the winning edit is undone.
Upgrade the room format
The room records the format version of the session that seeded it. A release of @pptx-editor.dev/pro can change that format, and its release notes say so. A session refuses a room with another format version, at attach or when that version arrives later, for example when the provider syncs after attach. The session status becomes error with the reason code schema-version-mismatch. The session stops applying the room, and the editor keeps its own presentation.
Update every participant of a room to the same release at the same time. To tell a participant to save local work and load a compatible version, check the reason code. This example uses the session from Create one session per editor:
const unsubscribe = session.subscribeStatus(() => {
const { status, reason } = session.statusSnapshot();
if (status === 'error' && reason?.code === 'schema-version-mismatch') {
// Ask the participant to save local changes and reload the app.
}
});
// Call unsubscribe() when your UI unmounts.Do not reset a populated room to bypass that refusal.