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

# Adjust Commands

> Crop, straighten, zoom and size the photo from code, open Adjust's sections and move the view: the same moves as the Adjust tool's controls.

The `crop`, `size` and `view` groups, Adjust's sections in `menu`, and two reads. They're in every edition: the Free and the Lite are Adjust alone. Each follows [the rules of every command](https://docs.embededitor.com/api-reference/commands/overview.md#how-every-command-behaves).

Each runs the control's own code, with its motion and its undo step. It acts as something from outside: no tool name over the photo, no ruler focus mode.

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

## Values

* **Geometry** is in the px of the state's `crop` (`read.state().crop`): the size the editor works the photo at.
* **Angles** are in degrees. **Scale** is the zoom percent, 100 to 1000, as the state's `crop.scale`.
* **Undo.** Every `crop` and `size` command is one undo step, none when nothing changes. `menu` and `view` commands add none.

## Crop

```ts theme={"dark"}
crop: {
	flip: (input: { axis: 'X' | 'Y' }) => Promise<null>;
	rotate: (input: { direction: 'LEFT' | 'RIGHT' }) => Promise<null>;
	scale: (input: { percent: number }) => Promise<null>;
	set: (input: { height: number; width: number; x: number; y: number }) => Promise<null>;
	setFocus: (input: { focus: 'CENTER' | 'SUBJECT' }) => Promise<null>;
	setRatio: (input: { ratio: '1:1' | '1:2' | '16:9' | '2:1' | '3:4' | '4:3' | '9:16' | 'ORIGINAL' | null }) => Promise<null>;
	straighten: (input: { angle: number }) => Promise<null>;
};
```

### setRatio()

A ratio, as a tap on it in the Aspect section. The crop takes the largest window of that shape, placed where Focus says.

**ratio** `'1:1' | '1:2' | '3:4' | '9:16' | '16:9' | '4:3' | '2:1' | 'ORIGINAL' | null` *required*

The ratio by its name in the Aspect section. `'ORIGINAL'` is the photo's own ratio, as the photo is turned. `null` frees it and keeps the window as it is, as Free does.

The ratio in effect changes nothing. While the host locks the ratio (`aspectRatioLocked`), it rejects with `NOT_AVAILABLE`.

### set()

The crop's window, as the person's crop.

**x, y, width, height** `number` *required*

The window, in the px of the state's `crop`. One past the photo's edge moves in. One larger than the photo shrinks at its ratio.

A ratio in effect stays for a window of that ratio and goes for any other. Under a locked ratio, a window off it rejects with `NOT_AVAILABLE`.

### setFocus()

Where the window goes, as Focus's menu on the crop pill.

**focus** `'SUBJECT' | 'CENTER'` *required*

The photo's subject, or its middle. The window of the ratio in effect goes there now, and every ratio chosen next follows it. On a photo whose subject can't be read, `'SUBJECT'` keeps the choice but moves no window, and the editor's notice says Focus couldn't read the photo; the command still resolves.

### scale()

The zoom, as the Scale slider. The crop zooms round its middle.

**percent** `number` *required*

100 to 1000. 100 is the photo's largest window of the crop's ratio. A straightened photo can't go as wide: under its least, the least.

### straighten()

The angle Adjust's ruler shows. The photo turns under the window.

**angle** `number` *required*

−45 to 45 degrees. The state's `rotation` holds the quarter turns and this angle together.

### rotate()

A quarter turn, as the crop pill's Rotate.

**direction** `'LEFT' | 'RIGHT'` *required*

`'LEFT'` is counterclockwise, the button's way. The whole photo turns with its window; any other window stays where it is on the screen.

### flip()

A mirror, as the crop pill's Flip.

**axis** `'X' | 'Y'` *required*

`'X'` mirrors left to right, the button's way. `'Y'` mirrors top to bottom.

```ts crop.ts theme={"dark"}
await editor.crop.setRatio({ ratio: '16:9' });
await editor.crop.setRatio({ ratio: 'ORIGINAL' }); // the photo's own ratio
await editor.crop.setRatio({ ratio: null }); // free again, the window as it is
await editor.crop.set({ x: 100, y: 50, width: 200, height: 150 });
await editor.crop.setFocus({ focus: 'CENTER' });
await editor.crop.scale({ percent: 200 });
await editor.crop.straighten({ angle: 2.5 });
await editor.crop.rotate({ direction: 'LEFT' });
await editor.crop.flip({ axis: 'X' });
```

## Size

```ts theme={"dark"}
size: {
	set: (input: { side: 'HEIGHT' | 'WIDTH'; value: number }) => Promise<null>;
};
```

### set()

The size Save writes, as Resize's fields.

**side** `'WIDTH' | 'HEIGHT'` *required*

The side to set. The other follows the crop's ratio.

**value** `number` *required*

Its length, in whole px. Both sides are held to `maxWidth` and `maxHeight`, and the output never passes 16.7 MP.

**Full edition.** Where Resize is off (`enableResize: false`, the Free, the Lite) it rejects with `NOT_AVAILABLE`.

```ts size.ts theme={"dark"}
await editor.size.set({ side: 'WIDTH', value: 1200 });
await editor.size.set({ side: 'HEIGHT', value: 800 });
```

## Adjust's Sections

Two commands of `menu`. Scale's slider and Aspect's ratios open over the menu's carousel, as the crop pill's buttons open them.

```ts theme={"dark"}
closeSection: () => Promise<null>;
openSection: (input: { section: 'ASPECT' | 'SCALE' }) => Promise<null>;
```

### openSection()

**section** `'SCALE' | 'ASPECT'` *required*

The section to open. The menu goes to Adjust first when another item shows. The section already open stays as it is.

`ASPECT` rejects with `NOT_AVAILABLE` while the host locks the ratio. Both reject while Annotate is open.

### closeSection()

Goes back to the carousel, as Done does. A ratio the Aspect section still waits on lands first.

```ts sections.ts theme={"dark"}
await editor.menu.openSection({ section: 'ASPECT' });

const opened = editor.read.section(); // 'ASPECT'

await editor.menu.closeSection();
```

## View

The view moves the photo on the screen, never the edit.

```ts theme={"dark"}
view: {
	compare: (input: { on: boolean }) => Promise<null>;
	pan: (input: { x: number; y: number }) => Promise<null>;
	recenter: () => Promise<null>;
	settled: () => Promise<null>;
	zoom: (input: { at?: { x: number; y: number }; factor: number }) => Promise<null>;
};
```

| Command | What it does |
| - | - |
| `view.compare({ on })` | Shows the original while `on`, as holding a press on the photo does. |
| `view.recenter()` | Springs the view back to its rest, the photo whole, as Annotate's zoom chip does. |
| `view.settled()` | Resolves once the view's motion rests: a refit after a crop, a command's zoom or pan. Wait on it before a screenshot. |
| `view.zoom({ factor, at })` | **Annotate only.** Zooms by `factor` round `at`, a point of the photo in its px (the view's middle when left out). Held between the photo whole and 8×, as the wheel holds it. |
| `view.pan({ x, y })` | **Annotate only.** Moves a zoomed view by `x`, `y` px of the photo, as a scroll: positive values show more of the right and the bottom. |

```ts view.ts theme={"dark"}
await editor.view.compare({ on: true });
await editor.view.compare({ on: false });
await editor.view.recenter();
```

Each starts from where the view rests: a zoom still gliding lands first. Out of Annotate, `view.zoom` and `view.pan` reject with `NOT_AVAILABLE`: the zoom there is the crop's, `crop.scale`.

```ts annotate-view.ts theme={"dark"}
// with Annotate open
await editor.view.zoom({ factor: 2, at: { x: 200, y: 150 } });
await editor.view.pan({ x: 50, y: 0 });
await editor.view.settled();
```

> [!NOTE]
>
> `view.settled()`, `view.zoom` and `view.pan` wait on the view's motion, which runs with the page's frames: in a hidden tab they wait until the tab shows. The person's wheel in Annotate moves the view by steps, so `view.settled()` doesn't wait for it.

## Reads

Two reads of `read`. They answer at once, `null` until the photo is on screen.

```ts theme={"dark"}
outputSize: () => Size | null;

section: () => 'ASPECT' | 'MAIN' | 'SCALE' | null;
```

| Read | What it gives |
| - | - |
| `read.section()` | The menu's section: `'MAIN'` (the carousel), `'SCALE'` or `'ASPECT'`. |
| `read.outputSize()` | The size Save writes now, as the size badge says. |

```ts reads.ts theme={"dark"}
const section = editor.read.section(); // 'MAIN', 'SCALE' or 'ASPECT'
const output = editor.read.outputSize(); // { width, height }
```

Every command runs by its name too, with the same object, through [`run`](https://docs.embededitor.com/api-reference/commands/for-ai): `editor.run({ command: 'crop.setRatio', input: { ratio: '16:9' } })`.


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