# mediaSync

> Why JS: seeking a media element in place and marking what plays need its API.

```ts
import { mediaSync } from "@sdxc/ui/mixins";
```

Makes a player's `a[data-start]` time links seek and play its first `<audio>` or `<video>`,
and marks the playing item of each `marks` list, as installMediaSync does. The player
is the host's closest `root` match; the host is usually a hidden marker in the player's island.

## Signature

```ts
mediaSync(options: MediaSync.MixinOptions): MixinDescriptor<HTMLElement>
```

Returns: A mixin descriptor for an element inside the player.

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `options` | `MediaSync.MixinOptions` | The player's root selector and the lists to mark. |

## Examples

```tsx
<span hidden mix={[mediaSync({ root: '[data-slot="episode"]', marks: ["[data-cue]"] })]} />
```

## Used with it

The events, constants and types its module publishes, each imported from `@sdxc/ui/mixins` too.

### markPlaying

Sets `aria-current="true"` on the last item of a playing-order list whose start is at or
before `time`, and removes it from the rest, writing only what changes.

#### Signature

```ts
markPlaying(items: Iterable<HTMLElement>, time: number): HTMLElement | undefined
```

Returns: The item that newly became current, or `undefined` when no item became current.

#### Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `items` | `Iterable<HTMLElement>` | The list's items in playing order, each with `data-start` or `data-cue`. |
| `time` | `number` | The media's current time in seconds. |

### installMediaSync

Keeps a player's time links and marks in step with its media until `signal` aborts: a
plain click on an `a[data-start]` seeks and plays, a modified click still opens the file,
and every seek and time update marks the item playing in each list.

#### Signature

```ts
installMediaSync(root: HTMLElement, media: HTMLMediaElement, signal: AbortSignal, options: MediaSync.Options): void
```

#### Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| `root` | `HTMLElement` | The player's root, which holds the links and the lists. |
| `media` | `HTMLMediaElement` | The `<audio>` or `<video>` the links seek. |
| `signal` | `AbortSignal` | Ends the listeners when it aborts. |
| `options` | `MediaSync.Options` | The lists to mark, and what to run after each update. |

#### Examples

```tsx
installMediaSync(root, audio, signal, { marks: ['[data-slot="chapters"] a'] });
```

### MediaSync.Options

What one player's sync marks and reports.

#### Members

| Member | Type | Description |
| --- | --- | --- |
| `marks` | `readonly string[]` | Selectors, each matching one playing-order list under the player whose items carry their start in `data-start` or `data-cue`; the item playing carries `aria-current="true"`. |
| `onTime?` | `(time: number, changed: HTMLElement[]) => void` | Runs after every seek and time update, with the items that newly became current. |

### MediaSync.MixinOptions

Configuration accepted by mediaSync.

#### Members

| Member | Type | Description |
| --- | --- | --- |
| `root` | `string` | Selector of the player's root, the closest ancestor of the host that matches. |
