# FAQ

> [llms.txt](https://zriz.dev/llms.txt)

Short answers, each with a link to the page that covers it in full.

## Setup

### What does zriz need

React 18.2 or newer, 19 included, from one build. Both packages ship types, and `@types/react` 18.2.6 or newer is an optional peer. [Quick start](https://zriz.dev/docs/quick-start.md) has the install.

### Which browsers does it run in

Chrome, Edge and Firefox in their latest two versions, Safari and iOS Safari 18 and newer, and Chrome and Samsung Internet on Android. A two-finger trackpad twist rotates only in Safari. On a trackpad in other browsers, rotate with the dial and the keys. Two fingers on a touch screen rotate in every browser.

### Does it work without a bundler

Yes, with an import map. Map `react`, `react/jsx-runtime`, `@zriz/react`, `@zriz/react/cropper`, `@zriz/core` and `@zriz/core/dom`. The parts also import `@zriz/react/warn`, so point that at `@zriz/react/dist/warn-off.js`.

To keep the warnings during development, point it at `dist/warn.js` and run `window.process = { env: {} }` before the modules load. Without a `process` global, `dist/warn.js` stays silent too.

### Does it work with the Next.js app router

Yes. Every part is a client component, so a server component can render them. Callbacks such as `onValueCommit` are functions, so put them in a client file of your own.

### Does it render on the server

Yes. The server renders the parts with no photo, and the photo loads in the browser after hydration.

### Does it work with Vue or Svelte

There are no Vue or Svelte parts. `@zriz/core/dom` binds a cropper to plain elements, so any framework can drive it. [Vanilla JS](https://zriz.dev/docs/vanilla-js.md) shows the setup.

### Can I use my own button component

Yes. Pass it to `render` on any part, and zriz merges its props and ref into yours. [Composition](https://zriz.dev/docs/composition.md) has the code.

### Why is my viewport empty

`Viewport` has no height of its own, so it starts at zero height. Give it a height, as in [viewport](https://zriz.dev/docs/viewport.md).

### Can I test it with jsdom

jsdom has no `ResizeObserver`, so `Viewport`, `Image` and `DialTicks` throw when they mount. Stub it in your test setup. To test crop logic with no DOM at all, use `createCropper` with a manual clock, as [cropper](https://zriz.dev/docs/cropper.md) shows.

```ts
globalThis.ResizeObserver ??= class {
  observe() {}
  unobserve() {}
  disconnect() {}
};
```

### Why do Node and Jest fail on the stylesheet

Node cannot import a `.css` file, and Jest cannot either until you map it. Point `\.css$` at an empty module with `moduleNameMapper` in your Jest config. Vitest and Bun load the import as it is, and in an app your bundler handles it.

## Photos and export

### Can it open HEIC photos from an iPhone

Safari decodes HEIC, so iPhone photos open there. In other browsers the load fails with `unsupported-format`. To open them everywhere, call `loadImage` yourself with a HEIC decoder as `decode`, as [loading images](https://zriz.dev/docs/loading-images.md) shows.

### How do I get the cropped file

Call `exportCrop` from `@zriz/core/dom` with the cropper from `actionsRef`. It resolves with an object that holds the file in `blob`, next to its `width` and `height`. [Exporting](https://zriz.dev/docs/exporting.md) has the code.

### Can I put it in a dialog or a drawer

Yes. A native `<dialog>` does not lock the page, so a wheel at the pan limit or over the dial scrolls what is behind it. `html:has(dialog[open]) { overflow: hidden; }` holds the page. Keep `Announcer` inside the dialog, see [accessibility](https://zriz.dev/docs/accessibility.md).

Radix `forceMount` with CSS hiding keeps `aria-hidden` on your app and the scroll lock while closed, so mount the dialog only when it is open. Base UI `keepMounted` leaves the page clean.

Vaul starts with focus on the page, and the first presses of tab land behind the drawer. Pass `autoFocus` to `Drawer.Root`. [Viewport](https://zriz.dev/docs/viewport.md) and [root](https://zriz.dev/docs/root.md) have the layout and swipe notes.

### Can I crop on the server

Yes. Send the original file and the value from `getValue()`, recompute the plan on the server, then turn that plan into sharp calls with `toSharp`. [Server crop](https://zriz.dev/docs/server-crop.md) has the route.
