<!-- AUTO-GENERATED by scripts/generate-docs.mjs — do not edit; edit docs/llm/reference/_fragments/<name>.md and run `pnpm docs:generate`. -->

# Media

Use when you show images or people.

## Index

- [`avatar`](#avatar) — Image with initials fallback and optional status dot
- [`avatar-group`](#avatar-group) — Overlapping avatar stack with +N overflow
- [`gallery`](#gallery) — Image lightbox with navigation and keyboard control
- [`image-viewer`](#image-viewer) — Zoomable, pannable image with zoom controls

---

## avatar

Image with automatic fallback to initials + optional status dot.

```html
<div data-c42-avatar>
  <img data-c42-avatar-image src="…" alt="Jane Doe" />
  <span data-c42-avatar-fallback></span>
  <span data-c42-avatar-status></span>
</div>
```

```ts
import { Avatar } from '@42/core/avatar';
new Avatar(root, { name: 'Jane Doe', status: 'online' });
```

Options: `name` (derives initials), `status` ('online'|'offline'|'busy'|'away'|null)
Methods: `setStatus(s)`, `setSrc(url)`
Events: `avatar:load`, `avatar:error`, `avatar:statuschange` → `{ status }`

---

## avatar-group

Overlapping stack of avatars with optional `+N` overflow collapsing. Headless: the
controller reflects `data-stacked` / `data-spacing` and caps visible avatars; the
overlap visuals live in CSS.

```html
<div data-c42-avatar-group>
  <div data-c42-avatar>…</div>
  <div data-c42-avatar>…</div>
  <div data-c42-avatar>…</div>
  <span data-c42-avatar-overflow></span>
</div>
```

```ts
import { AvatarGroup } from '@42/core/avatar-group';
const group = new AvatarGroup(root, { stacked: true, spacing: 'md', max: 4, label: 'Members' });
group.setMax(2);
```

Options: `stacked` (default true), `spacing` ('sm'|'md'|'lg', default 'md'), `max` (0 = no limit), `label` (aria-label)
Methods: `setStacked(boolean)`, `setSpacing('sm'|'md'|'lg')`, `setMax(number)`, `refresh()`
Events: `avatar-group:change` → `{ total, visible, overflow }`

---

## gallery

Image lightbox with navigation, loop, keyboard, scroll lock.

```html
<div data-c42-gallery>
  <img data-c42-gallery-thumb src="thumb1.jpg" data-full="full1.jpg" />
  <img data-c42-gallery-thumb src="thumb2.jpg" data-full="full2.jpg" />
  <div data-c42-gallery-lightbox>
    <img data-c42-gallery-image />
    <button data-c42-gallery-prev>‹</button>
    <button data-c42-gallery-next>›</button>
    <button data-c42-gallery-close>×</button>
  </div>
</div>
```

```ts
import { Gallery } from '@42/core/gallery';
new Gallery(root, { loop: true, closeOnEscape: true, lockScroll: true });
```

Options: `loop`, `closeOnEscape`, `lockScroll`
Events: `gallery:open`, `gallery:close`, `gallery:change` → `{ index, src }`

---

## image-viewer

Zoomable image with pan, expand/collapse, zoom controls.

```html
<div data-c42-image-viewer>
  <img data-c42-viewer-image src="photo.jpg" />
  <button data-c42-viewer-zoom-in>+</button>
  <button data-c42-viewer-zoom-out>−</button>
  <button data-c42-viewer-expand>⛶</button>
</div>
```

```ts
import { ImageViewer } from '@42/core/image-viewer';
new ImageViewer(root, { minZoom: 0, maxZoom: 7, expanded: false });
```

Options: `minZoom`, `maxZoom`, `expanded`
Events: `image-viewer:zoom` → `{ zoom, scale, expanded }`
