DocMosaicdocs
Get started

Controlled vs uncontrolled

Editor.Root supports both modes. Pick uncontrolled for plug-and-play, controlled when you need to own the document.

Editor.Root follows the standard React controlled/uncontrolled pattern. Pick the mode that fits your data layer.

Uncontrolled (default)

Editor.Root owns the document state and the history timeline internally. You don't pass anything.

<Editor.Root>{/* Editor.Root owns Document + history */}</Editor.Root>

Use this when you want a drop-in editor and don't need to persist state outside the React tree.

Controlled

Pass document + onChange to lift state out. You become the source of truth.

const [doc, setDoc] = useState<Document>(() => createDocument());

return (
    <Editor.Root document={doc} onChange={setDoc}>
        {/* ... */}
    </Editor.Root>
);

Use this when you want to:

  • Persist the document to localStorage / a backend / a URL
  • Sync the document across collaborators
  • Integrate with a different state container (Zustand, Redux, Jotai)

Headless: bring your own UI

If you want full control over the UI, skip Editor.Root and use useDocumentState directly:

import { useDocumentState } from '@docmosaic/react';

function CustomEditor() {
    const { document, actions, canUndo, canRedo } = useDocumentState();
    // render whatever UI you want
}

See BYO-UI with useDocumentState for the full pattern.