Version history
Google Docs-style, self-contained — no "save a version" button for your users to remember to click. Point-in-time document snapshots are captured automatically after each burst of edits settles down, each one attributed to whoever made the changes, stored in IndexedDB (a third object store alongside usePersistedDocument's documents and Templates' templates).
Quick start: <VersionHistory>
import { useEditor, NoteloomEditor, VersionHistory } from 'noteloom';
function Editor() {
const editor = useEditor({ currentUserId: currentUser.id }); // stamps every edit's author
return (
<NoteloomEditor editor={editor}>
<VersionHistory docId={docId} />
</NoteloomEditor>
);
}That's the whole integration. <VersionHistory> renders the "Version history" button, and for as long as it's mounted it also quietly captures snapshots in the background — no separate wiring needed. Clicking the button opens a drawer (matching the built-in Comments UI's own design language) listing every version grouped by day, each showing an avatar, author, relative time, and a lightweight summary ("3 blocks changed").
Clicking a version opens it on a Changes tab — a word-level diff against the version right before it, insertions highlighted green, deletions struck through in red, the same "show changes" idea as Google Docs — with a Preview tab alongside for a plain read-only render, and a "Restore this version" button.
Attribution
currentUserId (passed to useEditor(), or history.setDefaultActorId(id)/new History(store, { defaultActorId }) for the granular API) is stamped as every edit's actorId automatically — <VersionHistory> reads it straight off the history log, no separate identity plumbing required. Omit it and versions still get created, just with authorId: null (shown as "Unknown").
Tuning the capture window
<VersionHistory docId={docId} idleMs={5 * 60 * 1000} maxVersions={200} />idleMs (default 5 minutes) is how long edits need to pause before a version is closed and saved. maxVersions prunes the oldest versions beyond that count.
Granular API
For the granular API, or to save an explicit snapshot right before some risky action, use createAutoVersionHistory directly:
import { createAutoVersionHistory } from 'noteloom';
const versionHistory = createAutoVersionHistory({ store: editor.store, docId, idleMs: 5 * 60 * 1000, maxVersions: 200 });
// later, right before something risky (e.g. navigating away):
versionHistory.flush();
versionHistory.stop();Returns { stop, flush } — flush() closes and saves the current window immediately instead of waiting for the idle gap (e.g. right before navigating away).
Building your own UI
If <VersionHistory>'s built-in drawer doesn't fit, the reactive hook and raw storage operations it's built on are all exported individually:
import { useDocumentVersions, applyDocumentTemplate, diffDocumentsHTML } from 'noteloom';
function VersionList({ docId, store }) {
const { versions } = useDocumentVersions(docId); // newest first, reactive
const html = diffDocumentsHTML(null, versions[0]?.doc ?? null); // word-level diff; pass a real prevDoc to diff two versions
// ...render versions, call applyDocumentTemplate(store, version.doc) to restore one
}Restoring needs no new function — it's the exact same applyDocumentTemplate(store, doc) Templates already uses to wholesale-replace a live editor's content, which is what the drawer's own Restore button calls. saveDocumentVersion/loadDocumentVersion/deleteDocumentVersion/listDocumentVersions are the raw storage operations everything above is built on. diffDocumentsHTML(prevDoc, nextDoc) is the diffing function behind the Changes tab — pass null as prevDoc to mark everything as newly added.