> ## 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.

# Annotate

> Add, change and remove annotations from code, as the user does on the photo: their style, their words, the action bar's verbs and the Numbers' list.

`annotate` does what the user does in Annotate: a tap or a drag of a tool on the photo, the style row and the color row, the words typed in the menu's field, and the verbs of the action bar.

The examples call the handle `editor`. See [Get the handle](https://docs.embededitor.com/api-reference/commands/overview.md#get-the-handle).

> [!NOTE]
>
> Annotate is in the Full and the Trial. In the Free and the Lite, every `annotate` command rejects with `NOT_AVAILABLE`, and `read.options()` answers `null`. While you turn Annotate off (`enableAnnotate: false`), the same.

```ts theme={"dark"}
annotate: {
	add: (input: { piece: AnnotatePiece }) => Promise<{ id: string }>;
	addArrow: (input: { id: string; to?: { x: number; y: number } }) => Promise<{ arrow: number; id: string }>;
	addLeader: (input: { id: string }) => Promise<null>;
	addText: (input: { body?: string; id: string; title?: string }) => Promise<{ id: string }>;
	bringToFront: (input: { id: string }) => Promise<null>;
	close: () => Promise<null>;
	detach: (input: { arrow?: number; id: string }) => Promise<null>;
	duplicate: (input: { id: string }) => Promise<{ id: string }>;
	list: () => Promise<null>;
	open: () => Promise<null>;
	remove: (input: { arrow?: number; id: string }) => Promise<null>;
	select: (input: { arrow?: number; id: string | null }) => Promise<null>;
	setListTitle: (input: { title: string }) => Promise<null>;
	setStyle: (input: Flat<AnnotateStyle & { kind?: 'ELLIPSE' | 'LINE' | 'RECT' | 'ROUNDED'; tool?: AnnotateTool }>) => Promise<null>;
	setTheme: (input: { theme: AnnotationTheme }) => Promise<null>;
	setTool: (input: { tool: AnnotateTool }) => Promise<null>;
	unlist: () => Promise<null>;
	update: (
		input: Flat<
			AnnotateStyle & {
				angle?: AnnotationAngle;
				arrow?: number;
				at?: AnnotationPoint;
				bend?: AnnotationBend;
				body?: string;
				box?: Rect;
				from?: AnnotationPoint;
				id: string;
				kind?: 'ELLIPSE' | 'RECT' | 'ROUNDED';
				label?: string;
				origin?: AnnotationPoint;
				radius?: number;
				theme?: AnnotationTheme;
				title?: string;
				to?: AnnotationPoint;
				width?: number | null;
			}
		>
	) => Promise<null>;
};
```

Everything goes by the names and units of the saved state's [annotations](https://docs.embededitor.com/api-reference/annotations.md): points in the px of the size the editor works the image at (`read.size()`), a text's size a share of the image's shorter side, a color a hex. An annotation goes by its `id` (`a1`, `a2`…), and the Numbers' list by `'LIST'`. An arrow added to a text or to the list has no id of its own: it goes by its owner's `id` (`'LIST'` for the list) and its place in its owner's `arrows` (`arrow`).

## How These Commands Behave

* **An edit never opens Annotate.** `add`, `update` and the verbs change the state with Annotate open or closed, and the annotations show on the photo either way.
* **What it made is selected only while Annotate is open**, as a tap selects it. A drawing never is, as on screen.
* **Each edit is one undo step**, its words included: `add` with a `title` is one step, where the user takes two (the tap, then the typing).
* **A verb of the action bar is there only where the bar offers it.** `addArrow` on a shape, `addText` on a text or `bringToFront` on an annotation nothing covers reject with `NOT_AVAILABLE`. [`read.options()`](#read-options) lists what the bar offers.
* **An `id` the state doesn't have** rejects with `NOT_FOUND`.
* **Words are written, not typed.** No field takes the focus and nothing moves the view, as the user's typing does.

## Open and Close

### open(), close()

Opens Annotate, as a tap on its button: on the tool chosen last, nothing selected. It resolves once Annotate is open; the view then moves to Annotate's room. `close()` closes it, and what was selected lets go.

### setTool()

Chooses the tool a tap or a drag on the photo makes, as Annotate's carousel: `'ARROW'`, `'TEXT'`, `'NUMBER'`, `'RULER'`, `'SHAPE'`, `'DRAW'` or `'LENS'` (the magnifier). What was selected lets go. Its name doesn't show over the photo.

```ts theme={"dark"}
type AnnotateTool = 'ARROW' | 'DRAW' | 'LENS' | 'NUMBER' | 'RULER' | 'SHAPE' | 'TEXT';
```

### select()

Opens Annotate and selects an annotation, the Numbers' list (`id: 'LIST'`), or an arrow added to a text or to the list (`id` and `arrow`), as a tap on it: its handles, its action bar and its style row show. `id: null` lets the selection go, and opens nothing.

```ts select-piece.ts theme={"dark"}
const { id } = await editor.annotate.add({ piece: { type: 'SHAPE', box: { x: 40, y: 40, width: 120, height: 80 } } });

await editor.annotate.select({ id });

const tool = editor.read.tool(); // 'ANNOTATE'
```

## Add and Change

### add()

Adds an annotation, as a tap or a drag of its tool makes one, and resolves to its `id`. `piece` is one of the state's [annotations](https://docs.embededitor.com/api-reference/annotations.md) with no `id`:

* a `LINE` from `from` to `to` (the Arrow's); with `points`, a drawing (Draw's); with `role: 'SHAPE'`, a Shape's Line;
* a `RULER` from `from` to `to`;
* a `TEXT` at `at` (the Text's); with `role: 'NUMBER'`, a Number pinned to `at`;
* a `SHAPE` in `box`;
* a `LENS`, the magnifier, at `at` showing `origin`, `radius` px across from its middle.

What it leaves out takes its tool's last style, the one the next tap would make, and its color the color row's. A text is born as a tap makes it, growing away from the edge it is nearest; its `title` and `body`, and a ruler's `label`, are written into it as the menu's field writes them, trimmed. It rejects with `NOT_AVAILABLE` once the photo holds the most annotations it takes (200).

```ts add.ts theme={"dark"}
const { id } = await editor.annotate.add({ piece: { type: 'TEXT', at: { x: 120, y: 200 }, title: 'Tram 28', look: 'PLAIN' } });

await editor.annotate.add({ piece: { type: 'LINE', from: { x: 40, y: 40 }, to: { x: 110, y: 180 } } });
await editor.annotate.add({ piece: { type: 'LENS', at: { x: 320, y: 80 }, origin: { x: 260, y: 220 }, radius: 50, zoom: 2 } });
```

```ts theme={"dark"}
type AnnotatePiece =
	| Unsaved<Extract<SavedAnnotation, { type: 'LENS' }>>
	| Unsaved<Extract<SavedAnnotation, { type: 'LINE' }>>
	| Unsaved<Extract<SavedAnnotation, { type: 'RULER' }>>
	| Unsaved<Extract<SavedAnnotation, { type: 'SHAPE' }>>
	| Unsaved<Extract<SavedAnnotation, { type: 'TEXT' }>>;
```

### update()

Changes an annotation, the Numbers' list (`id: 'LIST'`), or with `arrow` an arrow added to a text or to the list, as its style row, its color row and its typing do, in one undo step:

* its style, by the style row's names (`AnnotateStyle` below);
* `color`, and `theme`, what sits behind its words (`'LIGHT'`, `'DARK'` or `'ACCENT'`, its color);
* a text's (not a Number's) `mark` (`'NONE'`, `'DOT'` or `'NUMBER'`);
* its words: a text's `title` and `body`, a ruler's `label`;
* its geometry: `from`, `to`, `at`, `box`, `origin`, `radius`, `angle`, `bend`, `width`, written as you give them.

An annotation takes its kind's options (below): a shape has no `font`, a line no `theme`. Anything else rejects with `INVALID_COMMAND`, `props` naming it. The list, and a Number in it, take the list's color, theme, font and size, every Number's with them, as on screen; the list takes nothing else. An added arrow takes no `theme`, and its `color` is its owner's: the list's for the list's own arrow and for a Number in the list, every Number's with it.

```ts update.ts theme={"dark"}
const { id } = await editor.annotate.add({ piece: { type: 'TEXT', at: { x: 120, y: 200 }, title: 'Tram' } });

await editor.annotate.update({ id, title: 'Tram 28, Lisbon', size: 0.05, theme: 'DARK' });
await editor.history.undo(); // back to 'Tram', in one step
```

```ts theme={"dark"}
type AnnotateStyle = {
	color?: string;
	corners?: 'ROUND' | 'SOFT' | 'SQUARE';
	end?: AnnotationCap;
	ends?: 'ARROW' | 'BAR' | 'NONE';
	fill?: number;
	font?: AnnotationFont;
	line?: 'DASHED' | 'DOTTED' | 'MARKER' | 'SKETCH' | 'SOLID' | 'TRANSPARENT';
	look?: 'BOX' | 'CAPTION' | 'PLAIN';
	mark?: 'DOT' | 'NONE' | 'NUMBER';
	padding?: 'LOOSE' | 'NORMAL' | 'TIGHT';
	path?: AnnotationPath;
	shape?: 'CIRCLE' | 'ROUNDED';
	size?: AnnotationSize;
	start?: AnnotationCap;
	stroke?: AnnotationStroke;
	weight?: AnnotationWeight;
	zoom?: number;
};
```

A line takes `start`, `end`, `path` (`'FREE'` only a drawing), `stroke` and `weight`; a ruler `ends`, `size`, `stroke` and `weight`; a text `look`, `corners`, `padding`, `font`, `size` and `mark`; a shape `kind`, `fill`, `stroke` and `weight`; a magnifier `line`, `weight`, `start`, `end`, `path`, `shape` and `zoom`. `Flat` is the type written out as one object.

## The Action Bar's Verbs

Each does what its button does, on the annotation you name, in one undo step.

| Command | The bar's button | On |
| - | - | - |
| `addArrow({ id, to })` | Add Arrow | a text, a Number or the list (`'LIST'`): an arrow to `to`, or, with no `to`, out of the side facing the photo's middle. Resolves to `{ id, arrow }`. |
| `addText({ id, title, body })` | + Text | an arrow, a line, a drawing, a shape or a magnifier: a text born touching it, its words written. Resolves to the text's `{ id }`. |
| `addLeader({ id })` | + Leader | a magnifier on the spot it shows: it moves off it to a free spot, its line showing. |
| `bringToFront({ id })` | Bring to Front | an annotation, or the list, something covers. |
| `detach({ id, arrow })` | Detach | a line with a glued end, or an arrow of a text or of the list with a glued tip: they let go where they are. |
| `duplicate({ id })` | Duplicate | an annotation: a copy a step down and right on the screen, whatever the photo's turn or mirror, with its text. Resolves to the copy's `{ id }`. |
| `remove({ id, arrow })` | Delete | an annotation with what it owns, the list (its Numbers staying), or one arrow of a text or of the list. |

```ts verbs.ts theme={"dark"}
const { id } = await editor.annotate.add({ piece: { type: 'TEXT', at: { x: 120, y: 200 }, title: 'Tram 28' } });
const { arrow } = await editor.annotate.addArrow({ id, to: { x: 300, y: 260 } });

await editor.annotate.remove({ id, arrow }); // the arrow alone
```

## The Next Annotation's Style

`setStyle()` sets the style the next annotation of `tool` is born in (the tool open on Annotate's carousel when you leave it out), as the style row and the color row do with nothing selected. `kind: 'LINE'` makes the Shape's next one a Line. An option that tool's annotation doesn't have rejects with `INVALID_COMMAND`. `setTheme()` sets the theme the next one is born in. Neither changes an annotation already there: [`update()`](#update) does. The colors the color row offers are the palette's, which every color row shares: [`palette.set()`](https://docs.embededitor.com/api-reference/commands/looks#palette) chooses its set.

```ts style.ts theme={"dark"}
await editor.annotate.setStyle({ tool: 'ARROW', end: 'TRIANGLE', weight: 'THICK', color: '#2563eb' });

await editor.annotate.add({ piece: { type: 'LINE', from: { x: 40, y: 40 }, to: { x: 200, y: 120 } } }); // a thick blue arrow
```

## The Numbers' List

`list()` puts the Numbers' words in a list, as In a List on a Number's style row: the list `unlist()` took away last, or a new one, placed off the photo's subject. While Annotate is open, the list is then selected. `unlist()` takes it away, as Beside, each Number's words back by its badge. Each is one undo step; with no Number, or a list there already, nothing changes.

`setListTitle()` writes the list's title, as its own field writes it: trimmed, with no focus, the list holding its top left corner. It is one undo step, and rejects with `NOT_FOUND` when the photo has no list.

The user's own In a List waits for the photo's subject to be read before the list lands. A command doesn't cancel it: called meanwhile, the command runs first, and the user's list lands after it.

```ts list.ts theme={"dark"}
await editor.annotate.add({ piece: { type: 'TEXT', role: 'NUMBER', at: { x: 80, y: 90 }, title: 'Brakes' } });
await editor.annotate.add({ piece: { type: 'TEXT', role: 'NUMBER', at: { x: 300, y: 200 }, title: 'Door' } });
await editor.annotate.list();
await editor.annotate.setListTitle({ title: 'Before the ride' });
```

## read.options()

What Annotate offers `target`, an annotation (`{ id }`), the Numbers' list (`{ id: 'LIST' }`), an arrow added to a text or to the list (with `arrow`) or a tool's next one (`{ tool }`): the commands its action bar offers it (with `annotate.list` or `annotate.unlist` for a Number, `annotate.unlist` for the list), and its style row's and color row's options by `update`'s names (`setStyle`'s for a tool), each with its value now and the `values` it takes, or the `range` a slider takes it in. It answers at once, as every read: `null` until Annotate's screens are loaded (a moment after the image is on screen, or once `annotate.open()` resolves), and for an `id` the state doesn't have.

```ts options.ts theme={"dark"}
const { id } = await editor.annotate.add({ piece: { type: 'TEXT', at: { x: 120, y: 200 }, title: 'Tram 28' } });

await editor.annotate.open();

const offer = editor.read.options({ target: { id } });
// offer.commands: ['annotate.addArrow', 'annotate.duplicate', 'annotate.remove']
// offer.style.size: { value: 0.036, range: { min: 0.02, max: 0.065 } }
```


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