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

# React

> Render Embed Editor in a React app with the EmbedEditor component.

Render the editor in a React app with the `EmbedEditor` component.

> [!TIP]
>
> Try every prop live in the [playground](https://embededitor.com/playground#c=eyJlZGl0aW9uIjoiRlVMTCJ9), open on React, and copy the code it writes.

> [tab] Free
>
> Free is on public npm, with no key. It has the Adjust tools, and a small "embededitor.com" badge in the corner of the menu.
>
> ## Install
>
> ```bash npm theme={"dark"}
> npm install @embededitor/free
> ```
>
> ```bash yarn theme={"dark"}
> yarn add @embededitor/free
> ```
>
> ```bash pnpm theme={"dark"}
> pnpm add @embededitor/free
> ```
>
> ```bash bun theme={"dark"}
> bun add @embededitor/free
> ```
>
> The React entry needs `react` and `react-dom` 18.3 or 19 as peers. There is no CSS to import.
>
> ## Render
>
> ```tsx PhotoEditor.tsx theme={"dark"}
> import { EmbedEditor } from '@embededitor/free/react';
>
> const PhotoEditor = ({ src }: { src: string }) => (
>   <div style={{ height: 600 }}>
>     <EmbedEditor lang='en-us' src={src} />
>   </div>
> );
>
> export default PhotoEditor;
> ```
>
> The editor fills the box its parent gives it, so give the parent a height, and at least 320 px of width.
>
> ## Get the File Back
>
> `onProcess` receives the saved `File` and the state it was made with.
>
> ```tsx PhotoEditor.tsx theme={"dark"}
> import { EmbedEditor } from '@embededitor/free/react';
> import type { EditState } from '@embededitor/free/react';
>
> const upload = async ({ dest, state }: { dest: File; state: EditState }) => {
>   const body = new FormData();
>
>   body.append('file', dest);
>   body.append('state', JSON.stringify(state));
>   await fetch('/api/photos', { body, method: 'POST' });
> };
>
> const PhotoEditor = ({ src }: { src: string }) => (
>   <div style={{ height: 600 }}>
>     <EmbedEditor lang='en-us' onProcess={upload} src={src} />
>   </div>
> );
>
> export default PhotoEditor;
> ```
>
> ## Open as a Modal
>
> `openEditor` opens the editor over the page: a dialog on a desktop, a bottom sheet on a phone.
>
> ```ts edit-photo.ts theme={"dark"}
> import { openEditor } from '@embededitor/free/react';
>
> const editPhoto = (file: File) => {
>   const { close } = openEditor({
>     onProcess: ({ dest }) => {
>       console.info('saved', dest.name);
>     },
>     src: file
>   });
>
>   return close;
> };
> ```
>
> More in [Open as a modal](https://docs.embededitor.com/guides/modal.md).
>
> ## Update Props
>
> Props apply live: change them like any other React prop.
>
> `src` and `state` are read when the editor opens. Once an image is on screen, give the editor a new `key` to open another one.
>
> ```tsx PhotoEditor.tsx theme={"dark"}
> <EmbedEditor key={photo.id} src={photo.url} />
> ```
>
> Pass a stable `src` (memoize it). A new `Blob` or `URL.createObjectURL(file)` written inline restarts the load each time the component renders while the image loads.
>
> ## Clean Up
>
> Unmount the component to remove the editor. For the modal, call the `close` that `openEditor` returns; Save closes it too, once `onProcess` returns.
>
> > [!TIP]
> >
> > `data-*` and `aria-*` attributes on `EmbedEditor` go to its host element, which helps with tests and analytics. Any other unknown prop is invalid.

> [tab] Lite
>
> Lite has the Adjust tools, without the badge. It installs from the private registry, with the key of your license.
>
> ## Set Up the Registry
>
> Your license key is on its card in your account at `account.embededitor.com`. [Buy a plan](https://embededitor.com/pricing) to get one.
>
> Point the `@embededitor` scope at the registry, and keep the key in an environment variable named `EMBED_EDITOR_KEY`, out of git.
>
> For npm, pnpm, bun and Yarn 1, add this to the `.npmrc` of your project:
>
> ```ini .npmrc theme={"dark"}
> @embededitor:registry=https://get.embededitor.com/
> //get.embededitor.com/:_authToken=${EMBED_EDITOR_KEY}
> ```
>
> Yarn 2 and newer ignore `.npmrc`. Add this to `.yarnrc.yml` instead:
>
> ```yaml .yarnrc.yml theme={"dark"}
> npmScopes:
>   embededitor:
>     npmRegistryServer: "https://get.embededitor.com"
>     npmAuthToken: "${EMBED_EDITOR_KEY}"
> ```
>
> Set the key where your install runs, your shell or your CI's secrets, never in git:
>
> ```bash Terminal theme={"dark"}
> export EMBED_EDITOR_KEY=<your-key>
> ```
>
> ## Install
>
> ```bash npm theme={"dark"}
> npm install @embededitor/lite
> ```
>
> ```bash yarn theme={"dark"}
> yarn add @embededitor/lite
> ```
>
> ```bash pnpm theme={"dark"}
> pnpm add @embededitor/lite
> ```
>
> ```bash bun theme={"dark"}
> bun add @embededitor/lite
> ```
>
> The React entry needs `react` and `react-dom` 18.3 or 19 as peers. There is no CSS to import.
>
> ## Render
>
> ```tsx PhotoEditor.tsx theme={"dark"}
> import { EmbedEditor } from '@embededitor/lite/react';
>
> const PhotoEditor = ({ src }: { src: string }) => (
>   <div style={{ height: 600 }}>
>     <EmbedEditor lang='en-us' src={src} />
>   </div>
> );
>
> export default PhotoEditor;
> ```
>
> The editor fills the box its parent gives it, so give the parent a height, and at least 320 px of width.
>
> ## Get the File Back
>
> `onProcess` receives the saved `File` and the state it was made with.
>
> ```tsx PhotoEditor.tsx theme={"dark"}
> import { EmbedEditor } from '@embededitor/lite/react';
> import type { EditState } from '@embededitor/lite/react';
>
> const upload = async ({ dest, state }: { dest: File; state: EditState }) => {
>   const body = new FormData();
>
>   body.append('file', dest);
>   body.append('state', JSON.stringify(state));
>   await fetch('/api/photos', { body, method: 'POST' });
> };
>
> const PhotoEditor = ({ src }: { src: string }) => (
>   <div style={{ height: 600 }}>
>     <EmbedEditor lang='en-us' onProcess={upload} src={src} />
>   </div>
> );
>
> export default PhotoEditor;
> ```
>
> ## Open as a Modal
>
> `openEditor` opens the editor over the page: a dialog on a desktop, a bottom sheet on a phone.
>
> ```ts edit-photo.ts theme={"dark"}
> import { openEditor } from '@embededitor/lite/react';
>
> const editPhoto = (file: File) => {
>   const { close } = openEditor({
>     onProcess: ({ dest }) => {
>       console.info('saved', dest.name);
>     },
>     src: file
>   });
>
>   return close;
> };
> ```
>
> More in [Open as a modal](https://docs.embededitor.com/guides/modal.md).
>
> ## Update Props
>
> Props apply live: change them like any other React prop.
>
> `src` and `state` are read when the editor opens. Once an image is on screen, give the editor a new `key` to open another one.
>
> ```tsx PhotoEditor.tsx theme={"dark"}
> <EmbedEditor key={photo.id} src={photo.url} />
> ```
>
> Pass a stable `src` (memoize it). A new `Blob` or `URL.createObjectURL(file)` written inline restarts the load each time the component renders while the image loads.
>
> ## Clean Up
>
> Unmount the component to remove the editor. For the modal, call the `close` that `openEditor` returns; Save closes it too, once `onProcess` returns.
>
> > [!TIP]
> >
> > `data-*` and `aria-*` attributes on `EmbedEditor` go to its host element, which helps with tests and analytics. Any other unknown prop is invalid.

> [tab] Full
>
> Full has every tool, without the badge. It installs from the private registry, with the key of your license.
>
> ## Set Up the Registry
>
> Your license key is on its card in your account at `account.embededitor.com`. [Buy a plan](https://embededitor.com/pricing) to get one.
>
> Point the `@embededitor` scope at the registry, and keep the key in an environment variable named `EMBED_EDITOR_KEY`, out of git.
>
> For npm, pnpm, bun and Yarn 1, add this to the `.npmrc` of your project:
>
> ```ini .npmrc theme={"dark"}
> @embededitor:registry=https://get.embededitor.com/
> //get.embededitor.com/:_authToken=${EMBED_EDITOR_KEY}
> ```
>
> Yarn 2 and newer ignore `.npmrc`. Add this to `.yarnrc.yml` instead:
>
> ```yaml .yarnrc.yml theme={"dark"}
> npmScopes:
>   embededitor:
>     npmRegistryServer: "https://get.embededitor.com"
>     npmAuthToken: "${EMBED_EDITOR_KEY}"
> ```
>
> Set the key where your install runs, your shell or your CI's secrets, never in git:
>
> ```bash Terminal theme={"dark"}
> export EMBED_EDITOR_KEY=<your-key>
> ```
>
> ## Install
>
> ```bash npm theme={"dark"}
> npm install @embededitor/full
> ```
>
> ```bash yarn theme={"dark"}
> yarn add @embededitor/full
> ```
>
> ```bash pnpm theme={"dark"}
> pnpm add @embededitor/full
> ```
>
> ```bash bun theme={"dark"}
> bun add @embededitor/full
> ```
>
> The React entry needs `react` and `react-dom` 18.3 or 19 as peers. There is no CSS to import.
>
> ## Render
>
> ```tsx PhotoEditor.tsx theme={"dark"}
> import { EmbedEditor } from '@embededitor/full/react';
>
> const PhotoEditor = ({ src }: { src: string }) => (
>   <div style={{ height: 600 }}>
>     <EmbedEditor lang='en-us' src={src} />
>   </div>
> );
>
> export default PhotoEditor;
> ```
>
> The editor fills the box its parent gives it, so give the parent a height, and at least 320 px of width.
>
> ## Get the File Back
>
> `onProcess` receives the saved `File` and the state it was made with.
>
> ```tsx PhotoEditor.tsx theme={"dark"}
> import { EmbedEditor } from '@embededitor/full/react';
> import type { EditState } from '@embededitor/full/react';
>
> const upload = async ({ dest, state }: { dest: File; state: EditState }) => {
>   const body = new FormData();
>
>   body.append('file', dest);
>   body.append('state', JSON.stringify(state));
>   await fetch('/api/photos', { body, method: 'POST' });
> };
>
> const PhotoEditor = ({ src }: { src: string }) => (
>   <div style={{ height: 600 }}>
>     <EmbedEditor lang='en-us' onProcess={upload} src={src} />
>   </div>
> );
>
> export default PhotoEditor;
> ```
>
> ## Open as a Modal
>
> `openEditor` opens the editor over the page: a dialog on a desktop, a bottom sheet on a phone.
>
> ```ts edit-photo.ts theme={"dark"}
> import { openEditor } from '@embededitor/full/react';
>
> const editPhoto = (file: File) => {
>   const { close } = openEditor({
>     onProcess: ({ dest }) => {
>       console.info('saved', dest.name);
>     },
>     src: file
>   });
>
>   return close;
> };
> ```
>
> More in [Open as a modal](https://docs.embededitor.com/guides/modal.md).
>
> ## Update Props
>
> Props apply live: change them like any other React prop.
>
> `src` and `state` are read when the editor opens. Once an image is on screen, give the editor a new `key` to open another one.
>
> ```tsx PhotoEditor.tsx theme={"dark"}
> <EmbedEditor key={photo.id} src={photo.url} />
> ```
>
> Pass a stable `src` (memoize it). A new `Blob` or `URL.createObjectURL(file)` written inline restarts the load each time the component renders while the image loads.
>
> ## Clean Up
>
> Unmount the component to remove the editor. For the modal, call the `close` that `openEditor` returns; Save closes it too, once `onProcess` returns.
>
> > [!TIP]
> >
> > `data-*` and `aria-*` attributes on `EmbedEditor` go to its host element, which helps with tests and analytics. Any other unknown prop is invalid.

## Next Steps

> [card] [Props](https://docs.embededitor.com/api-reference/props.md)
>
> Every option the editor takes.

> [card] [The Saved State](https://docs.embededitor.com/saving/saved-state.md)
>
> Reopen a photo with its edits.

> [card] [Next.js](https://docs.embededitor.com/frameworks/nextjs.md)
>
> Server components and safe areas.

> [card] [Theming](https://docs.embededitor.com/customization/theming.md)
>
> Match the editor to your brand.


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