@mango-iiif/av 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/dist/annotations.d.ts +12 -0
  4. package/dist/annotations.js +15 -0
  5. package/dist/annotations.js.map +1 -0
  6. package/dist/chapters.d.ts +12 -0
  7. package/dist/chapters.js +14 -0
  8. package/dist/chapters.js.map +1 -0
  9. package/dist/chunk-3LLEY7MA.js +126 -0
  10. package/dist/chunk-3LLEY7MA.js.map +1 -0
  11. package/dist/chunk-CDLYT3KB.js +17 -0
  12. package/dist/chunk-CDLYT3KB.js.map +1 -0
  13. package/dist/chunk-GAVG7CPU.js +1 -0
  14. package/dist/chunk-GAVG7CPU.js.map +1 -0
  15. package/dist/chunk-GX7UU6V4.js +547 -0
  16. package/dist/chunk-GX7UU6V4.js.map +1 -0
  17. package/dist/chunk-IFTSCRCU.js +83 -0
  18. package/dist/chunk-IFTSCRCU.js.map +1 -0
  19. package/dist/chunk-JXUHKKIX.js +94 -0
  20. package/dist/chunk-JXUHKKIX.js.map +1 -0
  21. package/dist/chunk-ML77YRJL.js +221 -0
  22. package/dist/chunk-ML77YRJL.js.map +1 -0
  23. package/dist/chunk-NTHMZZYJ.js +38 -0
  24. package/dist/chunk-NTHMZZYJ.js.map +1 -0
  25. package/dist/chunk-PZ6GV6ZJ.js +163 -0
  26. package/dist/chunk-PZ6GV6ZJ.js.map +1 -0
  27. package/dist/chunk-R4OUWZ3R.js +1038 -0
  28. package/dist/chunk-R4OUWZ3R.js.map +1 -0
  29. package/dist/chunk-YH6DS7J6.js +74 -0
  30. package/dist/chunk-YH6DS7J6.js.map +1 -0
  31. package/dist/controller-DLy38ais.d.ts +356 -0
  32. package/dist/controller-element-BOKM9v2S.d.ts +15 -0
  33. package/dist/core.d.ts +28 -0
  34. package/dist/core.js +28 -0
  35. package/dist/core.js.map +1 -0
  36. package/dist/index.d.ts +25 -0
  37. package/dist/index.js +70 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/media.d.ts +28 -0
  40. package/dist/media.js +16 -0
  41. package/dist/media.js.map +1 -0
  42. package/dist/player.d.ts +27 -0
  43. package/dist/player.js +15 -0
  44. package/dist/player.js.map +1 -0
  45. package/dist/transcript-element.d.ts +12 -0
  46. package/dist/transcript-element.js +16 -0
  47. package/dist/transcript-element.js.map +1 -0
  48. package/docs/API.md +264 -0
  49. package/docs/FEATURE_PARITY.md +43 -0
  50. package/package.json +94 -0
@@ -0,0 +1,15 @@
1
+ import { h as AVPlayerController, i as AVPlayerEventMap } from './controller-DLy38ais.js';
2
+
3
+ declare const HTMLElementBase: typeof HTMLElement;
4
+ declare abstract class AVControllerElement extends HTMLElementBase {
5
+ #private;
6
+ get controller(): AVPlayerController;
7
+ set controller(value: AVPlayerController);
8
+ connectedCallback(): void;
9
+ disconnectedCallback(): void;
10
+ protected get controllerEvents(): Array<keyof AVPlayerEventMap>;
11
+ protected abstract controllerChanged(): void;
12
+ protected abstract handleControllerEvent<K extends keyof AVPlayerEventMap>(type: K, event: CustomEvent<AVPlayerEventMap[K]>): void;
13
+ }
14
+
15
+ export { AVControllerElement as A };
package/dist/core.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { l as AVStrings, J as JsonObject, e as AVManifest, u as TranscriptResource, s as TranscriptCue, r as TimeSpan } from './controller-DLy38ais.js';
2
+ export { A as AVAnnotation, a as AVAnnotationAdapter, b as AVAnnotationDraft, c as AVCanvas, d as AVControlsConfig, f as AVPanelsConfig, g as AVPlayerConfig, h as AVPlayerController, i as AVPlayerEventMap, j as AVPlayerState, k as AVResumeConfig, m as AVTranscriptConfig, n as AuthService, C as Chapter, D as DownloadResource, I as IIIFPresentationVersion, L as LocalizedValue, M as MediaKind, o as MediaSource, p as MetadataEntry, T as TextTrack, q as TextTrackKind, t as TranscriptCueType, v as defaultConfig, w as defaultStrings } from './controller-DLy38ais.js';
3
+
4
+ interface NormalizeOptions {
5
+ fetch?: typeof globalThis.fetch;
6
+ requestInit?: RequestInit;
7
+ preferredLanguages?: string[];
8
+ loadExternalAnnotations?: boolean;
9
+ strings?: Partial<AVStrings>;
10
+ }
11
+ declare const normalizeManifest: (input: JsonObject | string, options?: NormalizeOptions) => Promise<AVManifest>;
12
+
13
+ interface TranscriptParseOptions {
14
+ showNotes?: boolean;
15
+ showMetadata?: boolean;
16
+ }
17
+ declare const parseTimedText: (input: string, format: "vtt" | "srt", options?: TranscriptParseOptions) => TranscriptCue[];
18
+ declare const parseTranscript: (input: string | unknown, format: string, options?: TranscriptParseOptions) => TranscriptCue[];
19
+ declare const loadTranscript: (resource: TranscriptResource, options?: TranscriptParseOptions & {
20
+ fetch?: typeof globalThis.fetch;
21
+ requestInit?: RequestInit;
22
+ }) => Promise<TranscriptCue[]>;
23
+
24
+ declare const parseTime: (value: string | number | undefined) => number | undefined;
25
+ declare const parseTemporalFragment: (target: unknown) => TimeSpan | undefined;
26
+ declare const formatTime: (seconds: number) => string;
27
+
28
+ export { AVManifest, AVStrings, JsonObject, type NormalizeOptions, TimeSpan, TranscriptCue, TranscriptResource, formatTime, loadTranscript, normalizeManifest, parseTemporalFragment, parseTime, parseTimedText, parseTranscript };
package/dist/core.js ADDED
@@ -0,0 +1,28 @@
1
+ import "./chunk-GAVG7CPU.js";
2
+ import {
3
+ loadTranscript,
4
+ parseTimedText,
5
+ parseTranscript
6
+ } from "./chunk-3LLEY7MA.js";
7
+ import {
8
+ AVPlayerController,
9
+ defaultConfig,
10
+ defaultStrings,
11
+ formatTime,
12
+ normalizeManifest,
13
+ parseTemporalFragment,
14
+ parseTime
15
+ } from "./chunk-R4OUWZ3R.js";
16
+ export {
17
+ AVPlayerController,
18
+ defaultConfig,
19
+ defaultStrings,
20
+ formatTime,
21
+ loadTranscript,
22
+ normalizeManifest,
23
+ parseTemporalFragment,
24
+ parseTime,
25
+ parseTimedText,
26
+ parseTranscript
27
+ };
28
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,25 @@
1
+ import { MangoAVAnnotationsElement } from './annotations.js';
2
+ export { defineMangoAVAnnotations } from './annotations.js';
3
+ import { MangoAVTranscriptElement } from './transcript-element.js';
4
+ export { defineMangoAVTranscript } from './transcript-element.js';
5
+ import { MangoAVChaptersElement } from './chapters.js';
6
+ export { defineMangoAVChapters } from './chapters.js';
7
+ import { MangoAVPlayerElement } from './player.js';
8
+ export { defineMangoAVPlayer } from './player.js';
9
+ import { MangoAVMediaElement } from './media.js';
10
+ export { defineMangoAVMedia } from './media.js';
11
+ export { A as AVAnnotation, a as AVAnnotationAdapter, b as AVAnnotationDraft, c as AVCanvas, d as AVControlsConfig, e as AVManifest, f as AVPanelsConfig, g as AVPlayerConfig, h as AVPlayerController, i as AVPlayerEventMap, j as AVPlayerState, k as AVResumeConfig, l as AVStrings, m as AVTranscriptConfig, n as AuthService, C as Chapter, D as DownloadResource, I as IIIFPresentationVersion, J as JsonObject, L as LocalizedValue, M as MediaKind, o as MediaSource, p as MetadataEntry, T as TextTrack, q as TextTrackKind, r as TimeSpan, s as TranscriptCue, t as TranscriptCueType, u as TranscriptResource, v as defaultConfig, w as defaultStrings } from './controller-DLy38ais.js';
12
+ export { NormalizeOptions, formatTime, loadTranscript, normalizeManifest, parseTemporalFragment, parseTime, parseTimedText, parseTranscript } from './core.js';
13
+ import './controller-element-BOKM9v2S.js';
14
+
15
+ declare global {
16
+ interface HTMLElementTagNameMap {
17
+ 'mango-av-media': MangoAVMediaElement;
18
+ 'mango-av-player': MangoAVPlayerElement;
19
+ 'mango-av-chapters': MangoAVChaptersElement;
20
+ 'mango-av-transcript': MangoAVTranscriptElement;
21
+ 'mango-av-annotations': MangoAVAnnotationsElement;
22
+ }
23
+ }
24
+
25
+ export { MangoAVAnnotationsElement, MangoAVChaptersElement, MangoAVMediaElement, MangoAVPlayerElement, MangoAVTranscriptElement };
package/dist/index.js ADDED
@@ -0,0 +1,70 @@
1
+ import {
2
+ MangoAVAnnotationsElement,
3
+ defineMangoAVAnnotations
4
+ } from "./chunk-IFTSCRCU.js";
5
+ import {
6
+ MangoAVChaptersElement,
7
+ defineMangoAVChapters
8
+ } from "./chunk-YH6DS7J6.js";
9
+ import "./chunk-GAVG7CPU.js";
10
+ import {
11
+ MangoAVMediaElement,
12
+ defineMangoAVMedia
13
+ } from "./chunk-GX7UU6V4.js";
14
+ import {
15
+ MangoAVPlayerElement,
16
+ defineMangoAVPlayer
17
+ } from "./chunk-ML77YRJL.js";
18
+ import "./chunk-NTHMZZYJ.js";
19
+ import {
20
+ MangoAVTranscriptElement,
21
+ defineMangoAVTranscript
22
+ } from "./chunk-PZ6GV6ZJ.js";
23
+ import "./chunk-CDLYT3KB.js";
24
+ import {
25
+ loadTranscript,
26
+ parseTimedText,
27
+ parseTranscript
28
+ } from "./chunk-3LLEY7MA.js";
29
+ import "./chunk-JXUHKKIX.js";
30
+ import {
31
+ AVPlayerController,
32
+ defaultConfig,
33
+ defaultStrings,
34
+ formatTime,
35
+ normalizeManifest,
36
+ parseTemporalFragment,
37
+ parseTime
38
+ } from "./chunk-R4OUWZ3R.js";
39
+
40
+ // src/index.ts
41
+ if (typeof window !== "undefined" && "customElements" in window) {
42
+ defineMangoAVMedia();
43
+ defineMangoAVPlayer();
44
+ defineMangoAVChapters();
45
+ defineMangoAVTranscript();
46
+ defineMangoAVAnnotations();
47
+ }
48
+ export {
49
+ AVPlayerController,
50
+ MangoAVAnnotationsElement,
51
+ MangoAVChaptersElement,
52
+ MangoAVMediaElement,
53
+ MangoAVPlayerElement,
54
+ MangoAVTranscriptElement,
55
+ defaultConfig,
56
+ defaultStrings,
57
+ defineMangoAVAnnotations,
58
+ defineMangoAVChapters,
59
+ defineMangoAVMedia,
60
+ defineMangoAVPlayer,
61
+ defineMangoAVTranscript,
62
+ formatTime,
63
+ loadTranscript,
64
+ normalizeManifest,
65
+ parseTemporalFragment,
66
+ parseTime,
67
+ parseTimedText,
68
+ parseTranscript
69
+ };
70
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export * from './core';\nexport { defineMangoAVMedia, MangoAVMediaElement } from './components/mango-av-media';\nexport { defineMangoAVPlayer, MangoAVPlayerElement } from './components/mango-av-player';\nexport { defineMangoAVChapters, MangoAVChaptersElement } from './components/mango-av-chapters';\nexport { defineMangoAVTranscript, MangoAVTranscriptElement } from './components/mango-av-transcript';\nexport { defineMangoAVAnnotations, MangoAVAnnotationsElement } from './components/mango-av-annotations';\n\nimport { defineMangoAVMedia } from './components/mango-av-media';\nimport { defineMangoAVPlayer } from './components/mango-av-player';\nimport { defineMangoAVChapters } from './components/mango-av-chapters';\nimport { defineMangoAVTranscript } from './components/mango-av-transcript';\nimport { defineMangoAVAnnotations } from './components/mango-av-annotations';\n\nif (typeof window !== 'undefined' && 'customElements' in window) {\n defineMangoAVMedia();\n defineMangoAVPlayer();\n defineMangoAVChapters();\n defineMangoAVTranscript();\n defineMangoAVAnnotations();\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'mango-av-media': import('./components/mango-av-media').MangoAVMediaElement;\n 'mango-av-player': import('./components/mango-av-player').MangoAVPlayerElement;\n 'mango-av-chapters': import('./components/mango-av-chapters').MangoAVChaptersElement;\n 'mango-av-transcript': import('./components/mango-av-transcript').MangoAVTranscriptElement;\n 'mango-av-annotations': import('./components/mango-av-annotations').MangoAVAnnotationsElement;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,IAAI,OAAO,WAAW,eAAe,oBAAoB,QAAQ;AAC/D,qBAAmB;AACnB,sBAAoB;AACpB,wBAAsB;AACtB,0BAAwB;AACxB,2BAAyB;AAC3B;","names":[]}
@@ -0,0 +1,28 @@
1
+ import { h as AVPlayerController, J as JsonObject, g as AVPlayerConfig, e as AVManifest, c as AVCanvas } from './controller-DLy38ais.js';
2
+
3
+ declare const HTMLElementBase: typeof HTMLElement;
4
+ declare class MangoAVMediaElement extends HTMLElementBase {
5
+ #private;
6
+ static observedAttributes: string[];
7
+ readonly player: AVPlayerController;
8
+ constructor();
9
+ get manifest(): JsonObject | string | undefined;
10
+ get controller(): AVPlayerController;
11
+ set manifest(value: JsonObject | string | undefined);
12
+ get config(): AVPlayerConfig;
13
+ set config(value: AVPlayerConfig);
14
+ connectedCallback(): void;
15
+ disconnectedCallback(): void;
16
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
17
+ load(input: JsonObject | string): Promise<AVManifest>;
18
+ play(): Promise<void>;
19
+ pause(): void;
20
+ seekTo(time: number): void;
21
+ selectCanvas(indexOrId: number | string, options?: {
22
+ time?: number;
23
+ autoplay?: boolean;
24
+ }): AVCanvas | undefined;
25
+ }
26
+ declare const defineMangoAVMedia: (tagName?: string) => typeof MangoAVMediaElement;
27
+
28
+ export { MangoAVMediaElement, defineMangoAVMedia };
package/dist/media.js ADDED
@@ -0,0 +1,16 @@
1
+ import {
2
+ MangoAVMediaElement,
3
+ defineMangoAVMedia
4
+ } from "./chunk-GX7UU6V4.js";
5
+ import "./chunk-NTHMZZYJ.js";
6
+ import "./chunk-CDLYT3KB.js";
7
+ import "./chunk-3LLEY7MA.js";
8
+ import "./chunk-R4OUWZ3R.js";
9
+
10
+ // src/media.ts
11
+ if (typeof window !== "undefined" && "customElements" in window) defineMangoAVMedia();
12
+ export {
13
+ MangoAVMediaElement,
14
+ defineMangoAVMedia
15
+ };
16
+ //# sourceMappingURL=media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/media.ts"],"sourcesContent":["export { defineMangoAVMedia, MangoAVMediaElement } from './components/mango-av-media';\n\nimport { defineMangoAVMedia } from './components/mango-av-media';\nif (typeof window !== 'undefined' && 'customElements' in window) defineMangoAVMedia();\n"],"mappings":";;;;;;;;;;AAGA,IAAI,OAAO,WAAW,eAAe,oBAAoB,OAAQ,oBAAmB;","names":[]}
@@ -0,0 +1,27 @@
1
+ import { A as AVControllerElement } from './controller-element-BOKM9v2S.js';
2
+ import { J as JsonObject, g as AVPlayerConfig, e as AVManifest, c as AVCanvas, i as AVPlayerEventMap } from './controller-DLy38ais.js';
3
+
4
+ declare class MangoAVPlayerElement extends AVControllerElement {
5
+ #private;
6
+ static observedAttributes: string[];
7
+ constructor();
8
+ get manifest(): JsonObject | string | undefined;
9
+ set manifest(value: JsonObject | string | undefined);
10
+ get config(): AVPlayerConfig;
11
+ set config(value: AVPlayerConfig);
12
+ connectedCallback(): void;
13
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
14
+ load(input: JsonObject | string): Promise<AVManifest>;
15
+ play(): Promise<void>;
16
+ pause(): void;
17
+ seekTo(time: number): void;
18
+ selectCanvas(indexOrId: number | string, options?: {
19
+ time?: number;
20
+ autoplay?: boolean;
21
+ }): AVCanvas | undefined;
22
+ protected controllerChanged(): void;
23
+ protected handleControllerEvent<K extends keyof AVPlayerEventMap>(type: K, event: CustomEvent<AVPlayerEventMap[K]>): void;
24
+ }
25
+ declare const defineMangoAVPlayer: (tagName?: string) => typeof MangoAVPlayerElement;
26
+
27
+ export { MangoAVPlayerElement, defineMangoAVPlayer };
package/dist/player.js ADDED
@@ -0,0 +1,15 @@
1
+ import {
2
+ MangoAVPlayerElement,
3
+ defineMangoAVPlayer
4
+ } from "./chunk-ML77YRJL.js";
5
+ import "./chunk-NTHMZZYJ.js";
6
+ import "./chunk-JXUHKKIX.js";
7
+ import "./chunk-R4OUWZ3R.js";
8
+
9
+ // src/player.ts
10
+ if (typeof window !== "undefined" && "customElements" in window) defineMangoAVPlayer();
11
+ export {
12
+ MangoAVPlayerElement,
13
+ defineMangoAVPlayer
14
+ };
15
+ //# sourceMappingURL=player.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/player.ts"],"sourcesContent":["export { defineMangoAVPlayer, MangoAVPlayerElement } from './components/mango-av-player';\n\nimport { defineMangoAVPlayer } from './components/mango-av-player';\nif (typeof window !== 'undefined' && 'customElements' in window) defineMangoAVPlayer();\n"],"mappings":";;;;;;;;;AAGA,IAAI,OAAO,WAAW,eAAe,oBAAoB,OAAQ,qBAAoB;","names":[]}
@@ -0,0 +1,12 @@
1
+ import { A as AVControllerElement } from './controller-element-BOKM9v2S.js';
2
+ import { i as AVPlayerEventMap } from './controller-DLy38ais.js';
3
+
4
+ declare class MangoAVTranscriptElement extends AVControllerElement {
5
+ #private;
6
+ constructor();
7
+ protected controllerChanged(): void;
8
+ protected handleControllerEvent<K extends keyof AVPlayerEventMap>(type: K, _event: CustomEvent<AVPlayerEventMap[K]>): void;
9
+ }
10
+ declare const defineMangoAVTranscript: (tagName?: string) => typeof MangoAVTranscriptElement;
11
+
12
+ export { MangoAVTranscriptElement, defineMangoAVTranscript };
@@ -0,0 +1,16 @@
1
+ import {
2
+ MangoAVTranscriptElement,
3
+ defineMangoAVTranscript
4
+ } from "./chunk-PZ6GV6ZJ.js";
5
+ import "./chunk-CDLYT3KB.js";
6
+ import "./chunk-3LLEY7MA.js";
7
+ import "./chunk-JXUHKKIX.js";
8
+ import "./chunk-R4OUWZ3R.js";
9
+
10
+ // src/transcript-element.ts
11
+ if (typeof window !== "undefined" && "customElements" in window) defineMangoAVTranscript();
12
+ export {
13
+ MangoAVTranscriptElement,
14
+ defineMangoAVTranscript
15
+ };
16
+ //# sourceMappingURL=transcript-element.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transcript-element.ts"],"sourcesContent":["export { defineMangoAVTranscript, MangoAVTranscriptElement } from './components/mango-av-transcript';\n\nimport { defineMangoAVTranscript } from './components/mango-av-transcript';\nif (typeof window !== 'undefined' && 'customElements' in window) defineMangoAVTranscript();\n"],"mappings":";;;;;;;;;;AAGA,IAAI,OAAO,WAAW,eAAe,oBAAoB,OAAQ,yBAAwB;","names":[]}
package/docs/API.md ADDED
@@ -0,0 +1,264 @@
1
+ # API reference
2
+
3
+ ## Entry points
4
+
5
+ - `@mango-iiif/av` exports the complete API and registers all Mango AV custom elements in a browser.
6
+ - `@mango-iiif/av/core` exports parsing, types, transcript helpers, and `AVPlayerController` without registering a custom element.
7
+ - `@mango-iiif/av/media`, `/player`, `/chapters`, `/transcript`, and `/annotations` register and export only the selected element.
8
+
9
+ ## Components
10
+
11
+ | Element | Purpose |
12
+ | --- | --- |
13
+ | `<mango-av-media>` | Complete precomposed player, navigation, transcript, annotations, metadata, and files. |
14
+ | `<mango-av-player>` | Media Chrome audio/video playback and Canvas/source controls only. |
15
+ | `<mango-av-chapters>` | Independently placeable structured Range navigation. |
16
+ | `<mango-av-transcript>` | Independently placeable synchronized transcript, selector, search, and download UI. |
17
+ | `<mango-av-annotations>` | Independently placeable synchronized annotation UI. |
18
+
19
+ ## `<mango-av-media>`
20
+
21
+ ### Attributes
22
+
23
+ | Attribute | Type | Purpose |
24
+ | --- | --- | --- |
25
+ | `manifest-url` | URL | Fetch and load a IIIF Presentation 2 or 3 Manifest. |
26
+ | `config` | JSON string | Set JSON-compatible `AVPlayerConfig` fields. Function hooks must be assigned through the property API. |
27
+
28
+ ### Properties and methods
29
+
30
+ | Member | Type | Purpose |
31
+ | --- | --- | --- |
32
+ | `manifest` | `JsonObject \| string` | Manifest object, raw JSON, or URL. Setting it loads the resource. |
33
+ | `config` | `AVPlayerConfig` | Runtime configuration, including callbacks. |
34
+ | `controller` | `AVPlayerController` | Shared state and playback controller. The legacy `player` alias exposes the same instance. |
35
+ | `load(input)` | `Promise<AVManifest>` | Load and normalize a manifest. |
36
+ | `play()` | `Promise<void>` | Begin playback. |
37
+ | `pause()` | `void` | Pause playback. |
38
+ | `seekTo(seconds)` | `void` | Seek within the active source/segment. |
39
+ | `selectCanvas(indexOrId, options?)` | `AVCanvas \| undefined` | Change Canvas and optionally seek/autoplay. |
40
+
41
+ ### Slots
42
+
43
+ | Slot | Location |
44
+ | --- | --- |
45
+ | `header` | Replaces the default manifest title and summary. |
46
+ | `before-player` | Before the Media Chrome controller. |
47
+ | `player-overlay` | Inside the Media Chrome controller, above media. |
48
+ | `controls` | Replaces the default Media Chrome controls and menus. |
49
+ | `after-player` | After the player and toolbar. |
50
+
51
+ ## Standalone components
52
+
53
+ Every standalone component has a `controller: AVPlayerController` property. Assign the same controller instance to any components that should synchronize:
54
+
55
+ ```ts
56
+ const controller = new AVPlayerController();
57
+
58
+ player.controller = controller;
59
+ chapters.controller = controller;
60
+ transcript.controller = controller;
61
+ annotations.controller = controller;
62
+
63
+ await controller.load(manifest);
64
+ ```
65
+
66
+ The elements can be in unrelated parts of the document or application component tree. Communication occurs through the controller rather than DOM ancestry.
67
+
68
+ Use one `<mango-av-player>` per controller because the controller attaches to one active media element. Any number of chapters, transcript, annotations, or application-owned views can share it.
69
+
70
+ Use the component subpath entry points when an application should bundle only selected UI elements:
71
+
72
+ ```ts
73
+ import '@mango-iiif/av/player';
74
+ import '@mango-iiif/av/chapters';
75
+ import '@mango-iiif/av/transcript';
76
+ ```
77
+
78
+ Subscribe to the same typed event stream from application code with `controller.on()`:
79
+
80
+ ```ts
81
+ const unsubscribe = controller.on('av-canvaschange', (event) => {
82
+ console.log(event.detail.canvas, event.detail.canvasIndex);
83
+ });
84
+
85
+ unsubscribe();
86
+ ```
87
+
88
+ ## Translations
89
+
90
+ `AVPlayerConfig.strings` accepts `Partial<AVStrings>`. Overrides are merged with `defaultStrings`, so a translation can be introduced incrementally and all unspecified strings remain English.
91
+
92
+ ```ts
93
+ import { AVPlayerController, defaultStrings, type AVStrings } from '@mango-iiif/av/core';
94
+
95
+ const welsh: Partial<AVStrings> = {
96
+ chapters: 'Penodau',
97
+ transcript: 'Trawsgrifiad',
98
+ previous: 'Blaenorol',
99
+ next: 'Nesaf',
100
+ sourceNumber: 'Ffynhonnell {number}',
101
+ resumePrompt: 'Parhau o {time}?',
102
+ };
103
+
104
+ const controller = new AVPlayerController({
105
+ preferredLanguages: ['cy', 'en', 'none'],
106
+ strings: welsh,
107
+ });
108
+ ```
109
+
110
+ The placeholders `{number}`, `{time}`, `{status}`, `{statusText}`, and `{type}` are retained until rendering. Translation values can therefore be supplied through either the TypeScript API or the JSON `config` attribute. `controller.configure({ strings })` updates all connected components and emits `av-configchange`.
111
+
112
+ String keys cover:
113
+
114
+ - panel, navigation, download, search, resume, and accessibility labels;
115
+ - loading, error, and empty states;
116
+ - generated IIIF fallback labels such as `sourceNumber`, `transcriptNumber`, `sectionNumber`, `chapterNumber`, and `untitledManifest`.
117
+
118
+ `preferredLanguages` separately controls which language is selected from IIIF language maps. It is also applied to Media Chrome's `lang` attribute. German, Spanish, French, Portuguese, Simplified Chinese, and Traditional Chinese Media Chrome dictionaries are loaded automatically when selected; custom Mango AV strings work with any language.
119
+
120
+ ### `<mango-av-player>`
121
+
122
+ The standalone player supports `manifest`, `config`, `load`, `play`, `pause`, `seekTo`, and `selectCanvas`, as well as the `manifest-url` and JSON `config` attributes. Its slots are `overlay` and `controls`.
123
+
124
+ ### `<mango-av-chapters>`
125
+
126
+ Renders nested IIIF Ranges. Selecting a chapter calls `controller.selectCanvas()` and emits the bubbling `av-chapterselect` DOM event.
127
+
128
+ ### `<mango-av-transcript>`
129
+
130
+ Loads the active Canvas transcript and follows controller time. Selecting a timed cue calls `controller.seekTo()` and `controller.play()`. It emits `av-transcriptcueselect` and `av-transcriptsearch`. The heading can be replaced through the `heading` slot.
131
+
132
+ ### `<mango-av-annotations>`
133
+
134
+ Renders and follows the active Canvas annotations. Selecting a timed annotation calls `controller.seekTo()` and `controller.play()`. It emits `av-annotationselect`. The heading can be replaced through the `heading` slot.
135
+
136
+ ### CSS custom properties
137
+
138
+ | Property | Default |
139
+ | --- | --- |
140
+ | `--mango-av-accent` | `#5b3fd6` |
141
+ | `--mango-av-accent-contrast` | `#fff` |
142
+ | `--mango-av-background` | `#fff` |
143
+ | `--mango-av-surface` | `#f5f5f8` |
144
+ | `--mango-av-text` | `#18181b` |
145
+ | `--mango-av-muted` | `#62626a` |
146
+ | `--mango-av-border` | `#d7d7de` |
147
+ | `--mango-av-radius` | `.65rem` |
148
+ | `--mango-av-font` | system sans-serif |
149
+ | `--mango-av-panel-width` | `24rem` |
150
+ | `--mango-av-player-aspect-ratio` | `16 / 9` |
151
+
152
+ Media Chrome's own public variables remain available and can override the mapped defaults.
153
+
154
+ ## `AVPlayerConfig`
155
+
156
+ ```ts
157
+ interface AVPlayerConfig {
158
+ controls?: {
159
+ seek?: boolean;
160
+ volume?: boolean;
161
+ captions?: boolean;
162
+ playbackRate?: boolean;
163
+ pictureInPicture?: boolean;
164
+ fullscreen?: boolean;
165
+ sourceSelector?: boolean;
166
+ download?: boolean;
167
+ skipSeconds?: number;
168
+ };
169
+ panels?: {
170
+ chapters?: boolean;
171
+ transcript?: boolean;
172
+ annotations?: boolean;
173
+ metadata?: boolean;
174
+ supplementalFiles?: boolean;
175
+ };
176
+ transcript?: {
177
+ autoScroll?: boolean;
178
+ search?: boolean;
179
+ download?: boolean;
180
+ showNotes?: boolean;
181
+ showMetadata?: boolean;
182
+ showSearchMarkers?: boolean;
183
+ };
184
+ resume?: {
185
+ enabled?: boolean;
186
+ maxItems?: number;
187
+ ttlDays?: number;
188
+ prompt?: boolean;
189
+ };
190
+ strings?: Partial<AVStrings>;
191
+ preferredLanguages?: string[];
192
+ autoAdvance?: boolean;
193
+ repeat?: boolean;
194
+ startCanvasId?: string;
195
+ startTime?: number;
196
+ activePanel?: 'chapters' | 'transcript' | 'annotations' | 'metadata' | 'files' | 'none';
197
+ crossorigin?: 'anonymous' | 'use-credentials' | '';
198
+ preload?: 'none' | 'metadata' | 'auto';
199
+ playbackRates?: number[];
200
+ fetch?: typeof globalThis.fetch;
201
+ requestInit?: RequestInit;
202
+ resolveRequest?: (url, context) => string | Promise<string>;
203
+ annotationAdapter?: AVAnnotationAdapter;
204
+ }
205
+ ```
206
+
207
+ `fetch` and `requestInit` configure manifest, external AnnotationPage, and transcript requests. `resolveRequest` runs immediately before a media URL is assigned; it can obtain an IIIF Auth token, sign a URL, route through a proxy, or enforce an application's access policy. The normalized Canvas exposes discovered auth services to the callback through `context.canvas.authServices`.
208
+
209
+ `annotationAdapter` connects create/update/delete to the host's persistence API:
210
+
211
+ ```ts
212
+ media.config = {
213
+ annotationAdapter: {
214
+ create: async (canvas, draft) => api.create(canvas.id, draft),
215
+ update: async (canvas, annotation) => api.update(canvas.id, annotation),
216
+ remove: async (canvas, annotation) => api.remove(canvas.id, annotation.id),
217
+ },
218
+ };
219
+
220
+ await media.controller.createAnnotation({
221
+ text: 'Important passage',
222
+ time: { start: 12, end: 18 },
223
+ motivation: ['highlighting'],
224
+ });
225
+ ```
226
+
227
+ If no adapter is supplied, annotation mutations are local for the current session.
228
+
229
+ ## `AVPlayerController`
230
+
231
+ Playback methods:
232
+
233
+ - `load`, `attachMedia`, `detachMedia`, and `destroy`
234
+ - `play`, `pause`, `stop`, `seekTo`, and `seekBy`
235
+ - `selectCanvas`, `next`, `previous`, and `selectSource`
236
+ - `setAutoAdvance` and `setRepeat`
237
+ - `getSavedPosition` and `resolvedSourceUrl`
238
+ - `createAnnotation`, `updateAnnotation`, and `removeAnnotation`
239
+ - `on(event, listener)`, which returns an unsubscribe function
240
+
241
+ Read-only properties are `config`, `state`, `manifest`, `canvas`, `source`, and `media`.
242
+
243
+ ## Events
244
+
245
+ `AVPlayerController` is the canonical cross-component event bus. It emits the events below to every component sharing that instance. `<mango-av-media>` and `<mango-av-player>` also expose controller events as bubbling, composed DOM `CustomEvent`s for host application integration.
246
+
247
+ | Event | Detail |
248
+ | --- | --- |
249
+ | `av-loadstart` | Input source |
250
+ | `av-ready` | Normalized manifest |
251
+ | `av-error` | `Error` |
252
+ | `av-canvaschange` | Canvas and index |
253
+ | `av-sourcechange` | Media source and index |
254
+ | `av-play`, `av-pause`, `av-ended` | Canvas ID and playback position where applicable |
255
+ | `av-timeupdate`, `av-seek` | Timeline values |
256
+ | `av-annotationschange` | Active Canvas annotation list |
257
+ | `av-configchange` | Resolved controller configuration |
258
+ | `av-statechange` | Complete `AVPlayerState` snapshot |
259
+
260
+ ## Parsing helpers
261
+
262
+ `normalizeManifest(input, options)` is the version boundary. It returns the same `AVManifest` model for IIIF Presentation 2 and 3.
263
+
264
+ `parseTimedText`, `parseTranscript`, and `loadTranscript` support WebVTT, SRT, plain text, and structured JSON. `parseTime`, `parseTemporalFragment`, and `formatTime` are also public.
@@ -0,0 +1,43 @@
1
+ # Feature coverage
2
+
3
+ This document records the audio, video, IIIF, transcript, annotation, and integration behavior implemented in `@mango-iiif/av`.
4
+
5
+ | Capability | `@mango-iiif/av` implementation | Verification |
6
+ | --- | --- | --- |
7
+ | Root IIIF player with URL/object input | `<mango-av-media>` and `AVPlayerController.load` | Unit + browser |
8
+ | Video and audio playback | Native media elements inside Media Chrome | Browser |
9
+ | HLS | `<hls-video>` with native HLS/hls.js fallback | Browser demo |
10
+ | Multiple media resources and quality/source selection | Normalized `Choice`/body list and source selector | Unit |
11
+ | Multi-Canvas playback | Previous, next, Canvas selection, state events | Unit + browser |
12
+ | Temporal Canvas/source clipping | `#t=` normalization and segment enforcement | Unit |
13
+ | Custom start Canvas/time | Presentation 2 `startCanvas`, Presentation 3 `start`, and config overrides | Unit |
14
+ | Auto-advance and repeat | Manifest behavior plus runtime toggle/API | Unit/controller |
15
+ | Structured navigation | Recursive Presentation 2/3 Range model and accessible chapter buttons | Unit + browser |
16
+ | Transcripts | Inline/external transcript resources and synchronized panel | Unit + browser |
17
+ | Transcript formats | WebVTT, SRT, text, JSON, and inline TextualBody; DOCX is intentionally excluded | Unit |
18
+ | Transcript selector/search/download | Configurable transcript tools | Browser |
19
+ | Transcript auto-scroll | Active cue tracking against controller time | Browser |
20
+ | Captions/subtitles/descriptions | Native tracks and Media Chrome captions menu | Parser unit + browser |
21
+ | Time-synchronized annotations | Commenting, supplementing, transcribing, tagging, and highlighting display | Unit + browser |
22
+ | Marker create/edit/delete endpoints | Typed `annotationAdapter` and controller mutation API | Controller API |
23
+ | Metadata display | Manifest + Canvas metadata, rights, and required statement | Parser unit + browser |
24
+ | Supplemental files | Manifest + Canvas `rendering` downloads | Parser unit + browser |
25
+ | Resume playback | Bounded, expiring local-storage cache with optional prompt | Controller/browser |
26
+ | IIIF Auth integration | Auth service discovery plus configurable fetch/request resolver | Parser unit/API |
27
+ | Poster/placeholder | Presentation 3 `placeholderCanvas` extraction | Parser |
28
+ | Responsive layout and accessibility | Responsive panel, native controls, ARIA tabs/navigation, keyboard-native buttons | Playwright |
29
+ | Standalone usage | Complete and independently placeable framework-free elements plus controller-only entry point | Build/pack |
30
+ | Configurable appearance | CSS properties, named slots, Media Chrome variables, live style recipes | Playwright/demo |
31
+
32
+ ## Deliberate API differences
33
+
34
+ - React Context and React component props are replaced by a typed controller and DOM events.
35
+ - Video.js-specific plugin APIs are replaced by standard `HTMLMediaElement` methods and Media Chrome controls.
36
+ - Playlist marker mutations use `annotationAdapter`, allowing REST, GraphQL, local-first, or authenticated persistence.
37
+ - Protected-resource policy remains with the consuming application through `fetch`, `requestInit`, and `resolveRequest`; the package does not hard-code a login provider or token transport.
38
+ - Styling uses stable host-level custom properties and slots rather than component SCSS overrides.
39
+ - DOCX/Word transcript parsing is intentionally out of scope; the loader rejects it explicitly.
40
+
41
+ ## Additional IIIF behavior
42
+
43
+ The normalized model also preserves Presentation version, Canvas behaviors, audio-description tracks, nested Ranges, required statements, rights, homepages, auth services, source dimensions/duration, and machine-generated transcript flags. Unknown motivations and behaviors are retained as strings so extensions remain available to host applications.