> ## Documentation Index
> Fetch the complete documentation index at: https://docs.doconda.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Editor plugin

> Word, PowerPoint and Excel inside your site: a React component that opens, edits and saves the file in the browser.

The editor plugin is a **React component** you add to your product. Your users open a Word, PowerPoint or Excel
file (for example, the one your agent just created with Doconda), touch it up and save it, without leaving your
site. Everything happens in their browser: the file is not uploaded anywhere to be edited.

It is purchased separately from the API, per organization, with a **monthly, yearly or one-time** plan and a **7-day free trial**. See [licence and domains](/en/editor/license).

## Install

With an active licence, the dashboard (**Billing → Editor plugin**) gives you your install command, with a
personal link:

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
npm install https://api.eu.doconda.com/v1/editor/package/edt_….tgz
```

It is imported as `@doconda/editor`. It needs React 19 or later.

<Warning>
  The link is secret: don't publish it. If the licence stops being active, the link stops working. Every
  download carries a mark identifying your organization.
</Warning>

## Your first editor

```tsx theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import { DocondaEditor } from "@doconda/editor"

export function Edit({ url }: { url: string }) {
  return (
    <div style={{ height: 700, display: "flex" }}>
      <DocondaEditor src={url} licenseKey="ek_eu_…" className="flex-1" />
    </div>
  )
}
```

* `src` is the file's link: a `.docx`, `.pptx` or `.xlsx`. For example, the `url` of a file from
  `GET /documents/{id}/outputs`.
* The format is inferred from the link's extension. If the link has none, pass it with `format="docx"`, `"pptx"` or
  `"xlsx"`.
* The editor takes the height you give it: put it in a container with a height.
* `licenseKey` is your licence key (from the dashboard, under **Billing → Editor plugin**). Not needed on `localhost`.

## Open from memory or with headers

If you already have the file (an `<input type="file">`, a response from your API), pass it with `file`: a `File`, `Blob`,
`ArrayBuffer` or `Uint8Array`.

```tsx theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
<DocondaEditor file={selectedFile} licenseKey="ek_eu_…" />
```

If the link needs authentication, `requestInit` is passed as is to `fetch`:

```tsx theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
<DocondaEditor src="/api/contracts/42.docx" requestInit={{ headers: { Authorization: `Bearer ${token}` } }} />
```

## Save

Get the edited file through a `ref`:

```tsx theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
import { useRef } from "react"
import { DocondaEditor, type EditorHandle } from "@doconda/editor"

const editor = useRef<EditorHandle>(null)

<DocondaEditor ref={editor} src={url} licenseKey="ek_eu_…" />

const file = await editor.current!.save()   // a File (.docx, .pptx or .xlsx)
```

The file keeps the original's name (or whatever `fileName` says). The `ref` also has `bytes()` (the bytes, not
wrapped in a `File`), `focus()` and `isDirty()` (whether there are unsaved changes).

Or listen for **Ctrl/Cmd+S** with `onSave`, which receives the file's bytes:

```tsx theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
<DocondaEditor src={url} licenseKey="ek_eu_…" onSave={(bytes) => upload(bytes)} />
```

Or let it save on its own: with `autosave`, `onSave` is called once the user has gone that long (in milliseconds) without touching anything.

```tsx theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
<DocondaEditor
  src={url}
  autosave={2000}
  onSave={(bytes) => upload(bytes)}
  onDirtyChange={(pending) => setNotice(pending ? "Unsaved" : "Saved")}
  confirmOnLeave
/>
```

`onDirtyChange` tells you when there start to be unsaved changes and when they are saved. `confirmOnLeave` asks for
confirmation if the page is closed or reloaded with pending changes.

To save it in Doconda as a new version of the document (with its review, PDF and change report), send that
file to [`POST /documents/{id}/versions`](/en/guides/edit#save-a-hand-edited-version):

```ts theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
const body = new FormData()
body.append("file", await editor.current!.save())
await fetch(`https://api.eu.doconda.com/v1/documents/${id}/versions`, {
  method: "POST",
  headers: { Authorization: `Bearer ${DOCONDA_API_KEY}` },
  body,
})
```

<Warning>
  Make that call from your server: the API key must not reach the browser.
</Warning>

## What it can do

| Format | What it edits |
| - | - |
| **Word** | Text and paragraph styles, fonts, sizes, colours, highlighting, underlines, lists, indents, line spacing, borders and shading, tables and their styles, images, shapes, text boxes, links, columns, header and footer, footnotes, comments, table of contents, find and replace, print or save as PDF |
| **PowerPoint** | Slides (new, duplicate, reorder, layout, background), text with its styles, shapes, images, tables, group, align and distribute, layer order, transitions, entrance animations, speaker notes, zoom, full-screen presenting, print. Charts are shown and preserved |
| **Excel** | Cells and formulas (calculated in the editor, written as in Spanish-language Excel), cell and number formatting, borders, merge, wrap text, insert and delete rows and columns, change widths and heights, multiple sheets |

Whatever the editor does not touch is saved as is: styles, charts, notes or parts of the file it cannot edit are not
lost.

## Props

| Prop | What it does |
| - | - |
| `src` | The file's link |
| `file` | The file in memory (`File`, `Blob`, `ArrayBuffer` or `Uint8Array`), instead of `src` |
| `requestInit` | `fetch` options for downloading `src` (headers, credentials) |
| `format` | `"docx"`, `"pptx"` or `"xlsx"`, if the link has no extension |
| `fileName` | Name of the file returned by `save()` (defaults to the original's) |
| `licenseKey` | Your licence key (`ek_…`) |
| `readOnly` | View only: no toolbars, no editing |
| `author` | Name that signs new comments |
| `onReady` | The file has opened |
| `onError` | It could not be opened (or `editor_unlicensed`, without a licence) |
| `onChange` | Every time something changes |
| `onSave` | Ctrl/Cmd+S (and `autosave`), with the file's bytes |
| `autosave` | Milliseconds without changes after which `onSave` is called |
| `onDirtyChange` | There are unsaved changes (`true`) or they were saved (`false`) |
| `confirmOnLeave` | Asks for confirmation when leaving the page with unsaved changes |
| `fallback` | What is shown while it opens (for example, your spinner) |
| `className`, `style` | Container class and styles |
| `theme`, `locale`, `labels`, `toolbar`, `items`, `features`, `classNames`, `colors`, `fonts`, `spellCheck` | See [customize](/en/editor/customize) |
| `licenseUrl` | Only if you use a different Doconda API (defaults to your key's region) |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.