@ktt45678/vidstack
Version:
UI component library for building high-quality, accessible video and audio experiences on the web.
193 lines (187 loc) • 5.37 kB
JavaScript
import { onDispose, listenEvent, DOMEvent, scoped } from '../chunks/vidstack-C6myozhB.js';
import { canUsePictureInPicture, canUseVideoPresentation, canPlayHLSNatively } from '../chunks/vidstack-CTW_LGt6.js';
import { HTMLMediaProvider } from './vidstack-html.js';
import { HTMLAirPlayAdapter } from '../chunks/vidstack-B7-_7of1.js';
import { TextTrack, TextTrackSymbol } from '../chunks/vidstack-CFEqcMSQ.js';
import '../chunks/vidstack-C-clE4br.js';
import '../chunks/vidstack-Dihypf8P.js';
import '../chunks/vidstack-BoSiLpaP.js';
import 'media-captions';
import '../chunks/vidstack-CVbXna2m.js';
import '../chunks/vidstack-D2w309v1.js';
class NativeHLSTextTracks {
constructor(_video, _ctx) {
this.m = _video;
this.b = _ctx;
_video.textTracks.onaddtrack = this.Yd.bind(this);
onDispose(this.ce.bind(this));
}
Yd(event) {
const nativeTrack = event.track;
if (!nativeTrack || findTextTrackElement(this.m, nativeTrack)) return;
const track = new TextTrack({
id: nativeTrack.id,
kind: nativeTrack.kind,
label: nativeTrack.label ?? "",
language: nativeTrack.language,
type: "vtt"
});
track[TextTrackSymbol._] = { track: nativeTrack };
track[TextTrackSymbol.ma] = 2;
track[TextTrackSymbol.Mf] = true;
let lastIndex = 0;
const onCueChange = (event2) => {
if (!nativeTrack.cues) return;
for (let i = lastIndex; i < nativeTrack.cues.length; i++) {
track.addCue(nativeTrack.cues[i], event2);
lastIndex++;
}
};
onCueChange(event);
nativeTrack.oncuechange = onCueChange;
this.b.textTracks.add(track, event);
track.setMode(nativeTrack.mode, event);
}
ce() {
this.m.textTracks.onaddtrack = null;
for (const track of this.b.textTracks) {
const nativeTrack = track[TextTrackSymbol._]?.track;
if (nativeTrack?.oncuechange) nativeTrack.oncuechange = null;
}
}
}
function findTextTrackElement(video, track) {
return Array.from(video.children).find((el) => el.track === track);
}
class VideoPictureInPicture {
constructor(_video, _media) {
this.m = _video;
this.a = _media;
this.E = (active, event) => {
this.a.delegate.c("picture-in-picture-change", active, event);
};
listenEvent(this.m, "enterpictureinpicture", this.Gi.bind(this));
listenEvent(this.m, "leavepictureinpicture", this.Hi.bind(this));
}
get active() {
return document.pictureInPictureElement === this.m;
}
get supported() {
return canUsePictureInPicture(this.m);
}
async enter() {
return this.m.requestPictureInPicture();
}
exit() {
return document.exitPictureInPicture();
}
Gi(event) {
this.E(true, event);
}
Hi(event) {
this.E(false, event);
}
}
class VideoPresentation {
constructor(_video, _media) {
this.m = _video;
this.a = _media;
this.U = "inline";
listenEvent(this.m, "webkitpresentationmodechanged", this.hb.bind(this));
}
get pb() {
return canUseVideoPresentation(this.m);
}
async fd(mode) {
if (this.U === mode) return;
this.m.webkitSetPresentationMode(mode);
}
hb(event) {
const prevMode = this.U;
this.U = this.m.webkitPresentationMode;
this.a.player?.dispatch(
new DOMEvent("video-presentation-change", {
detail: this.U,
trigger: event
})
);
["fullscreen", "picture-in-picture"].forEach((type) => {
if (this.U === type || prevMode === type) {
this.a.delegate.c(`${type}-change`, this.U === type, event);
}
});
}
}
class FullscreenPresentationAdapter {
constructor(_presentation) {
this.Oa = _presentation;
}
get active() {
return this.Oa.U === "fullscreen";
}
get supported() {
return this.Oa.pb;
}
async enter() {
this.Oa.fd("fullscreen");
}
async exit() {
this.Oa.fd("inline");
}
}
class PIPPresentationAdapter {
constructor(_presentation) {
this.Oa = _presentation;
}
get active() {
return this.Oa.U === "picture-in-picture";
}
get supported() {
return this.Oa.pb;
}
async enter() {
this.Oa.fd("picture-in-picture");
}
async exit() {
this.Oa.fd("inline");
}
}
class VideoProvider extends HTMLMediaProvider {
constructor(video, ctx) {
super(video, ctx);
this.$$PROVIDER_TYPE = "VIDEO";
scoped(() => {
this.airPlay = new HTMLAirPlayAdapter(video, ctx);
if (canUseVideoPresentation(video)) {
const presentation = new VideoPresentation(video, ctx);
this.fullscreen = new FullscreenPresentationAdapter(presentation);
this.pictureInPicture = new PIPPresentationAdapter(presentation);
} else if (canUsePictureInPicture(video)) {
this.pictureInPicture = new VideoPictureInPicture(video, ctx);
}
}, this.scope);
}
get type() {
return "video";
}
setup() {
super.setup();
if (canPlayHLSNatively(this.video)) {
new NativeHLSTextTracks(this.video, this.b);
}
this.b.textRenderers.Xf(this.video);
onDispose(() => {
this.b.textRenderers.Xf(null);
});
if (this.type === "video") this.b.delegate.c("provider-setup", this);
}
/**
* The native HTML `<video>` element.
*
* @see {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement}
*/
get video() {
return this.a;
}
}
export { VideoProvider };