# Image

> Atom — orn-ui

> ⚠️ Requires <UIProvider>: This component (like every orn-ui component) must render inside a <UIProvider> ancestor, or it throws at runtime. See https://orn-ui-docs.vercel.app/getting-started.md

> Runs on Expo SDK 54, 55, 56 and 57, and on bare React Native >=0.81 with react >=19.1. No native modules — works in Expo Go, no prebuild.

## Installation

Install just this component (copies the source into your project, no npm dependency)
```bash
npx orn-ui add image
```

Or install the whole package and import it
```tsx
pnpm add orn-ui
import { Image } from 'orn-ui/image';
```

Depends on: core (theme + icons), spinner

## Variants

### Basic

```tsx
<Image
  source={{ uri: 'https://picsum.photos/200' }}
  width={120}
  height={120}
  radius={12}
/>
```

### Sizes & radius

```tsx
<VariantRow>
  <Image source={{ uri: 'https://picsum.photos/200' }} width={48} height={48} radius={24} />
  <Image source={{ uri: 'https://picsum.photos/200' }} width={72} height={72} radius={12} />
  <Image source={{ uri: 'https://picsum.photos/200' }} width={96} height={96} radius={0} />
</VariantRow>
```

### Custom fallback

```tsx
<Image
  source={{ uri: 'https://example.com/broken.png' }}
  width={120}
  height={120}
  radius={12}
  fallback={<Body style={{ textAlign: 'center', padding: 8 }}>Couldn’t load</Body>}
/>
```

### Above-the-fold (priority="high")

```tsx
<Image
  source={{ uri: 'https://picsum.photos/400' }}
  width={160}
  height={90}
  radius={8}
  priority="high"
/>
```

## Full demo source

```tsx
const variants: VariantDef[] = [
  {
    label: 'Basic',
    content: (
      <Image
        source={{ uri: 'https://picsum.photos/200' }}
        width={120}
        height={120}
        radius={12}
      />
    ),
  },
  {
    label: 'Sizes & radius',
    content: (
      <VariantRow>
        <Image source={{ uri: 'https://picsum.photos/200' }} width={48} height={48} radius={24} />
        <Image source={{ uri: 'https://picsum.photos/200' }} width={72} height={72} radius={12} />
        <Image source={{ uri: 'https://picsum.photos/200' }} width={96} height={96} radius={0} />
      </VariantRow>
    ),
  },
  {
    label: 'Custom fallback',
    content: (
      <Image
        source={{ uri: 'https://example.com/broken.png' }}
        width={120}
        height={120}
        radius={12}
        fallback={<Body style={{ textAlign: 'center', padding: 8 }}>Couldn’t load</Body>}
      />
    ),
  },
  {
    label: 'Above-the-fold (priority="high")',
    content: (
      <Image
        source={{ uri: 'https://picsum.photos/400' }}
        width={160}
        height={90}
        radius={8}
        priority="high"
      />
    ),
  },
];
return <VariantList variants={variants} />;
```

## Props

| Name | Type | Default | Description |
|---|---|---|---|
| `source` | `ImageSourcePropType` | — | — |
| `width?` | `number` | — | — |
| `height?` | `number` | — | — |
| `resizeMode?` | `'cover' \| 'contain' \| 'stretch' \| 'repeat' \| 'center' \| 'none'` | cover | — |
| `radius?` | `number` | 0 | Corner radius, same pattern as Avatar/Card. |
| `loading?` | `ReactNode` | true | What to show while loading. `false` shows nothing. |
| `fallback?` | `ReactNode` | a plain grey placeholder, no content | What to show if loading fails. |
| `priority?` | `'low' \| 'normal' \| 'high'` | normal | 'high' fires Image.prefetch() on mount, before <Image> starts its own loading cycle — meant for the above-the-fold image of a screen (the first one the user sees). Free if it is already cached. |
| `style?` | `StyleProp<ViewStyle>` | — | — |
| `onLoadEnd?` | `() => void` | — | — |
| `onError?` | `(error: NativeSyntheticEvent<ImageErrorEventData>) => void` | — | — |
