# Editor

The `withPortive` plugin adds image and file attachment uploading to Slate.

```ts
type withEditor =
  (editor: Editor, options: Options) =>
    Editor & { portive: PortiveObject } =
```

When used with `withReact` and `withHistory` those plugins should be applied inside:

```ts
import { createEditor } from "slate"
import { withHistory } from "slate-history"
import { withReact } from "slate-react"
import { withPortive } from "slate-images-and-attachments"

const [editor] = useState(() => {
  const reactEditor = withReact(withHistory(createEditor()))
  const portiveEditor = withPortive(reactEditor, {
    // ...options
  })
})
```

## Options

Configuration options for `withPortive`:

```ts
type Options = {
  authToken: string | (() => string | Promise<string>)
  initialMaxSize: [number, number]
  minResizeWidth?: number
  maxResizeWidth?: number
  initialOrigins: Record<string, Origin>
}
```

### `authToken: string | () => string | () => Promise<string>`

To learn what an `authToken` is, why you need one and how to generate one see the `authToken` reference.

The `authToken` can be provided as a `string` or a `function` (including an `async function`) that returns a `string`.

### `initialMaxSize: [number, number]`

Sets the initial maximum size of an uploaded image in the Editor. The value represents a max `[width, height]`.

If an image is smaller than the `initialMaxSize` width/height, the image is shown at full size. If an image is larger than the width/height, the image is scaled down to fit within the width/height.

### `minResizeWidth?: number = 100`

Images below the `minResizeWidth` are not shown drag handles for resizing. This is usually a good idea because there is not much value in resizing very small images and the resize handles can overwhelm the size of a small image.

Images above the `minResizeWidth` can be resized, but they can only be resized down to the `minResizeWidth`.

### `maxResizeWidth?: number = 1280`

The maximum width an image can be resized to.

### `createImageFileElement: (e: CreateImageFileElementEvent) => Element & ImageElementInterface`

```ts
type CreateImageFileEvent = {
  originKey: string
  originSize: [number, number]
  initialSize: [number, number]
  file: File
}

type ImageElementInterface = {
  originKey: string
  originSize: [number, number]
  size: [number, number]
}
```

When a user starts uploading a file, it is handled in one of two ways:

1. If it is a supported image file type (e.g. `.gif`, `.jpg`, `.jpeg`, `.png` or `.webp`) then this method `createImageFileElement` is called
2. If it is not a supported image file type then a different method `createGenericFileElement` is called

The result of the callback is an Image `Element` which must include but is not limited to these props:

* `originKey` which is a `string` the file's `Origin` (i.e. where it comes from and also its current uploading state).
* `originSize` which are the dimensions of the image a the `Origin`
* `size` which represents the current display width/height of the image

Typically, these properties are passed almost straight through from the `CreateImageFileEvent`. for example:

```ts
usePortive(editor, {
  // ...
  createImageFileElement(e) {
    return {
      type: "my-image-element-type", // the type for the image element desired
      originKey: e.originKey,
      originSize: e.originSize,
      size: e.initialSize,
      children: [{ text: "" }], // the `children` on a `Void` element
    }
  },
})
```

### `createGenericFileElement: (e: CreateGenericFileElementEvent) => Element & { originKey: string }`

```ts
type CreateGenericFileEvent = {
  originKey: string
  file: File
}

type GenericElementInterface = {
  originKey: string
}
```

1. If it is a supported image file type (e.g. `.gif`, `.jpg`, `.jpeg`, `.png` or `.webp`) then a different method `createImageFileElement` is called
2. If it is not a supported image file type then this method `createGenericFileElement` is called

The result of the callback is a Generic File `Element` (i.e. usually an Element that represents a file attachment) which must include but is not limited to this prop:

* `originKey` which is a `string` the file's `Origin` (i.e. where it comes from and also its current uploading state).

Typically, several of these properties are used to provide information for an attachment Element. for example:

```ts
usePortive(editor, {
  // ...
  createGenericFileElement(e) {
    return {
      type: "my-attachment-type", // the type for the image element desired
      originKey: e.originKey,
      originalFilename: e.file.filename,
      sizeInBytes: e.file.size,
      children: [{ text: "" }], // the `children` on a `Void` element
    }
  },
})
```

### `initialOrigins?: Record<string, Origin> = {}`

*For Unit Testing and Demos*

When a file is uploaded, the state of the upload is kept in a [`zustand`](https://github.com/pmndrs/zustand) store outside of the editor value. This is necessary so that the upload progress is not part of Slate's edit history.

During testing, however, we may wish to create an `editor` object with


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://slate-portive.docs.portive.com/reference/with-portive.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
