@docx-editor.dev/react
v2.21.1
Published
React DOCX editor adapter for the @docx-editor.dev editor contract.
Maintainers
Readme
@docx-editor.dev/react
A visual .docx editor for React. Open a Word document, edit its paginated layout, and save a DOCX file. Parsing and serialization run in the browser.
Saving preserves untouched content, unsupported OOXML, and package payloads. Continuous integration (CI) checks document structure and save-and-reopen behavior.
Install the adapter and its required engine peer:
npm install @docx-editor.dev/react @docx-editor.dev/coreQuick start
Import the stylesheet once and give the editor a container with a defined height:
import { useState } from 'react';
import { DocxEditor } from '@docx-editor.dev/react';
import '@docx-editor.dev/core/styles/editor.css';
export function App() {
const [doc, setDoc] = useState<Uint8Array>();
return (
<div style={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
<input
type="file"
accept=".docx"
onChange={async (e) => {
const file = e.target.files?.[0];
setDoc(file ? new Uint8Array(await file.arrayBuffer()) : undefined);
}}
/>
<div style={{ flex: 1, minHeight: 0 }}>
{doc && <DocxEditor document={doc} mode="edit" />}
</div>
</div>
);
}<DocxEditor> is the full packaged editor: title bar, menu, toolbar, navigation pane, context menu, and the painted document. It fills its parent, so give it a box with a real height, and import the stylesheet once.
For Next.js and server-side rendering (SSR), load the editor in the browser. Use dynamic(..., { ssr: false }) inside a Client Component.
Build your own UI
The packaged chrome is one arrangement of public parts. Every packaged control uses the same hooks you would; there is no private API behind it.
import { DocxEditor, useEditorCommand } from '@docx-editor.dev/react';
function BoldButton() {
const bold = useEditorCommand('text.bold');
return (
<button
onMouseDown={(e) => e.preventDefault()} // chrome must not steal the caret
onClick={() => bold.execute()}
disabled={!bold.isEnabled}
data-active={bold.isActive || undefined}
>
Bold
</button>
);
}
export function Editor({ bytes }: { bytes: Uint8Array }) {
return (
<DocxEditor.Root document={bytes}>
<BoldButton />
<DocxEditor.Viewport>
<DocxEditor.Content />
</DocxEditor.Viewport>
</DocxEditor.Root>
);
}Root owns the editor instance, Viewport is the scroll container, Content is where pages are painted. Everything else (toolbar, menu, rulers, navigation, link popover, context menu) is optional and placed by name.
The customization ladder, in order: className and data-active → the icon prop → asChild (merge behavior onto your own element) → in-place slot override (hidden, preset={false}) → the hooks.
Hooks
| Hook | What it gives you |
| --- | --- |
| useEditorCommand(slot) | execute, isActive, isEnabled, disabledReason |
| useEditorState(selector) | A memoized slice of the editor snapshot |
| useDocxEditor() | The editor instance, or null before mount |
| useEditorEvent(event, fn) | change, selectionChange, error |
| useFontFamily() / useParagraphStyle() | Value controls: current value, options, setter |
| usePageSetup() | Margins, orientation, paper size |
| useDocumentOutline() / useDocumentSearch() | The navigation pane, headless |
| useContentControl() | Word content controls at the caret |
Enabled state has exactly one source. A control that hardcodes disabled will drift from the engine. Read isEnabled and show disabledReason.
Companion packages
@docx-editor.dev/pro— tracked changes, comments, custom nodes@docx-editor.dev/editor-api— A supported subset of the Word Office.js API for server and browser editing@docx-editor.dev/core— the engine this adapter renders
Documentation
License
Apache-2.0
