# Media player

Audio and video in one phone-first player. Demo: `/media-player`
(https://components.hybriel.worldapi.org/media-player).

Pure Hybriel: one file, `media-player.hl`, with its own `Style`; no JavaScript file. The
browser's own media element plays — this component draws the controls around it, sized
for a thumb (every button at least 44 px, play / pause larger).

## Use it in an app

Copy `components/media-player/media-player.hl` (and `components/icons/icons.hl` if you
do not have it — the player's icons come from there), then:

```
import MediaPlayer from './media-player.hl'

Hybrid queue = [
	{ src = '/media/song.mp3'  title = 'Song'  dur = '3:41' }
	{ src = '/media/clip.mp4'  title = 'Clip'  dur = '0:30' }
]
String current = '/media/song.mp3'
picked = (src) => { current = src }

View {
	MediaPlayer { src = current  kind = "audio"  title = "Song"  artist = "Someone"
		cover = "/media/cover.png"  queue = queue  onPlay = picked }
}
```

## Attributes

| Attribute | Meaning |
|---|---|
| `src` | the address of the media file (the host owns it) |
| `kind` | `"video"` (default) or `"audio"`: audio shows a cover instead of the video area |
| `title` | the heading of the cover (audio); the video element's accessible name |
| `artist` | the second line of the cover (audio) |
| `cover` | the cover image of an audio item (optional) |
| `queue` | the host's list: `[{ src, title, dur }]` — rendered under the player; the row whose `src` plays is marked with the accent colour only |
| `onPlay` | a function the host hands in; a tap on a queue item (and the end of one) calls it with that item's `src` (the host then hands a new `src` back — the player is built anew with it) |
| `skip` | `true` (default) shows the back / forward buttons; `false` leaves both out of the View. Keyboard seeking stays available. |
| `repeat` | `"off"` (default) advances through the host queue; `"one"` replays the current item from zero without calling `onPlay` or replacing its source. |
| `jump` | the seek jump of the back / forward buttons, in seconds (default 10) |

Write every attribute as a **literal** (`kind = "audio"`): then several players stand on
one page, each with its own values. (A composed component's members are the page's state.)
Use one per page: the player's own state (the time, the speed) is the page's state too.

## Controls

- A **seek bar** you drag with a finger (pointer events, the whole strip is 44 px tall):
  the played part in the accent colour, the buffered part lighter, the thumb a dot. It
  takes the keyboard too (arrows, Home, End) when it has the focus.
- **Back 10 s**, **play / pause** (the largest button), **forward 10 s**, the **current
  time / total time**, **mute**, the **speed** (1 / 1.25 / 1.5 / 2, one button that steps
  through them), and **fullscreen** on video.
- Keyboard on the media element (a click on the video gives it the focus): Space plays /
  pauses, ArrowLeft / ArrowRight jump 10 s.

## Behaviour

- The video area is 16:9, letterboxed (`object-fit: contain`); audio shows the cover with
  the title and artist.
- The queue under the player is dense: 44 px tap rows that look thin (the visible rows
  hug their text, the touch area is the padding).
- When an item ends, the next queue item's `src` goes to the host the same way a tap does.
- Colours are the semantic tokens with a black/white/grey fallback (the base look), so a
  bare copy looks right and an app that declares the WorldAPI tokens (layouts.worldapi.org's
  theme) restyles it. No frames; the current queue item is the accent colour on a surface.

## Not yet

No captions track UI (a `<track>` can be handed to the media element by the host's own
markup inside the component's slot is not offered yet); no volume slider (mute only);
no picture-in-picture button (the browser's own menu on the video still has it).

## Player options

Use `MediaPlayer { src = current  skip = false  repeat = "one" }` to leave out
the two ten-second buttons and repeat the current song. Both options can change
while the player is mounted. Repeat one uses the media element’s native `loop`
attribute; it does not reload the source or call the host at each end. The `/media-player` demo has one toggle for each.
Shuffle, Previous/Next and repeat-all controls belong to the host app.
