@fusion.dev/helix-headless 0.56.0 → 0.57.0
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.
- package/custom-elements.json +79 -427
- package/dist/video/root/extra-controls.d.ts +43 -0
- package/dist/video/root/extra-controls.js +41 -0
- package/dist/video/root/keys.d.ts +25 -0
- package/dist/video/root/keys.js +50 -0
- package/dist/video/root/video-root.d.ts +7 -36
- package/dist/video/root/video-root.js +20 -112
- package/package.json +5 -5
- package/dist/video/root/captions.d.ts +0 -85
- package/dist/video/root/captions.js +0 -45
- package/dist/video/root/fullscreen.d.ts +0 -28
- package/dist/video/root/fullscreen.js +0 -28
- package/dist/video/root/idle.d.ts +0 -34
- package/dist/video/root/idle.js +0 -24
- package/dist/video/root/media-session.d.ts +0 -54
- package/dist/video/root/media-session.js +0 -49
- package/dist/video/root/remote-playback.d.ts +0 -34
- package/dist/video/root/remote-playback.js +0 -38
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
-
/**
|
|
3
|
-
* How long the reader has been still, which decides when the bar goes.
|
|
4
|
-
*
|
|
5
|
-
* A wait rather than leaving with the pointer, or a reader moving across the
|
|
6
|
-
* picture to reach a control watches the bar vanish under them. The wait is
|
|
7
|
-
* only ever about *idling*: whether a paused video keeps its bar is the
|
|
8
|
-
* element's decision, and this only says when the reader stopped.
|
|
9
|
-
*
|
|
10
|
-
* The delay is asked for on every restart rather than taken once, because it
|
|
11
|
-
* is a property the consumer can change while the video plays.
|
|
12
|
-
*/
|
|
13
|
-
export declare class IdleController implements ReactiveController {
|
|
14
|
-
private readonly delay;
|
|
15
|
-
private readonly report;
|
|
16
|
-
private timer;
|
|
17
|
-
constructor(host: ReactiveControllerHost, delay: () => number, report: (idle: boolean) => void);
|
|
18
|
-
/**
|
|
19
|
-
* Restarts the wait, on anything that counts as the reader being here.
|
|
20
|
-
*
|
|
21
|
-
* Pointer movement and focus both count, and both have to: a reader using the
|
|
22
|
-
* keyboard never moves a pointer, and a bar that only answered the mouse
|
|
23
|
-
* would leave them nothing to look at. Zero turns the wait off and the bar
|
|
24
|
-
* goes immediately; a large number keeps it up for as long as anyone is
|
|
25
|
-
* likely to look.
|
|
26
|
-
*/
|
|
27
|
-
readonly stir: () => void;
|
|
28
|
-
/**
|
|
29
|
-
* Leaving is the one case that does not wait: the reader has gone somewhere
|
|
30
|
-
* else, and there is nothing to reach for.
|
|
31
|
-
*/
|
|
32
|
-
readonly leave: () => void;
|
|
33
|
-
hostDisconnected(): void;
|
|
34
|
-
}
|
package/dist/video/root/idle.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export class IdleController {
|
|
2
|
-
constructor(host, delay, report) {
|
|
3
|
-
this.delay = delay;
|
|
4
|
-
this.report = report;
|
|
5
|
-
this.stir = () => {
|
|
6
|
-
this.report(false);
|
|
7
|
-
clearTimeout(this.timer);
|
|
8
|
-
const delay = this.delay();
|
|
9
|
-
if (delay > 0) {
|
|
10
|
-
this.timer = setTimeout(() => {
|
|
11
|
-
this.report(true);
|
|
12
|
-
}, delay);
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
this.leave = () => {
|
|
16
|
-
clearTimeout(this.timer);
|
|
17
|
-
this.report(true);
|
|
18
|
-
};
|
|
19
|
-
host.addController(this);
|
|
20
|
-
}
|
|
21
|
-
hostDisconnected() {
|
|
22
|
-
clearTimeout(this.timer);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
-
/**
|
|
3
|
-
* How far a skip control moves, in seconds.
|
|
4
|
-
*
|
|
5
|
-
* Ten, which is the number every player that has one uses, and the number the
|
|
6
|
-
* platform names in `seekbackward` and `seekforward` when it hands over a
|
|
7
|
-
* default. A different length here would be correct only on this player.
|
|
8
|
-
*/
|
|
9
|
-
export declare const SKIP_SECONDS = 10;
|
|
10
|
-
/** What a headset's buttons do, handed over by the player that owns them. */
|
|
11
|
-
export interface SessionHandlers {
|
|
12
|
-
/**
|
|
13
|
-
* Asks for the next item, or `null` where the consumer has named nothing to
|
|
14
|
-
* skip to: the platform draws the key from whether a handler is set.
|
|
15
|
-
*/
|
|
16
|
-
next: (() => void) | null;
|
|
17
|
-
/** And the previous one, under the same rule. */
|
|
18
|
-
previous: (() => void) | null;
|
|
19
|
-
seek: (seconds: number) => void;
|
|
20
|
-
skipBy: (seconds: number) => void;
|
|
21
|
-
toggle: () => void;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Holds the page's media session for one player, and tells the platform what
|
|
25
|
-
* is playing.
|
|
26
|
-
*
|
|
27
|
-
* The handlers are what make a headset's play, pause and skip work at all.
|
|
28
|
-
* Without them a platform falls back to guessing which element was meant,
|
|
29
|
-
* which is right often enough to hide the fault and wrong exactly when there
|
|
30
|
-
* are two.
|
|
31
|
-
*/
|
|
32
|
-
export declare class MediaSessionController implements ReactiveController {
|
|
33
|
-
private readonly host;
|
|
34
|
-
constructor(host: ReactiveControllerHost & HTMLElement);
|
|
35
|
-
/**
|
|
36
|
-
* Takes the session.
|
|
37
|
-
*
|
|
38
|
-
* On play rather than on render, which is the ownership rule: a page with two
|
|
39
|
-
* players gives the session to whichever one the reader started, so a
|
|
40
|
-
* headset's buttons land on what they are listening to rather than on
|
|
41
|
-
* whichever came first in the markup.
|
|
42
|
-
*/
|
|
43
|
-
claim(metadata: {
|
|
44
|
-
artwork: string;
|
|
45
|
-
title: string;
|
|
46
|
-
}, handlers: SessionHandlers): void;
|
|
47
|
-
/** Tells the platform whether the owner is playing, and nothing if it is not the owner. */
|
|
48
|
-
report(playing: boolean): void;
|
|
49
|
-
/**
|
|
50
|
-
* The page's one media session goes back to nobody, but only if this
|
|
51
|
-
* element is the one holding it.
|
|
52
|
-
*/
|
|
53
|
-
hostDisconnected(): void;
|
|
54
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
let owner;
|
|
2
|
-
export const SKIP_SECONDS = 10;
|
|
3
|
-
export class MediaSessionController {
|
|
4
|
-
constructor(host) {
|
|
5
|
-
this.host = host;
|
|
6
|
-
host.addController(this);
|
|
7
|
-
}
|
|
8
|
-
claim(metadata, handlers) {
|
|
9
|
-
if (typeof navigator === 'undefined' || !navigator.mediaSession) {
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
owner = this.host;
|
|
13
|
-
const session = navigator.mediaSession;
|
|
14
|
-
session.metadata = new MediaMetadata({
|
|
15
|
-
artwork: metadata.artwork === '' ? [] : [{ src: metadata.artwork }],
|
|
16
|
-
title: metadata.title,
|
|
17
|
-
});
|
|
18
|
-
session.setActionHandler('play', handlers.toggle);
|
|
19
|
-
session.setActionHandler('pause', handlers.toggle);
|
|
20
|
-
session.setActionHandler('seekto', (details) => {
|
|
21
|
-
if (details.seekTime !== undefined && details.seekTime !== null) {
|
|
22
|
-
handlers.seek(details.seekTime);
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
session.setActionHandler('seekbackward', (details) => {
|
|
26
|
-
handlers.skipBy(-(details.seekOffset ?? SKIP_SECONDS));
|
|
27
|
-
});
|
|
28
|
-
session.setActionHandler('seekforward', (details) => {
|
|
29
|
-
handlers.skipBy(details.seekOffset ?? SKIP_SECONDS);
|
|
30
|
-
});
|
|
31
|
-
session.setActionHandler('nexttrack', handlers.next);
|
|
32
|
-
session.setActionHandler('previoustrack', handlers.previous);
|
|
33
|
-
}
|
|
34
|
-
report(playing) {
|
|
35
|
-
if (owner === this.host && typeof navigator !== 'undefined' && navigator.mediaSession) {
|
|
36
|
-
navigator.mediaSession.playbackState = playing ? 'playing' : 'paused';
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
hostDisconnected() {
|
|
40
|
-
if (owner !== this.host) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
owner = undefined;
|
|
44
|
-
if (typeof navigator !== 'undefined' && navigator.mediaSession) {
|
|
45
|
-
navigator.mediaSession.metadata = null;
|
|
46
|
-
navigator.mediaSession.playbackState = 'none';
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
-
/** What the watch reports, as it learns it. */
|
|
3
|
-
export interface RemoteReport {
|
|
4
|
-
/** Whether anything on the network offers to play this. */
|
|
5
|
-
available: (available: boolean) => void;
|
|
6
|
-
/** Whether it is playing somewhere else right now. */
|
|
7
|
-
connected: (connected: boolean) => void;
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Watches for something to play the video on, and stops on the way out.
|
|
11
|
-
*
|
|
12
|
-
* The Remote Playback API is the standard one, and it is what Safari
|
|
13
|
-
* implements for AirPlay and Chrome for Cast: one call covers both, where the
|
|
14
|
-
* older `webkitShowPlaybackTargetPicker` covers only the first. Firefox has
|
|
15
|
-
* neither, and `remote` simply being absent is what turns the control off
|
|
16
|
-
* there.
|
|
17
|
-
*
|
|
18
|
-
* `watchAvailability` returns an id that has to be canceled, or the callback
|
|
19
|
-
* outlives the element that owns it: a callback holding a removed element is a
|
|
20
|
-
* leak with a `@state` write on the end.
|
|
21
|
-
*/
|
|
22
|
-
export declare class RemotePlaybackController implements ReactiveController {
|
|
23
|
-
private readonly report;
|
|
24
|
-
private video;
|
|
25
|
-
/** Cancels the availability watch, since it outlives a single render. */
|
|
26
|
-
private watch;
|
|
27
|
-
constructor(host: ReactiveControllerHost, report: RemoteReport);
|
|
28
|
-
/** Starts watching the video, once there is one. */
|
|
29
|
-
attach(video: HTMLVideoElement): Promise<void>;
|
|
30
|
-
/** Opens the platform's own device picker. It has no list of its own. */
|
|
31
|
-
prompt(): Promise<void>;
|
|
32
|
-
hostDisconnected(): void;
|
|
33
|
-
private readonly handleState;
|
|
34
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export class RemotePlaybackController {
|
|
2
|
-
constructor(host, report) {
|
|
3
|
-
this.report = report;
|
|
4
|
-
this.handleState = () => {
|
|
5
|
-
this.report.connected(this.video?.remote?.state === 'connected');
|
|
6
|
-
};
|
|
7
|
-
host.addController(this);
|
|
8
|
-
}
|
|
9
|
-
async attach(video) {
|
|
10
|
-
this.video = video;
|
|
11
|
-
video.remote?.addEventListener?.('connect', this.handleState);
|
|
12
|
-
video.remote?.addEventListener?.('disconnect', this.handleState);
|
|
13
|
-
const remote = video.remote;
|
|
14
|
-
if (!remote?.watchAvailability) {
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
try {
|
|
18
|
-
this.watch = await remote.watchAvailability((available) => {
|
|
19
|
-
this.report.available(available);
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
async prompt() {
|
|
26
|
-
try {
|
|
27
|
-
await this.video?.remote?.prompt();
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
hostDisconnected() {
|
|
33
|
-
if (this.watch !== undefined) {
|
|
34
|
-
void this.video?.remote?.cancelWatchAvailability?.(this.watch);
|
|
35
|
-
this.watch = undefined;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|