# Images — `@sonordev/site-kit/images`

Sonor-managed image slots with dev-mode editing, focal point support, and image picker.

## Usage

```tsx
import { ManagedImage } from '@sonordev/site-kit/images'

export default function HeroSection() {
  return (
    <ManagedImage
      slotId="hero-background"
      alt="Hero background"
      width={1920}
      height={1080}
      objectFit="cover"
      fallback="/images/default-hero.jpg"
    />
  )
}
```

## Props

```ts
interface ManagedImageProps {
  slotId: string                     // Unique slot identifier (e.g., 'hero-background')
  pagePath?: string                  // Page-specific slots (defaults to current path)
  alt?: string                       // Fallback alt text
  className?: string
  width?: number | string
  height?: number | string
  objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'
  fallback?: string                  // Fallback image URL when slot is empty
  placeholder?: React.ReactNode     // Custom placeholder component
  onLoad?: () => void
  onError?: (error: Error) => void
  priority?: boolean                 // Eager loading (Next.js Image priority)
  style?: React.CSSProperties
  forceDevMode?: boolean             // Enable dev picker outside localhost
}
```

## Dev Mode

Dev mode is on when `NODE_ENV` is `development`, on `localhost` / `127.0.0.1`, on any host with `?sonor_dev=true` in the URL, or with `forceDevMode`:

- Click any `ManagedImage` to open the image picker modal
- Browse files by folder, search, upload new images
- Set alt text and focal point
- Shows slot ID in empty states for debugging

## Focal Point

When an image has `focal_point_x` / `focal_point_y` set in Sonor, the component auto-calculates `object-position` so the focal area stays visible during cropping.

## API Functions

```ts
import { fetchManagedImage, uploadImage, assignImageToSlot } from '@sonordev/site-kit/images'

const image = await fetchManagedImage(slotId, pagePath)
const uploaded = await uploadImage(file, { folder: 'heroes', category: 'background' })
await assignImageToSlot(slotId, uploaded.id, pagePath)
```

## Favicon

```tsx
import { ManagedFavicon } from '@sonordev/site-kit/images'

// In layout <head>:
<ManagedFavicon />  // Fetches Sonor logo as favicon link tags
```
