@munsonlabs/video-player 0.1.5 → 0.2.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.
Files changed (36) hide show
  1. package/README.md +184 -21
  2. package/dist/chunks/ads-msms49DK.mjs +1 -0
  3. package/dist/chunks/brightcove-CIqE1989.mjs +1 -0
  4. package/dist/chunks/constants-DRD0PsRw.mjs +1 -0
  5. package/dist/chunks/dailymotion-wD02TK0C.mjs +1 -0
  6. package/dist/chunks/embedShared-B1B7ZH_3.mjs +1 -0
  7. package/dist/chunks/jwplayer-Dv826deA.mjs +1 -0
  8. package/dist/chunks/loadScript-Du6JsTc2.mjs +1 -0
  9. package/dist/chunks/prebid-RHDT0DOX.mjs +1 -0
  10. package/dist/chunks/sourceHelpers-DlkCZiTJ.mjs +1 -0
  11. package/dist/chunks/vimeo-SrHhodcx.mjs +1 -0
  12. package/dist/chunks/youtube-Boz9Goek.mjs +1 -0
  13. package/dist/elements/chunks/ads-msms49DK.mjs +1 -0
  14. package/dist/elements/chunks/brightcove-CIqE1989.mjs +1 -0
  15. package/dist/elements/chunks/constants-DRD0PsRw.mjs +1 -0
  16. package/dist/elements/chunks/dailymotion-wD02TK0C.mjs +1 -0
  17. package/dist/elements/chunks/embedShared-B1B7ZH_3.mjs +1 -0
  18. package/dist/elements/chunks/jwplayer-Dv826deA.mjs +1 -0
  19. package/dist/elements/chunks/loadScript-Du6JsTc2.mjs +1 -0
  20. package/dist/elements/chunks/prebid-RHDT0DOX.mjs +1 -0
  21. package/dist/elements/chunks/sourceHelpers-DlkCZiTJ.mjs +1 -0
  22. package/dist/elements/chunks/vimeo-SrHhodcx.mjs +1 -0
  23. package/dist/elements/chunks/youtube-Boz9Goek.mjs +1 -0
  24. package/dist/elements/controls.css +1 -1
  25. package/dist/elements/controls.d.mts +28 -49
  26. package/dist/elements/controls.mjs +1 -1
  27. package/dist/elements/core.css +1 -1
  28. package/dist/elements/core.d.mts +106 -5
  29. package/dist/elements/core.mjs +1 -5
  30. package/dist/elements/index.d.mts +119 -52
  31. package/dist/elements/index.mjs +1 -5
  32. package/dist/elements/style.css +1 -1
  33. package/dist/index.d.mts +299 -283
  34. package/dist/index.mjs +1 -5
  35. package/dist/style.css +1 -1
  36. package/package.json +3 -2
package/README.md CHANGED
@@ -27,6 +27,19 @@ import '@munsonlabs/video-player/style'
27
27
  </template>
28
28
  ```
29
29
 
30
+ ### Pinning a single player
31
+
32
+ Set `pin-position` on a standalone `VideoItem`/`VideoPlayer` (no `VideoStage` involved) to get the same corner-pinning mini-player behaviour `VideoStage` has, scoped to just that one player: once it scrolls out of view while playing, it pins to the given corner instead of auto-pausing, and shrinks back to its inline size once scrolled back into view.
33
+
34
+ ```vue
35
+ <VideoItem video-url="https://cdn.jwplayer.com/videos/O5chtspP-4VHSaSK0.mp4" pin-position="bottom-right" />
36
+ ```
37
+
38
+ - Only `'bottom-right'`, `'bottom-left'`, `'top-right'`, `'top-left'` are supported here (unlike `VideoStage`'s `pinPosition`, there's no `'full-width'` option for a single player).
39
+ - Pausing while pinned does **not** unpin it - like a mini-player, it stays put, paused, in the corner until scrolled back into view. A dismiss button and a scroll-to-player button are shown on the pinned box.
40
+ - Omit `pin-position` to disable pinning entirely - the player then just auto-pauses offscreen as usual.
41
+ - `HideMarker` (see [Hiding the pinned stage over content](#hiding-the-pinned-stage-over-content)) works the same way here too, since there's only ever one pinned/tucked element on a page at a time.
42
+
30
43
  ### Stage player
31
44
 
32
45
  `VideoStage` is a sticky full-width player that receives videos from `VideoItem` components anywhere on the page via window events. When the stage scrolls out of view it minifies to a pip in the bottom-right corner.
@@ -68,34 +81,79 @@ const stage = ref(null)
68
81
  </template>
69
82
  ```
70
83
 
84
+ ### Hiding the pinned stage over content
85
+
86
+ When `VideoStage` is pinned to a corner (any `pinPosition` other than `'full-width'`), it can sit over content you'd rather it not cover - a footer, a signup form, a comments section. `HideMarker` is a plain sentinel element: place it just before that content, and the stage slides mostly off-screen (leaving a small sliver) for as long as the marker is in the viewport, sliding back once it isn't.
87
+
88
+ ```vue
89
+ <script setup>
90
+ import { VideoStage, HideMarker } from '@munsonlabs/video-player'
91
+ </script>
92
+
93
+ <template>
94
+ <VideoStage pin-position="bottom-right" :playlist="videos" />
95
+
96
+ <!-- ...page content... -->
97
+
98
+ <HideMarker />
99
+ <Footer />
100
+ </template>
101
+ ```
102
+
103
+ - There's no prop linking `HideMarker` to a specific `VideoStage` - there's only ever one stage on a page, so it always applies to whichever one is mounted.
104
+ - The sliver width is a CSS custom property: `--mvp-stage-tuck` (default `32px`).
105
+ - `HideMarker` renders a single, unstyled, full-width `div` with `min-height: 1px` - it has no visible chrome of its own, and no slot for content. Because it's only 1px tall, it triggers briefly as the page scrolls past that exact line rather than staying "hidden" for as long as some section below it remains on screen; place it precisely where you want the stage to tuck away.
106
+
71
107
  ---
72
108
 
73
109
  ## VideoItem / VideoPlayer Props
74
110
 
75
- | Prop | Type | Default | Description |
76
- | ------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
77
- | `videoUrl` | `string` | - | **Required.** The video URL or platform-specific URI (the platform is auto-detected from its shape, see [Platform URLs](#platform-urls)) |
78
- | `title` | `string` | `''` | Video title |
79
- | `poster` | `string` | `''` | Poster image URL |
80
- | `aspectRatio` | `string` | `'16:9'` | e.g. `'16:9'`, `'9:16'`, `'4:3'` |
81
- | `autoplay` | `boolean` | `false` | Autoplay on mount (mutes automatically) |
82
- | `muted` | `boolean` | `false` | Start muted |
83
- | `lazy` | `boolean` | `true`\* | Show placeholder until clicked |
84
- | `nativeUi` | `boolean` | `false` | Use the platform's native controls (YouTube, Vimeo, Dailymotion only) |
85
- | `autoStage` | `boolean` | `false` | Immediately send this video to the stage on mount |
86
- | `playbackRate` | `number` | `1` | Initial playback rate |
87
- | `adTagUrl` | `string` | `''` | VAST or VMAP ad tag URL |
88
- | `adTagParams` | `object` | - | Fills `{macro}` tokens on whichever ad tag URL ends up in use, see [Ads](#ads-ima--vast--vmap) |
89
- | `headerBidding` | `object` | - | Runs a Prebid.js auction before the ad plays, see [Header bidding](#header-bidding-prebidjs) |
90
- | `tracks` | `array` | - | WebVTT caption/subtitle tracks, see [Captions](#captions-webvtt) |
91
- | `payload` | `object` | `{}` | Arbitrary data attached to every `state-change` event |
92
- | `action` | `PlayerAction` | `null` | Button shown in the player HUD, see [Actions](#actions) |
93
- | `disableTapCapture` | `boolean` | `false` | Disables the full-video tap-to-reveal-controls overlay (tap/click still reaches embed platform UI underneath, e.g. YouTube's own) |
94
- | `controls` | `boolean` | `true` | Set `false` to render a bare `<video>` with no built-in HUD - drive playback with your own UI instead, see [Headless Controls](#headless-controls) |
95
- | `playWhenInView` | `boolean` | `false` | Auto-play once at least half the player is visible, auto-pause once it isn't - e.g. for a scroll-snap feed. Implies `muted` unless `muted` is set explicitly |
111
+ | Prop | Type | Default | Description |
112
+ | ------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
113
+ | `videoUrl` | `string` | - | **Required.** The video URL or platform-specific URI (the platform is auto-detected from its shape, see [Platform URLs](#platform-urls)) |
114
+ | `title` | `string` | `''` | Video title |
115
+ | `poster` | `string` | `''` | Poster image URL |
116
+ | `aspectRatio` | `string` | `'16:9'` | e.g. `'16:9'`, `'9:16'`, `'4:3'` |
117
+ | `autoplay` | `boolean` | `false` | Autoplay on mount, see [Autoplay, mute & volume](#autoplay-mute--volume) |
118
+ | `muted` | `boolean` | - | Force a starting mute state - if unset, follows the shared audio preference, see [Autoplay, mute & volume](#autoplay-mute--volume) |
119
+ | `volume` | `number` | - | Force a starting volume (0-1) - if unset, follows the shared audio preference, see [Autoplay, mute & volume](#autoplay-mute--volume) |
120
+ | `lazy` | `boolean` | `true`\* | Show placeholder until clicked |
121
+ | `nativeUi` | `boolean` | `false` | Use the platform's native controls (YouTube, Vimeo, Dailymotion only) |
122
+ | `autoStage` | `boolean` | `false` | Immediately send this video to the stage on mount |
123
+ | `playbackRate` | `number` | `1` | Initial playback rate |
124
+ | `adTagUrl` | `string` | `''` | VAST or VMAP ad tag URL |
125
+ | `adTagParams` | `object` | - | Fills `{macro}` tokens on whichever ad tag URL ends up in use, see [Ads](#ads-ima--vast--vmap) |
126
+ | `headerBidding` | `object` | - | Runs a Prebid.js auction before the ad plays, see [Header bidding](#header-bidding-prebidjs) |
127
+ | `tracks` | `array` | - | WebVTT caption/subtitle tracks, see [Captions](#captions-webvtt) |
128
+ | `payload` | `object` | `{}` | Arbitrary data attached to every `state-change` event |
129
+ | `action` | `PlayerAction` | `null` | Button shown in the player HUD, see [Actions](#actions) |
130
+ | `disableTapCapture` | `boolean` | `false` | Disables the full-video tap-to-reveal-controls overlay (tap/click still reaches embed platform UI underneath, e.g. YouTube's own) |
131
+ | `controls` | `boolean` | `true` | Set `false` to render a bare `<video>` with no built-in HUD - drive playback with your own UI instead, see [Headless Controls](#headless-controls) |
132
+ | `playWhenInView` | `boolean` | `false` | Auto-play once at least half the player is visible, auto-pause once it isn't - e.g. for a scroll-snap feed, see [Autoplay, mute & volume](#autoplay-mute--volume) |
133
+ | `pinPosition` | `PinCorner` | - | Pins the player to this screen corner once it scrolls out of view while playing, instead of auto-pausing - see [Pinning a single player](#pinning-a-single-player) |
96
134
 
97
135
  \* `lazy` only has an effect on `VideoItem` (default `true`), which is what actually implements the placeholder-until-clicked behaviour. `VideoPlayer` accepts the prop for type compatibility but defaults to `false` and never reads it: using `<VideoPlayer>` directly always mounts the real player immediately, regardless of `lazy`.
98
136
 
137
+ ### Autoplay, mute & volume
138
+
139
+ Unless a video sets `muted`/`volume` explicitly, every player on the page shares one persisted audio preference (`localStorage`, updated whenever a viewer actually presses a mute button or drags a volume slider) - a newly-mounted or completely independent player starts at whatever level the viewer last chose anywhere else, instead of always resetting to full volume/unmuted.
140
+
141
+ Volume is never restricted - it always follows the shared preference. Mute has one hard exception layered on top: **autoplay-ish playback with no user gesture behind it must start muted**, full stop, regardless of the stored preference. This isn't a library choice, it's the browser enforcing its autoplay-with-sound policy - unmuted `autoplay`/`playWhenInView` without a gesture is blocked or force-muted by the browser itself. This applies to:
142
+
143
+ - `autoplay="true"` set directly on `VideoItem`/`VideoPlayer`.
144
+ - A `playWhenInView` video actually starting once scrolled into view - re-checked at that exact moment (not just once at mount, since a `playWhenInView` player can sit mounted-but-paused for a long time before it actually plays), so if you unmute something else in the meantime, it plays unmuted once it becomes visible instead of forcing itself muted again.
145
+
146
+ That policy is scoped to the current page load, though, not to `localStorage`: once a real gesture has resulted in unmuted playback during this session - a click that happens to land unmuted (see below), or an explicit press of a mute button/volume slider - browsers generally allow further unmuted JS-triggered playback for the rest of it, so the forced-mute rule above stops applying from that point on (a fresh reload resets it - browsers don't know or care what a past session did).
147
+
148
+ A **real user gesture** is exempt from the policy entirely, and always follows the shared preference immediately, even before any gesture-less autoplay would've been allowed to (the gesture itself is what a browser needs, and it's happening right here) - and if that preference happens to be unmuted, this is itself one of the triggers above that lifts the forced-mute rule for the rest of the session, no explicit mute-button press required:
149
+
150
+ - Clicking a lazy `VideoItem`'s placeholder for the first time.
151
+ - `VideoStage`'s idle-click-to-resume and `video-toggle` window event.
152
+
153
+ **`VideoStage`'s playlist skip/auto-advance is the one exception to "follow the shared preference"**: `playNext`/`playPrevious` carry the _outgoing_ video's own live mute/volume state forward to the next one, rather than the shared preference. This is the feed convention (TikTok/Reels-style), not the single-video-click convention: within one continuous playlist, audio should stick to whatever's already playing - skipping past a video you never unmuted shouldn't spontaneously turn sound on just because nothing's ever been saved globally, and skipping past one you did unmute shouldn't silently mute the next one either.
154
+
155
+ An explicit `muted`/`volume` set on a specific `VideoItem`/`VideoPlayer` (or a specific playlist `VideoEntry`) always wins over all of the above, in every case.
156
+
99
157
  ### Platform URLs
100
158
 
101
159
  The platform is detected automatically from the shape of `videoUrl`; there's no separate prop to set it.
@@ -111,6 +169,45 @@ The platform is detected automatically from the shape of `videoUrl`; there's no
111
169
 
112
170
  \* `PLAYER_ID_EMBED` is one path segment: `{PLAYER_ID}_{EMBED_NAME}` (e.g. `abc123_default` for the account's default player), which is exactly the URL Brightcove Studio's "Publish" panel gives you for an embed.
113
171
 
172
+ ### Adding a custom platform
173
+
174
+ `registerPlatform` teaches the player about a platform beyond the six above, without forking the package:
175
+
176
+ ```ts
177
+ import { registerPlatform } from '@munsonlabs/video-player'
178
+
179
+ registerPlatform({
180
+ key: 'acme',
181
+ test: (url) => url.includes('acme.tv'),
182
+ embed: true, // true: the platform has its own SDK/iframe; false: it resolves to a plain playable file
183
+ createAdapter: (videoEl, options) => createAcmeAdapter(videoEl, options),
184
+ })
185
+ ```
186
+
187
+ Call it once, before mounting any player that might see the new URL - resolution reads the registry fresh every time, so ordering (not caching) is the only thing that matters.
188
+
189
+ **Embed** (`embed: true`) - the platform owns its own player (YouTube, Twitch, Vimeo). `createAdapter` is a factory returning a full `PlaybackAdapter`: every method the player needs (`play`/`pause`/`currentTime`/captions/quality/PiP/fullscreen/`on`/`off`/`dispose`), translating your SDK's own events into the ones the player listens for (`play`, `pause`, `ended`, `timeupdate`, `durationchange`, etc.).
190
+
191
+ **Source** (`embed: false`) - the platform just hosts a file/manifest behind an opaque URL or ID (JW Player, Brightcove). `resolveSource` (optional - skip it if the URL is already a direct, playable link) is a function returning `{ src, type?, poster?, adTagUrl? }`; the library's own native `<video>`/hls.js/dash.js path handles playback for you, nothing else to implement.
192
+
193
+ `registerPlatform` is `registerMatcher` + `registerEmbedAdapter`/`registerSourceResolver` in one call - each is exported separately too, for the rare case you only need one (e.g. adding a resolver to a platform something else already registered a matcher for).
194
+
195
+ This works identically from the [web component bundles](#web-component-usage) - see [Registering a platform from a web component](#registering-a-platform-from-a-web-component) for the two extra things worth knowing there (a timing subtlety around `customElements.define()`, and the `?defer` import mode that sidesteps it for statically-declared tags).
196
+
197
+ ### How a URL becomes a playing embed
198
+
199
+ What happens between setting `video-url` and an embed (YouTube/Vimeo/Dailymotion/a custom platform) actually appearing on screen, end to end:
200
+
201
+ 1. **Platform detection.** On mount, `usePlayer` calls `resolvePlatform(videoUrl)`, which checks the URL against every registered matcher (the six built-ins plus anything added via `registerPlatform`) and returns a platform key plus whether it's `embed` or a plain source.
202
+ 2. **Adapter construction.** That result goes to `mountAdapter`, which either resolves a source URL and builds a native `<video>`/hls.js/dash.js adapter, or - for embeds - looks up the platform's registered factory (e.g. `createYoutubeAdapter`) and calls it.
203
+ 3. **Hidden mount.** The embed factory calls `createEmbedMount`, which inserts a wrapper `<div>` next to the `<video>` element and starts it at `opacity: 0; pointer-events: none`. The `<video>` (showing its `poster`) stays the visible thing for now - this is what masks the embed SDK's own iframe loading chrome (spinners, its own poster flash) until the SDK is actually ready. The adapter's `el` is this wrapper, not the `<video>` itself (unlike the native path, where `el` _is_ the `<video>`).
204
+ 4. **SDK boot + event translation.** The factory loads the platform's SDK (or reuses it if another instance already has), builds the player inside the wrapper, and translates the SDK's own events into the common set every adapter emits (`play`, `pause`, `timeupdate`, `durationchange`, etc.).
205
+ 5. **Wiring.** Back in `usePlayer`, `finalizeAdapter` stores the adapter and calls `attachPlayerEvents`, which subscribes all the reactive player state (`isPlaying`, `current`, `supportsCaptions`, ...) to those translated events.
206
+ 6. **Reveal.** Once the adapter actually starts playing for the first time (`hasStarted` flips true), a `watch` swaps visibility: the `<video>` is hidden and the wrapper fades to `opacity: 1` with pointer events restored - this is the moment the embed becomes the visible thing.
207
+ 7. **Teardown.** On unmount, the adapter's `dispose()` removes the wrapper, restores the `<video>` element's normal display, and detaches the platform's own event listeners.
208
+
209
+ The native (non-embed) path skips steps 3 and 6 entirely - the `<video>` element is the adapter's `el` from the start, so there's nothing separate to reveal.
210
+
114
211
  ---
115
212
 
116
213
  ## Headless Controls
@@ -133,6 +230,7 @@ import {
133
230
  Scrubber,
134
231
  VolumeSlider,
135
232
  TimeDisplay,
233
+ Transcript,
136
234
  } from '@munsonlabs/video-player'
137
235
  ```
138
236
 
@@ -162,6 +260,29 @@ Or, `<label for>`-style, skip the ref and point at an element id instead:
162
260
 
163
261
  `player` and `for` are both optional - if both are given, `player` wins. Each button's own CSS uses `:where()` (zero specificity), so a single class you add always wins, and most expose their state via a scoped slot for full custom markup (e.g. `PlayButton`'s `#default="{ isPlaying }"`). See [Web Component Usage](#web-component-usage) for using these as raw custom elements (`<muns-controls-play-button>` etc.) outside Vue.
164
262
 
263
+ ### Transcript
264
+
265
+ `Transcript` renders a clickable transcript for the linked player: pass `cues` as `{ time, end?, text }[]` (times in seconds), clicking a cue seeks to its timestamp (starting playback first if paused), and the cue at the playhead is highlighted and kept scrolled into view as playback progresses:
266
+
267
+ ```vue
268
+ <VideoPlayer id="my-player" video-url="..." />
269
+ <Transcript
270
+ for="my-player"
271
+ :cues="[
272
+ { time: 0, text: 'Welcome back to the show.' },
273
+ { time: 12, text: 'Today we look at the new release.' },
274
+ { time: 47, end: 60, text: 'Here is the demo.' },
275
+ ]"
276
+ />
277
+ ```
278
+
279
+ - Unlike captions/quality, this works on **every** platform (YouTube/Vimeo/Dailymotion included) - it only needs the current time and `seek`, which every adapter has.
280
+ - `end` is optional: when set, nothing is highlighted between that cue's `end` and the next cue's start (a silence/music gap); when omitted, a cue stays highlighted until the next one starts.
281
+ - Auto-scroll pauses while the pointer is over the list, so it never fights the user's own scrolling.
282
+ - A scoped slot customises each cue's markup: `#default="{ cue, index, isActive, formatTime }"`.
283
+ - As a custom element (`<muns-controls-transcript>`), pass cues as an inline JSON string attribute: `cues='[{"time":0,"text":"..."}]'`.
284
+ - Clicking a cue before the video has loaded (a lazy `VideoItem`, an unstarted player) starts playback instead - jumping needs the duration, which isn't known yet at that point.
285
+
165
286
  ### Building your own wrapper component
166
287
 
167
288
  `useForwardedPlayer` is what `VideoItem`/`VideoStage` themselves use to forward a template-ref'd `VideoPlayer`'s controls/state onto their own `defineExpose` - the same mechanism is available for building a custom wrapper component of your own:
@@ -212,6 +333,8 @@ interface StateChangeEvent {
212
333
  | 'thirdQuartile'
213
334
  | 'controlsopen'
214
335
  | 'controlsclose'
336
+ | 'stageopen'
337
+ | 'stageclose'
215
338
  | 'bufferstart'
216
339
  | 'bufferend'
217
340
  | 'timeupdate'
@@ -235,6 +358,8 @@ interface StateChangeEvent {
235
358
 
236
359
  `controlsopen` / `controlsclose` fire when the expanded controls popup mounts/unmounts (e.g. via the "show controls" button), with `element` set to the popup's root DOM node: handy for positioning your own UI relative to it, or measuring it. On `controlsclose`, `element` is a snapshot of the closing node; it's detached from the DOM immediately after.
237
360
 
361
+ `stageopen` / `stageclose` fire from `VideoStage` only, when the stage mounts its inner player (the first video arrives) and when it tears it down again. Like `controlsopen`/`controlsclose`, they arrive on the same `state-change` stream rather than as a separate event.
362
+
238
363
  `captionchange` / `qualitychange` fire on every `setCaptionTrack()`/`setQuality()` call (whichever menu triggered it) and whenever the adapter detects the active track/level changed on its own (e.g. hls.js's/dash.js's own ABR switching), but never before playback has started (so the initial caption/quality detection at mount doesn't get reported as a "change"). See [Captions](#captions-webvtt) and [Video Quality](#video-quality-hls--dash).
239
364
 
240
365
  `tap` fires whenever the full-video tap-to-reveal-controls overlay is tapped/clicked (see `disableTapCapture`), regardless of `controls`. With the built-in HUD (`controls: true`) this is the same gesture that reveals it; with `controls: false` it's the only signal a headless consumer gets for "the user tapped the video", useful for showing/hiding your own custom HUD in response.
@@ -512,6 +637,8 @@ Three bundles are available: pick exactly one, since importing more than one dou
512
637
 
513
638
  The `core`/`controls` bundles leave styling entirely up to you: defer the import, swap in your own stylesheet, or skip it if you're providing your own styles. Only the combined `element` bundle is zero-config.
514
639
 
640
+ `/element` and `/element/core` (not `/element/controls`, which never touches platform code) each dynamically `import()` a platform's own adapter code the first time a URL for that platform actually mounts, landing in a sibling `chunks/` directory rather than the main file - a page that only ever plays plain MP4/HLS/DASH downloads none of it. Loading from a directory-serving CDN (unpkg, jsdelivr, esm.sh) needs no special handling; self-hosting either bundle means deploying its `chunks/` directory alongside it.
641
+
515
642
  ```html
516
643
  <script type="importmap">
517
644
  {
@@ -553,6 +680,7 @@ Core (in `/element` and `/element/core`):
553
680
  | `<muns-video-stage>` | `<VideoStage>` |
554
681
  | `<muns-video-player>` | `<VideoPlayer>` |
555
682
  | `<muns-video-placeholder>` | `<VideoPlaceholder>` |
683
+ | `<muns-hide-marker>` | `<HideMarker>` |
556
684
 
557
685
  Controls (in `/element` and `/element/controls`), see [Headless Controls](#headless-controls) for what each does:
558
686
 
@@ -570,6 +698,7 @@ Controls (in `/element` and `/element/controls`), see [Headless Controls](#headl
570
698
  | `<muns-controls-scrubber>` | `<Scrubber>` |
571
699
  | `<muns-controls-volume-slider>` | `<VolumeSlider>` |
572
700
  | `<muns-controls-time-display>` | `<TimeDisplay>` |
701
+ | `<muns-controls-transcript>` | `<Transcript>` |
573
702
 
574
703
  ### Passing objects as web component attributes
575
704
 
@@ -605,6 +734,40 @@ player.togglePlay()
605
734
  console.log(player.isPlaying)
606
735
  ```
607
736
 
737
+ ### Registering a platform from a web component
738
+
739
+ [`registerPlatform`](#adding-a-custom-platform) is exported from `/element` and `/element/core` too:
740
+
741
+ ```html
742
+ <script type="module">
743
+ import { registerPlatform } from 'https://esm.sh/@munsonlabs/video-player/element/core'
744
+ registerPlatform({ key: 'acme', test: (url) => url.includes('acme.tv'), embed: true, createAdapter: createAcmeAdapter })
745
+
746
+ const player = document.createElement('muns-video-player')
747
+ player.setAttribute('video-url', 'https://acme.tv/watch/123')
748
+ document.body.append(player)
749
+ </script>
750
+ ```
751
+
752
+ One thing worth knowing that doesn't come up in the Vue case - **timing**: importing `/element`/`/element/core` calls `customElements.define()`, which synchronously upgrades any matching tag already sitting in the DOM as part of that same call - and a `<script type="module">` defers until after the whole document has been parsed, so a _statically-declared_ `<muns-video-player>` tag is already sitting in the DOM by the time your script runs, and gets upgraded (running `usePlayer`'s adapter resolution) as soon as the import above evaluates, before your own `registerPlatform` call on the next line has a chance to run. Creating the tag from script, after registering, as above sidesteps this entirely.
753
+
754
+ If your tags are statically declared in the markup (so you can't create them after registering), load `/element/core` with a **`?defer`** query instead: it skips the automatic `customElements.define()` on import, so you register your platform first and then call the exported `defineElements()` yourself - the static tags upgrade at that point, with your platform already in the registry:
755
+
756
+ ```html
757
+ <script type="module">
758
+ import { registerPlatform, defineElements } from 'https://esm.sh/@munsonlabs/video-player/element/core?defer'
759
+ registerPlatform({ key: 'acme', test: (url) => url.includes('acme.tv'), embed: true, createAdapter: createAcmeAdapter })
760
+ defineElements()
761
+ </script>
762
+
763
+ <muns-video-player video-url="https://acme.tv/watch/123"></muns-video-player>
764
+ ```
765
+
766
+ - `?defer` is read from the `/element/core` module's own URL, so import `/element/core` directly with the query (or point an import-map entry at a URL that includes it). The combined `/element` bundle always registers immediately - it imports the core module internally without the query.
767
+ - `defineElements()` is idempotent: it only defines whichever tags aren't already registered, so calling it when the elements were already defined is a no-op rather than a double-registration error.
768
+
769
+ Note this requires an `import` from wherever `/element`/`/element/core` is loaded - there's no way to reach the registry from a script that doesn't (or can't) import the package itself.
770
+
608
771
  ---
609
772
 
610
773
  ## Peer Dependencies
@@ -0,0 +1 @@
1
+ import{c as e,d as t,f as n}from"./constants-DRD0PsRw.mjs";import{t as r}from"./loadScript-Du6JsTc2.mjs";function i(){return window.google?.ima?Promise.resolve():r(e,`ima`)}function a(e,r,a,o){let s=document.createElement(`div`);s.className=`ima-ad-container`,e.appendChild(s);let c=a,l=null,u=null,d=null,f=!1,p=!1,m=!1,h=!1,g=!1,_=!1,v=1,y=new ResizeObserver(([e])=>{let t=window.google?.ima;if(!d||!t)return;let{width:n,height:r}=e.contentRect;d.resize(n,r,t.ViewMode.NORMAL)});y.observe(r);function b(){u?.contentComplete()}function x(r){h=r,e.classList.toggle(n,r),r||(g=!1,e.classList.remove(t))}function S(){if(f||!p||!m||!l||!u||!c)return;f=!0;let e=window.google?.ima;if(!e)return;l.initialize();let t=new e.AdsRequest;t.adTagUrl=c,u.requestAds(t)}function C(e){c=e,S()}i().then(()=>{if(_)return;let n=window.google?.ima;n&&(l=new n.AdDisplayContainer(s,r),u=new n.AdsLoader(l),p=!0,u.addEventListener(n.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,i=>{if(_)return;let a=new n.AdsRenderingSettings;a.restoreCustomPlaybackStateOnAdBreakComplete=!0,d=i.getAdsManager(r,a),r.addEventListener(`ended`,b),d.addEventListener(n.AdEvent.Type.CONTENT_PAUSE_REQUESTED,()=>{r.removeEventListener(`ended`,b),r.pause(),x(!0),o.onAdStart();let e=d?.getVolume()??1;e>0&&(v=e),o.onAdMuteChange(e===0)}),d.addEventListener(n.AdEvent.Type.CONTENT_RESUME_REQUESTED,()=>{r.addEventListener(`ended`,b),x(!1),o.onAdEnd(),r.ended||r.play()}),d.addEventListener(n.AdEvent.Type.PAUSED,()=>{g=!0,e.classList.add(t),o.onAdPauseChange(!0)}),d.addEventListener(n.AdEvent.Type.RESUMED,()=>{g=!1,e.classList.remove(t),o.onAdPauseChange(!1)}),d.addEventListener(n.AdEvent.Type.AD_PROGRESS,()=>{o.onAdProgress(d?.getRemainingTime()??0)}),d.addEventListener(n.AdErrorEvent.Type.AD_ERROR,e=>{x(!1),o.onError(e.getError().getMessage()),r.play()});try{d.init(r.clientWidth,r.clientHeight,n.ViewMode.NORMAL),d.start()}catch(e){o.onError(e instanceof Error?e.message:`Ad playback failed to start.`)}}),u.addEventListener(n.AdErrorEvent.Type.AD_ERROR,e=>{o.onError(e.getError().getMessage())}),S())}).catch(e=>o.onError(e.message));function w(){m=!0,S()}function T(){if(!d)return;let e=d.getVolume();e>0?(v=e,d.setVolume(0)):d.setVolume(v||1),o.onAdMuteChange(d.getVolume()===0)}return{isAdPlaying:()=>h,isAdPaused:()=>g,requestAdsOnFirstPlay:w,setAdTagUrl:C,pauseAd:()=>d?.pause(),resumeAd:()=>d?.resume(),toggleAdMute:T,dispose:()=>{_=!0,y.disconnect(),r.removeEventListener(`ended`,b),d?.destroy(),u?.destroy(),s.remove(),e.classList.remove(n,t)}}}export{a as attachAds};
@@ -0,0 +1 @@
1
+ import{n as e,t}from"./constants-DRD0PsRw.mjs";import{n,t as r}from"./sourceHelpers-DlkCZiTJ.mjs";function i(e){let t;try{t=new URL(e)}catch{return null}if(t.hostname!==`players.brightcove.net`)return null;let[,n,r]=t.pathname.split(`/`),i=t.searchParams.get(`videoId`),a=r?.indexOf(`_`)??-1;return!n||a===-1||!i?null:{accountId:n,playerId:r.slice(0,a),embed:r.slice(a+1),videoId:i}}function a(e){for(let t of e?.plugins??[]){let e=t.options?.serverUrl??t.options?.imaOptions?.serverUrl;if(e)return e}return null}const o=r(async(t,n,r,i)=>{let o=await fetch(`${e}/${t}/${n}_${r}/config.json`);if(!o.ok)throw Error(`Brightcove: could not load player config (${o.status})`);let s=await o.json(),c=i??s?.video_cloud?.policy_key;if(!c)throw Error(`Brightcove: policy_key not found in player config`);return{policyKey:c,adTagUrl:a(s)}},(e,t,n)=>`${e}/${t}_${n}`);async function s(e,r,i){let a=await fetch(`${t}/${e}/videos/${r}`,{headers:{Accept:`application/json;pk=${i}`}});if(!a.ok)throw Error(`Brightcove Playback API error: ${a.status}`);let o=await a.json(),s=n(o.sources||[]);if(!s.length)throw Error(`Brightcove: no playable sources found`);return{sources:s.map(e=>({src:e.src,type:e.type})),poster:o.poster??o.thumbnail??null}}async function c(e,t){let n=i(e);if(!n)throw Error(`Brightcove: invalid src — expected a Brightcove embed URL, e.g. "https://players.brightcove.net/{accountId}/{playerId}_{embed}/index.html?videoId={videoId}"`);let{accountId:r,playerId:a,embed:c,videoId:l}=n,{policyKey:u,adTagUrl:d}=await o(r,a,c,t),{sources:f,poster:p}=await s(r,l,u);return{...f[0],poster:p,adTagUrl:d}}export{c as resolveSource};
@@ -0,0 +1 @@
1
+ const e=`video-select`,t=`video-toggle`,n=`video-state`,r=`fullscreen-pending`,i=`fullscreen-pending-done`,a=`player:positions`,o=`player:autoAdvance`,s=`player:audio`,c={muted:!1,volume:1},l=`mvp-tech`,u=`mvp-youtube`,d=`mvp-vimeo`,f=`mvp-dailymotion`,p=`mvp-ad-playing`,m=`mvp-ad-paused`,h=`16:9`,g=`application/x-mpegURL`,_=`application/dash+xml`,v=`video/mp4`,y=[g,v],b=[.5,.75,1,1.25,1.5,2],x=3500,S=.1,C=3e3,w=[[.25,`firstQuartile`],[.5,`midpoint`],[.75,`thirdQuartile`]],T=`https://imasdk.googleapis.com/js/sdkloader/ima3.js`,E=`https://player.vimeo.com/api/player.js`,D=`https://cdn.jwplayer.com/v2/media`,O=`https://edge.api.brightcove.com/playback/v1/accounts`,k=`https://players.brightcove.net`;export{t as A,y as C,E as D,a as E,e as O,C as S,o as T,d as _,c as a,b,T as c,m as d,p as f,l as g,i as h,h as i,n as k,D as l,r as m,k as n,g as o,f as p,_ as r,x as s,O as t,v as u,u as v,s as w,w as x,S as y};
@@ -0,0 +1 @@
1
+ import{p as e}from"./constants-DRD0PsRw.mjs";import{r as t}from"./embedShared-B1B7ZH_3.mjs";import{t as n}from"./loadScript-Du6JsTc2.mjs";function r(e){let t=e.match(/[?&]video=([a-zA-Z0-9]+)/);return t?t[1]:e.match(/(?:dailymotion\.com\/(?:embed\/)?video\/|dai\.ly\/)([a-zA-Z0-9]+)/)?.[1]??null}function i(i,a){let o=null;return t(i,a,{cssClass:e,connect:async({techId:e,emitter:t,state:i,isDisposed:s,consumeQueuedPlay:c})=>{let l=r(a.src);if(!l){i.errorState={code:4,message:`Could not parse video ID from source URL`},t.trigger(`error`);return}let u=!1;try{let r=typeof a.customVars?.playerId==`string`?a.customVars.playerId:void 0,d=await n(r?`https://geo.dailymotion.com/libs/player/${r}.js`:`https://geo.dailymotion.com/libs/player.js`,r||`dailymotion-sdk`).then(()=>window.dailymotion);if(!d||s())return;let f=await d.createPlayer(e,{...r&&{player:r},video:l,params:{autoplay:!!a.autoplay,mute:!!a.muted}});o=f,a.volume!==void 0&&f.setVolume(a.volume);let p=d.events;c(()=>o?.play()),f.on(p.PLAYER_CRITICALPATHREADY,e=>{let n=e.videoThumbnails;if(!n)return;let r=Object.keys(n).map(Number).sort((e,t)=>t-e)[0],i=r===void 0?void 0:n[r];i&&t.trigger(`posterchange`,i)}),f.on(p.VIDEO_PLAY,()=>{i.paused=!1,t.trigger(`play`),t.trigger(`playing`),!a.autoplay&&!u&&(u=!0,f.pause())}),f.on(p.VIDEO_PLAYING,()=>{i.paused=!1,t.trigger(`play`),t.trigger(`playing`)}),f.on(p.VIDEO_PAUSE,()=>{i.paused=!0,t.trigger(`pause`)}),p.VIDEO_BUFFERING&&f.on(p.VIDEO_BUFFERING,()=>t.trigger(`waiting`)),f.on(p.VIDEO_END,()=>{i.paused=!0,t.trigger(`ended`)}),f.on(p.VIDEO_TIMECHANGE,e=>{i.currentTime=e.videoTime??i.currentTime,i.duration=e.videoDuration??i.duration,t.trigger(`timeupdate`)}),f.on(p.VIDEO_DURATIONCHANGE,e=>{i.duration=e.videoDuration??i.duration,t.trigger(`durationchange`)}),f.on(p.VIDEO_SEEKSTART,()=>t.trigger(`seeking`)),f.on(p.VIDEO_SEEKEND,e=>{i.currentTime=e.videoTime??i.currentTime,t.trigger(`seeked`)}),f.on(p.PLAYER_VOLUMECHANGE,e=>{i.volume=e.playerVolume??i.volume,i.muted=e.playerIsMuted??i.muted,t.trigger(`volumechange`)}),f.on(p.PLAYER_ERROR,()=>t.trigger(`error`)),p.AD_START&&f.on(p.AD_START,()=>{i.paused=!1,t.trigger(`play`),t.trigger(`adstart`)}),p.AD_END&&f.on(p.AD_END,()=>t.trigger(`adend`))}catch(e){i.errorState={code:4,message:e instanceof Error?e.message:`This video could not be played.`},t.trigger(`error`)}},hasPlayer:()=>!!o,play:()=>o?.play(),pause:()=>o?.pause(),seekToSdk:e=>o?.seek(e),volumeToSdk:e=>o?.setVolume(e),muteToSdk:(e,t)=>o?.setMute(t),sdkFullscreenEnter:()=>o?.setFullscreen(!0),sdkFullscreenExit:()=>o?.setFullscreen(!1),destroyPlayer:()=>{let e=o;o=null,e?.destroy?.()}})}export{i as createDailymotionAdapter};
@@ -0,0 +1 @@
1
+ import{g as e,h as t,m as n}from"./constants-DRD0PsRw.mjs";function r(){return/iPad|iPhone|iPod/.test(navigator.userAgent)||/Mac/.test(navigator.userAgent)&&navigator.maxTouchPoints>1}function i(e){(e.requestFullscreen||e.webkitRequestFullscreen)?.call(e)}function a(){(document.exitFullscreen||document.webkitExitFullscreen)?.call(document)}function o(){let e=new Map;function t(t,n){for(let r of Array.isArray(t)?t:[t])e.has(r)||e.set(r,new Set),e.get(r)?.add(n)}function n(t,n){e.get(t)?.delete(n)}function r(t,...n){e.get(t)?.forEach(e=>e(...n))}function i(){e.clear()}return{on:t,off:n,trigger:r,dispose:i}}const s={supportsCaptions:()=>!1,getCaptionTracks:()=>[],setCaptionTrack:()=>{},getActiveCaptionTrack:()=>null,supportsQuality:()=>!1,getQualityLevels:()=>[],getCurrentQuality:()=>null,isAutoQuality:()=>!0,setQuality:()=>{},supportsPip:()=>!1,isPipActive:()=>!1,togglePip:()=>{}};let c=0;function l(t,n){t.parentElement?.classList.add(n);let r=`${n}-${++c}`,i=document.createElement(`div`);i.id=r,i.className=e,i.style.cssText=`width:100%;height:100%;top:0;left:0;position:absolute`;let a=document.createElement(`div`);return a.style.cssText=`width:100%;height:100%;position:absolute;inset:0;opacity:0;pointer-events:none;transition:opacity 0.2s`,a.appendChild(i),t.parentElement?.insertBefore(a,t),{techId:r,wrapper:a,innerDiv:i}}function u(e,t){e.style.display=`none`,t.style.opacity=`1`,t.style.pointerEvents=``}function d(e,t,n){t.remove(),e.parentElement?.classList.remove(n),e.style.display=``}function f(e){return e.closest(`.player__shell`)}function p(e,t){if(r()&&t()!==!1)return;let n=f(e);n&&i(n)}function m(){a()}function h(){let e=new Set;return{schedule(t,n=0){let r=setTimeout(()=>{e.delete(r),t()},n);e.add(r)},clearAll(){e.forEach(clearTimeout),e.clear()}}}function g(e){e.trigger(n);let r=document.createElement(`div`);r.style.cssText=`position:fixed;inset:0;z-index:99999;opacity:0;pointer-events:none`,document.body.appendChild(r);let i=!1;function a(){i||e.trigger(t)}function o(n){i||(i=!0,e.trigger(t),r.remove(),n?.())}return{overlay:r,reveal:a,finish:o}}function _(e,t,n){let i=o(),{techId:c,wrapper:u}=l(e,n.cssClass),{schedule:f,clearAll:m}=h(),g={currentTime:0,duration:0,volume:t.volume??1,muted:!1,paused:!0,playQueued:!1,errorState:null},_=!1,v={techId:c,wrapper:u,emitter:i,state:g,schedule:f,isDisposed:()=>_,consumeQueuedPlay(e){g.playQueued&&(g.playQueued=!1,e())}};n.connect(v);function y(){p(e,()=>{if(!n.sdkFullscreenEnter)return!1;n.sdkFullscreenEnter()})}function b(){if(r()&&n.sdkFullscreenExit){n.sdkFullscreenExit();return}a()}return{el:u,play:()=>{n.hasPlayer()?n.play():g.playQueued=!0},pause:()=>n.pause(),paused:()=>g.paused,currentTime:()=>g.currentTime,setCurrentTime:e=>{if(n.setCurrentTime){n.setCurrentTime(v,e);return}g.currentTime=e,n.seekToSdk?.(e),i.trigger(`seeking`)},duration:()=>g.duration,volume:()=>g.volume,setVolume:e=>{g.volume=e,n.volumeToSdk(e)},muted:()=>g.muted,setMuted:e=>{g.muted=e,n.muteToSdk(v,e)},...n.rate?n.rate(v):{playbackRate:()=>1,setPlaybackRate:()=>{}},bufferedEnd:()=>g.currentTime,error:()=>g.errorState,setSrc:()=>{},supportsPlaybackRate:()=>!1,...s,enterFullscreen:y,exitFullscreen:b,on:i.on,off:i.off,dispose:()=>{_=!0,m(),n.destroyPlayer(),d(e,u,n.cssClass),i.dispose()}}}export{p as a,u as c,o as d,a as f,h as i,g as l,i as m,l as n,m as o,r as p,_ as r,f as s,s as t,d as u};
@@ -0,0 +1 @@
1
+ import{l as e,o as t,u as n}from"./constants-DRD0PsRw.mjs";import{n as r,t as i}from"./sourceHelpers-DlkCZiTJ.mjs";function a(e){return e.match(/cdn\.jwplayer\.com\/videos\/([^-]+)/)?.[1]??e.match(/cdn\.jwplayer\.com\/manifests\/([^.]+)/)?.[1]??e.match(/^jwplayer:\/\/([^/]+)$/)?.[1]??null}function o(e){let t=e?.advertising?.schedule;return Array.isArray(t)&&t.length?t[0].tag??null:e?.advertising?.tag??null}const s=i(async t=>{let n=await fetch(`${e}/${t}`);if(!n.ok)throw Error(`JW Platform API error: ${n.status}`);let i=(await n.json()).playlist?.[0];if(!i)throw Error(`JW Platform: empty playlist`);let a=r((i.sources??[]).map(e=>({src:e.file,type:e.type})));if(!a.length)throw Error(`JW Platform: no playable sources found`);return{src:a[0].src,type:a[0].type,poster:i.image??null,adTagUrl:o(i)}});async function c(e){let r=a(e);if(!r)throw Error(`JW Platform: unrecognised source URL: ${e}`);let i=await s(r);if(e.startsWith(`jwplayer://`))return i;let o=/\.mp4(\?|#|$)/.test(e)?n:t;return{...i,src:e,type:o}}export{c as resolveSource};
@@ -0,0 +1 @@
1
+ const e={};function t(t,n=t){return e[n]||(e[n]=new Promise((e,n)=>{let r=document.createElement(`script`);r.src=t,r.onload=()=>e(),r.onerror=()=>n(Error(`Failed to load script: ${t}`)),document.head.appendChild(r)})),e[n]}export{t};
@@ -0,0 +1 @@
1
+ function e(e,t){let n=window.pbjs;if(!n)return Promise.resolve(t);let r=e.timeoutMs??1e3;return new Promise(i=>{let a=!1;function o(e){a||(a=!0,i(e||t))}let s=setTimeout(()=>o(t),r);n.que.push(()=>{try{n.addAdUnits(e.adUnit),n.requestBids({adUnitCodes:[e.adUnit.code],timeout:r,bidsBackHandler:()=>{clearTimeout(s);try{o(n.adServers?.gam?.buildVideoUrl({adUnit:e.adUnit,params:e.params}))}catch{o(t)}}})}catch{clearTimeout(s),o(t)}})})}export{e as resolveHeaderBiddingAdTagUrl};
@@ -0,0 +1 @@
1
+ import{C as e}from"./constants-DRD0PsRw.mjs";function t(e,t=(...e)=>String(e[0])){let n={};return async(...r)=>{let i=t(...r);if(n[i])return n[i];let a=await e(...r);return n[i]=a,a}}function n(t){return t.filter(t=>t.src&&e.includes(t.type)).sort((t,n)=>e.indexOf(t.type)-e.indexOf(n.type))}export{n,t};
@@ -0,0 +1 @@
1
+ import{D as e,_ as t}from"./constants-DRD0PsRw.mjs";import{r as n}from"./embedShared-B1B7ZH_3.mjs";import{t as r}from"./loadScript-Du6JsTc2.mjs";function i(e){return e.match(/(?:vimeo\.com\/(?:video\/|channels\/[^/]+\/|groups\/[^/]+\/videos\/)?|player\.vimeo\.com\/video\/)(\d+)/)?.[1]??null}function a(a,o){let s=null,c=1;return n(a,o,{cssClass:t,connect:async({techId:t,emitter:n,state:a,isDisposed:c,consumeQueuedPlay:l})=>{let u=i(o.src);if(!u||(await r(e,`vimeo`),c()||!window.Vimeo))return;let d={id:Number(u),byline:!1,portrait:!1,title:!1,transparent:!0,controls:!!o.nativeUi,autopause:!1,...o.autoplay!==void 0&&{autoplay:o.autoplay},...o.muted!==void 0&&{muted:o.muted}};s=new window.Vimeo.Player(t,d),o.autoplay&&(a.playQueued=!0),s.ready().then(()=>{o.muted&&s?.setMuted(!0).catch(()=>{}),o.volume!==void 0&&s?.setVolume(o.volume).catch(()=>{}),l(()=>void s?.play().catch(()=>{}))}).catch(e=>{a.errorState={code:4,message:e?.message||`This video is unavailable or cannot be embedded here.`},n.trigger(`error`)}),s.on(`play`,()=>{a.paused=!1,n.trigger(`play`),n.trigger(`playing`)}),s.on(`pause`,()=>{a.paused=!0,n.trigger(`pause`)}),s.on(`ended`,()=>{a.paused=!0,n.trigger(`ended`)});let f=!1;s.on(`timeupdate`,e=>{let{seconds:t,duration:r}=e;a.currentTime=t,a.duration=r,n.trigger(`timeupdate`),r&&!f&&(f=!0,n.trigger(`durationchange`))}),s.on(`loaded`,()=>{f=!1,n.trigger(`loadedmetadata`),n.trigger(`durationchange`)}),s.on(`seeking`,e=>{a.currentTime=e.seconds,n.trigger(`seeking`)}),s.on(`seeked`,e=>{a.currentTime=e.seconds,n.trigger(`seeked`),n.trigger(`timeupdate`)}),s.on(`bufferstart`,()=>n.trigger(`waiting`)),s.on(`bufferend`,()=>n.trigger(`canplay`)),s.on(`volumechange`,e=>{a.volume=e.volume,n.trigger(`volumechange`)}),s.on(`error`,()=>n.trigger(`error`))},hasPlayer:()=>!!s,play:()=>void s?.play().catch(()=>{}),pause:()=>void s?.pause().catch(()=>{}),rate:({emitter:e})=>({playbackRate:()=>c,setPlaybackRate:t=>{c=t,s?.setPlaybackRate(t).catch(()=>{}),e.trigger(`ratechange`)}}),setCurrentTime:({emitter:e},t)=>{s?.setCurrentTime(t).catch(()=>{}),e.trigger(`timeupdate`),e.trigger(`seeking`)},volumeToSdk:e=>void s?.setVolume(e).catch(()=>{}),muteToSdk:({emitter:e,schedule:t},n)=>{s?.setMuted(n).then(()=>t(()=>e.trigger(`volumechange`),50)).catch(()=>{})},sdkFullscreenEnter:()=>void s?.requestFullscreen().catch(()=>{}),destroyPlayer:()=>{let e=s;s=null,e?.destroy().catch(()=>{})}})}export{a as createVimeoAdapter};
@@ -0,0 +1 @@
1
+ import{v as e}from"./constants-DRD0PsRw.mjs";import{a as t,d as n,i as r,l as i,n as a,o,t as s,u as c}from"./embedShared-B1B7ZH_3.mjs";import{t as l}from"./loadScript-Du6JsTc2.mjs";function u(e,t){return t===e.PlayerState.PLAYING||t===e.PlayerState.BUFFERING}function d(e){let t={videoId:null,listId:null},n=e.match(/^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|shorts\/|&v=)([^#&?]*).*/);n?.[2]?.length===11&&(t.videoId=n[2]);let r=e.match(/[?&]list=([^#&?]+)/);return r?.[1]&&(t.listId=r[1]),t}let f=!1,p=!1;const m=[];function h(){p||(p=!0,l(`https://www.youtube.com/iframe_api`).then(()=>{window.YT?.ready(()=>{f=!0,m.forEach(e=>e()),m.length=0})}))}function g(l,p){h();let g=n(),{techId:_,wrapper:v}=a(l,e),y=d(p.src),b=null,x=y.videoId,S=!1,C=!1,w=!1,T=null,E=!1,D=null,O=!1,{schedule:k,clearAll:A}=r(),j=null,M={active:!1,wasPaused:!1,timeBefore:0,catchUpInterval:null};function N(){try{let e=b?.getPlayerResponse()?.adPlacements;return Array.isArray(e)&&e.length>0}catch{return!1}}function P(e){b?.loadVideoById({videoId:e})}function F(e){b?.cueVideoById({videoId:e})}function I(){y.videoId&&(M.wasPaused=!1,S?x===y.videoId?b?.playVideo():(P(y.videoId),x=y.videoId):(g.trigger(`waiting`),C=!0))}function L(){M.catchUpInterval&&clearInterval(M.catchUpInterval),M.active=!1,M.wasPaused&&b?.pauseVideo(),g.trigger(`seeked`)}function R(){O=(b?.getAvailablePlaybackRates()??[]).length>1,S=!0,p.muted&&b?.mute(),p.volume!==void 0&&b?.setVolume(p.volume*100),C?I():w&&y.videoId&&(F(y.videoId),x=y.videoId)}function z(e){if(e===T||D!==null)return;T=e;let t=N();t!==E&&(E=t,g.trigger(t?`adstart`:`adend`));let n=window.YT;if(n){switch(e){case-1:g.trigger(`loadstart`),g.trigger(`loadedmetadata`),g.trigger(`durationchange`),g.trigger(`ratechange`);break;case n.PlayerState.ENDED:g.trigger(`ended`);break;case n.PlayerState.PLAYING:g.trigger(`timeupdate`),g.trigger(`durationchange`),g.trigger(`playing`),g.trigger(`play`),M.active&&L();break;case n.PlayerState.PAUSED:g.trigger(`canplay`),M.active||g.trigger(`pause`);break;case n.PlayerState.BUFFERING:g.trigger(`waiting`);break;case n.PlayerState.CUED:g.trigger(`canplay`);break}j&&=(clearInterval(j),null),e===n.PlayerState.PLAYING&&(j=setInterval(()=>g.trigger(`timeupdate`),250))}}function B(){let e={controls:+!!p.nativeUi,modestbranding:1,rel:0,showinfo:0,mute:+!!p.muted,origin:window.location.origin,allowfullscreen:1,fullscreen:1,fs:1,autoplay:0,playsinline:1,...p.customVars};x=y.videoId,b=new window.YT.Player(_,{videoId:x??void 0,playerVars:e,events:{onReady:R,onStateChange:e=>z(e.data),onPlaybackRateChange:()=>g.trigger(`ratechange`),onVolumeChange:()=>g.trigger(`volumechange`),onError:e=>{D=e.data,g.trigger(`error`),k(()=>{D=null})}}})}f?B():m.push(B),p.autoplay?S?I():C=!0:y.videoId&&(w=!0);function V(){if(!b)return;let e=b.getCurrentTime(),{video_id:t}=b.getVideoData();b.pauseVideo();let{overlay:n,reveal:r,finish:a}=i(g),o=document.createElement(`div`);o.id=`yt-fs-${Math.random().toString(36).slice(2)}`,n.appendChild(o);let s=null,c=()=>{document.removeEventListener(`pointerdown`,l,!0),a(()=>{let t=s?.getCurrentTime()??e;try{s?.destroy()}catch{}b?.seekTo(t,!0),g.trigger(`timeupdate`)})};function l(){c()}s=new window.YT.Player(o.id,{videoId:t,playerVars:{playsinline:0,autoplay:0,controls:1,modestbranding:1,rel:0,start:Math.floor(e)},events:{onReady:t=>{r(),t.target.seekTo(e,!0),t.target.playVideo()},onStateChange:e=>{let t=window.YT;t&&(e.data===t.PlayerState.ENDED?c():e.data===t.PlayerState.PAUSED?(document.removeEventListener(`pointerdown`,l,!0),document.addEventListener(`pointerdown`,l,{capture:!0,once:!0})):(document.removeEventListener(`pointerdown`,l,!0),r()))}}})}function H(){t(l,()=>{if(!b)return!1;V()})}return{el:v,play:I,pause:()=>b?.pauseVideo(),paused:()=>{if(!b)return!0;let e=window.YT;return!e||!u(e,T)},currentTime:()=>b?.getCurrentTime()??0,setCurrentTime:e=>{if(!b)return;let t=window.YT;t&&T===t.PlayerState.PAUSED&&(M.timeBefore=b.getCurrentTime()),M.active||(M.wasPaused=!t||!u(t,T)),b.seekTo(e,!0),g.trigger(`timeupdate`),g.trigger(`seeking`),M.active=!0,t&&T===t.PlayerState.PAUSED&&M.timeBefore!==e&&(M.catchUpInterval&&clearInterval(M.catchUpInterval),M.catchUpInterval=setInterval(()=>{T!==t.PlayerState.PAUSED||!M.active?M.catchUpInterval&&clearInterval(M.catchUpInterval):b&&b.getCurrentTime()!==M.timeBefore&&(g.trigger(`timeupdate`),L())},250))},duration:()=>b?.getDuration()??0,volume:()=>b?b.getVolume()/100:1,setVolume:e=>b?.setVolume(e*100),muted:()=>b?.isMuted()??!1,setMuted:e=>{b&&(e?b.mute():b.unMute(),k(()=>g.trigger(`volumechange`),50))},playbackRate:()=>b?.getPlaybackRate()??1,setPlaybackRate:e=>b?.setPlaybackRate(e),bufferedEnd:()=>b?.getVideoLoadedFraction?b.getVideoLoadedFraction()*b.getDuration():0,error:()=>D===null?null:{code:D,message:`This video could not be played.`},setSrc:e=>{let t=d(e);y.videoId=t.videoId,y.listId=t.listId,y.videoId&&(S?(P(y.videoId),x=y.videoId):w=!0)},supportsPlaybackRate:()=>O,...s,enterFullscreen:H,exitFullscreen:o,on:g.on,off:g.off,dispose:()=>{if(A(),j&&clearInterval(j),M.catchUpInterval&&clearInterval(M.catchUpInterval),b)try{b.stopVideo(),b.destroy()}catch{}else{let e=m.indexOf(B);e!==-1&&m.splice(e,1)}b=null,c(l,v,e),g.dispose()}}}export{g as createYoutubeAdapter};
@@ -0,0 +1 @@
1
+ import{c as e,d as t,f as n}from"./constants-DRD0PsRw.mjs";import{t as r}from"./loadScript-Du6JsTc2.mjs";function i(){return window.google?.ima?Promise.resolve():r(e,`ima`)}function a(e,r,a,o){let s=document.createElement(`div`);s.className=`ima-ad-container`,e.appendChild(s);let c=a,l=null,u=null,d=null,f=!1,p=!1,m=!1,h=!1,g=!1,_=!1,v=1,y=new ResizeObserver(([e])=>{let t=window.google?.ima;if(!d||!t)return;let{width:n,height:r}=e.contentRect;d.resize(n,r,t.ViewMode.NORMAL)});y.observe(r);function b(){u?.contentComplete()}function x(r){h=r,e.classList.toggle(n,r),r||(g=!1,e.classList.remove(t))}function S(){if(f||!p||!m||!l||!u||!c)return;f=!0;let e=window.google?.ima;if(!e)return;l.initialize();let t=new e.AdsRequest;t.adTagUrl=c,u.requestAds(t)}function C(e){c=e,S()}i().then(()=>{if(_)return;let n=window.google?.ima;n&&(l=new n.AdDisplayContainer(s,r),u=new n.AdsLoader(l),p=!0,u.addEventListener(n.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED,i=>{if(_)return;let a=new n.AdsRenderingSettings;a.restoreCustomPlaybackStateOnAdBreakComplete=!0,d=i.getAdsManager(r,a),r.addEventListener(`ended`,b),d.addEventListener(n.AdEvent.Type.CONTENT_PAUSE_REQUESTED,()=>{r.removeEventListener(`ended`,b),r.pause(),x(!0),o.onAdStart();let e=d?.getVolume()??1;e>0&&(v=e),o.onAdMuteChange(e===0)}),d.addEventListener(n.AdEvent.Type.CONTENT_RESUME_REQUESTED,()=>{r.addEventListener(`ended`,b),x(!1),o.onAdEnd(),r.ended||r.play()}),d.addEventListener(n.AdEvent.Type.PAUSED,()=>{g=!0,e.classList.add(t),o.onAdPauseChange(!0)}),d.addEventListener(n.AdEvent.Type.RESUMED,()=>{g=!1,e.classList.remove(t),o.onAdPauseChange(!1)}),d.addEventListener(n.AdEvent.Type.AD_PROGRESS,()=>{o.onAdProgress(d?.getRemainingTime()??0)}),d.addEventListener(n.AdErrorEvent.Type.AD_ERROR,e=>{x(!1),o.onError(e.getError().getMessage()),r.play()});try{d.init(r.clientWidth,r.clientHeight,n.ViewMode.NORMAL),d.start()}catch(e){o.onError(e instanceof Error?e.message:`Ad playback failed to start.`)}}),u.addEventListener(n.AdErrorEvent.Type.AD_ERROR,e=>{o.onError(e.getError().getMessage())}),S())}).catch(e=>o.onError(e.message));function w(){m=!0,S()}function T(){if(!d)return;let e=d.getVolume();e>0?(v=e,d.setVolume(0)):d.setVolume(v||1),o.onAdMuteChange(d.getVolume()===0)}return{isAdPlaying:()=>h,isAdPaused:()=>g,requestAdsOnFirstPlay:w,setAdTagUrl:C,pauseAd:()=>d?.pause(),resumeAd:()=>d?.resume(),toggleAdMute:T,dispose:()=>{_=!0,y.disconnect(),r.removeEventListener(`ended`,b),d?.destroy(),u?.destroy(),s.remove(),e.classList.remove(n,t)}}}export{a as attachAds};
@@ -0,0 +1 @@
1
+ import{n as e,t}from"./constants-DRD0PsRw.mjs";import{n,t as r}from"./sourceHelpers-DlkCZiTJ.mjs";function i(e){let t;try{t=new URL(e)}catch{return null}if(t.hostname!==`players.brightcove.net`)return null;let[,n,r]=t.pathname.split(`/`),i=t.searchParams.get(`videoId`),a=r?.indexOf(`_`)??-1;return!n||a===-1||!i?null:{accountId:n,playerId:r.slice(0,a),embed:r.slice(a+1),videoId:i}}function a(e){for(let t of e?.plugins??[]){let e=t.options?.serverUrl??t.options?.imaOptions?.serverUrl;if(e)return e}return null}const o=r(async(t,n,r,i)=>{let o=await fetch(`${e}/${t}/${n}_${r}/config.json`);if(!o.ok)throw Error(`Brightcove: could not load player config (${o.status})`);let s=await o.json(),c=i??s?.video_cloud?.policy_key;if(!c)throw Error(`Brightcove: policy_key not found in player config`);return{policyKey:c,adTagUrl:a(s)}},(e,t,n)=>`${e}/${t}_${n}`);async function s(e,r,i){let a=await fetch(`${t}/${e}/videos/${r}`,{headers:{Accept:`application/json;pk=${i}`}});if(!a.ok)throw Error(`Brightcove Playback API error: ${a.status}`);let o=await a.json(),s=n(o.sources||[]);if(!s.length)throw Error(`Brightcove: no playable sources found`);return{sources:s.map(e=>({src:e.src,type:e.type})),poster:o.poster??o.thumbnail??null}}async function c(e,t){let n=i(e);if(!n)throw Error(`Brightcove: invalid src — expected a Brightcove embed URL, e.g. "https://players.brightcove.net/{accountId}/{playerId}_{embed}/index.html?videoId={videoId}"`);let{accountId:r,playerId:a,embed:c,videoId:l}=n,{policyKey:u,adTagUrl:d}=await o(r,a,c,t),{sources:f,poster:p}=await s(r,l,u);return{...f[0],poster:p,adTagUrl:d}}export{c as resolveSource};
@@ -0,0 +1 @@
1
+ const e=`video-select`,t=`video-toggle`,n=`video-state`,r=`fullscreen-pending`,i=`fullscreen-pending-done`,a=`player:positions`,o=`player:autoAdvance`,s=`player:audio`,c={muted:!1,volume:1},l=`mvp-tech`,u=`mvp-youtube`,d=`mvp-vimeo`,f=`mvp-dailymotion`,p=`mvp-ad-playing`,m=`mvp-ad-paused`,h=`16:9`,g=`application/x-mpegURL`,_=`application/dash+xml`,v=`video/mp4`,y=[g,v],b=[.5,.75,1,1.25,1.5,2],x=3500,S=.1,C=3e3,w=[[.25,`firstQuartile`],[.5,`midpoint`],[.75,`thirdQuartile`]],T=`https://imasdk.googleapis.com/js/sdkloader/ima3.js`,E=`https://player.vimeo.com/api/player.js`,D=`https://cdn.jwplayer.com/v2/media`,O=`https://edge.api.brightcove.com/playback/v1/accounts`,k=`https://players.brightcove.net`;export{t as A,y as C,E as D,a as E,e as O,C as S,o as T,d as _,c as a,b,T as c,m as d,p as f,l as g,i as h,h as i,n as k,D as l,r as m,k as n,g as o,f as p,_ as r,x as s,O as t,v as u,u as v,s as w,w as x,S as y};
@@ -0,0 +1 @@
1
+ import{p as e}from"./constants-DRD0PsRw.mjs";import{r as t}from"./embedShared-B1B7ZH_3.mjs";import{t as n}from"./loadScript-Du6JsTc2.mjs";function r(e){let t=e.match(/[?&]video=([a-zA-Z0-9]+)/);return t?t[1]:e.match(/(?:dailymotion\.com\/(?:embed\/)?video\/|dai\.ly\/)([a-zA-Z0-9]+)/)?.[1]??null}function i(i,a){let o=null;return t(i,a,{cssClass:e,connect:async({techId:e,emitter:t,state:i,isDisposed:s,consumeQueuedPlay:c})=>{let l=r(a.src);if(!l){i.errorState={code:4,message:`Could not parse video ID from source URL`},t.trigger(`error`);return}let u=!1;try{let r=typeof a.customVars?.playerId==`string`?a.customVars.playerId:void 0,d=await n(r?`https://geo.dailymotion.com/libs/player/${r}.js`:`https://geo.dailymotion.com/libs/player.js`,r||`dailymotion-sdk`).then(()=>window.dailymotion);if(!d||s())return;let f=await d.createPlayer(e,{...r&&{player:r},video:l,params:{autoplay:!!a.autoplay,mute:!!a.muted}});o=f,a.volume!==void 0&&f.setVolume(a.volume);let p=d.events;c(()=>o?.play()),f.on(p.PLAYER_CRITICALPATHREADY,e=>{let n=e.videoThumbnails;if(!n)return;let r=Object.keys(n).map(Number).sort((e,t)=>t-e)[0],i=r===void 0?void 0:n[r];i&&t.trigger(`posterchange`,i)}),f.on(p.VIDEO_PLAY,()=>{i.paused=!1,t.trigger(`play`),t.trigger(`playing`),!a.autoplay&&!u&&(u=!0,f.pause())}),f.on(p.VIDEO_PLAYING,()=>{i.paused=!1,t.trigger(`play`),t.trigger(`playing`)}),f.on(p.VIDEO_PAUSE,()=>{i.paused=!0,t.trigger(`pause`)}),p.VIDEO_BUFFERING&&f.on(p.VIDEO_BUFFERING,()=>t.trigger(`waiting`)),f.on(p.VIDEO_END,()=>{i.paused=!0,t.trigger(`ended`)}),f.on(p.VIDEO_TIMECHANGE,e=>{i.currentTime=e.videoTime??i.currentTime,i.duration=e.videoDuration??i.duration,t.trigger(`timeupdate`)}),f.on(p.VIDEO_DURATIONCHANGE,e=>{i.duration=e.videoDuration??i.duration,t.trigger(`durationchange`)}),f.on(p.VIDEO_SEEKSTART,()=>t.trigger(`seeking`)),f.on(p.VIDEO_SEEKEND,e=>{i.currentTime=e.videoTime??i.currentTime,t.trigger(`seeked`)}),f.on(p.PLAYER_VOLUMECHANGE,e=>{i.volume=e.playerVolume??i.volume,i.muted=e.playerIsMuted??i.muted,t.trigger(`volumechange`)}),f.on(p.PLAYER_ERROR,()=>t.trigger(`error`)),p.AD_START&&f.on(p.AD_START,()=>{i.paused=!1,t.trigger(`play`),t.trigger(`adstart`)}),p.AD_END&&f.on(p.AD_END,()=>t.trigger(`adend`))}catch(e){i.errorState={code:4,message:e instanceof Error?e.message:`This video could not be played.`},t.trigger(`error`)}},hasPlayer:()=>!!o,play:()=>o?.play(),pause:()=>o?.pause(),seekToSdk:e=>o?.seek(e),volumeToSdk:e=>o?.setVolume(e),muteToSdk:(e,t)=>o?.setMute(t),sdkFullscreenEnter:()=>o?.setFullscreen(!0),sdkFullscreenExit:()=>o?.setFullscreen(!1),destroyPlayer:()=>{let e=o;o=null,e?.destroy?.()}})}export{i as createDailymotionAdapter};
@@ -0,0 +1 @@
1
+ import{g as e,h as t,m as n}from"./constants-DRD0PsRw.mjs";function r(){return/iPad|iPhone|iPod/.test(navigator.userAgent)||/Mac/.test(navigator.userAgent)&&navigator.maxTouchPoints>1}function i(e){(e.requestFullscreen||e.webkitRequestFullscreen)?.call(e)}function a(){(document.exitFullscreen||document.webkitExitFullscreen)?.call(document)}function o(){let e=new Map;function t(t,n){for(let r of Array.isArray(t)?t:[t])e.has(r)||e.set(r,new Set),e.get(r)?.add(n)}function n(t,n){e.get(t)?.delete(n)}function r(t,...n){e.get(t)?.forEach(e=>e(...n))}function i(){e.clear()}return{on:t,off:n,trigger:r,dispose:i}}const s={supportsCaptions:()=>!1,getCaptionTracks:()=>[],setCaptionTrack:()=>{},getActiveCaptionTrack:()=>null,supportsQuality:()=>!1,getQualityLevels:()=>[],getCurrentQuality:()=>null,isAutoQuality:()=>!0,setQuality:()=>{},supportsPip:()=>!1,isPipActive:()=>!1,togglePip:()=>{}};let c=0;function l(t,n){t.parentElement?.classList.add(n);let r=`${n}-${++c}`,i=document.createElement(`div`);i.id=r,i.className=e,i.style.cssText=`width:100%;height:100%;top:0;left:0;position:absolute`;let a=document.createElement(`div`);return a.style.cssText=`width:100%;height:100%;position:absolute;inset:0;opacity:0;pointer-events:none;transition:opacity 0.2s`,a.appendChild(i),t.parentElement?.insertBefore(a,t),{techId:r,wrapper:a,innerDiv:i}}function u(e,t){e.style.display=`none`,t.style.opacity=`1`,t.style.pointerEvents=``}function d(e,t,n){t.remove(),e.parentElement?.classList.remove(n),e.style.display=``}function f(e){return e.closest(`.player__shell`)}function p(e,t){if(r()&&t()!==!1)return;let n=f(e);n&&i(n)}function m(){a()}function h(){let e=new Set;return{schedule(t,n=0){let r=setTimeout(()=>{e.delete(r),t()},n);e.add(r)},clearAll(){e.forEach(clearTimeout),e.clear()}}}function g(e){e.trigger(n);let r=document.createElement(`div`);r.style.cssText=`position:fixed;inset:0;z-index:99999;opacity:0;pointer-events:none`,document.body.appendChild(r);let i=!1;function a(){i||e.trigger(t)}function o(n){i||(i=!0,e.trigger(t),r.remove(),n?.())}return{overlay:r,reveal:a,finish:o}}function _(e,t,n){let i=o(),{techId:c,wrapper:u}=l(e,n.cssClass),{schedule:f,clearAll:m}=h(),g={currentTime:0,duration:0,volume:t.volume??1,muted:!1,paused:!0,playQueued:!1,errorState:null},_=!1,v={techId:c,wrapper:u,emitter:i,state:g,schedule:f,isDisposed:()=>_,consumeQueuedPlay(e){g.playQueued&&(g.playQueued=!1,e())}};n.connect(v);function y(){p(e,()=>{if(!n.sdkFullscreenEnter)return!1;n.sdkFullscreenEnter()})}function b(){if(r()&&n.sdkFullscreenExit){n.sdkFullscreenExit();return}a()}return{el:u,play:()=>{n.hasPlayer()?n.play():g.playQueued=!0},pause:()=>n.pause(),paused:()=>g.paused,currentTime:()=>g.currentTime,setCurrentTime:e=>{if(n.setCurrentTime){n.setCurrentTime(v,e);return}g.currentTime=e,n.seekToSdk?.(e),i.trigger(`seeking`)},duration:()=>g.duration,volume:()=>g.volume,setVolume:e=>{g.volume=e,n.volumeToSdk(e)},muted:()=>g.muted,setMuted:e=>{g.muted=e,n.muteToSdk(v,e)},...n.rate?n.rate(v):{playbackRate:()=>1,setPlaybackRate:()=>{}},bufferedEnd:()=>g.currentTime,error:()=>g.errorState,setSrc:()=>{},supportsPlaybackRate:()=>!1,...s,enterFullscreen:y,exitFullscreen:b,on:i.on,off:i.off,dispose:()=>{_=!0,m(),n.destroyPlayer(),d(e,u,n.cssClass),i.dispose()}}}export{p as a,u as c,o as d,a as f,h as i,g as l,i as m,l as n,m as o,r as p,_ as r,f as s,s as t,d as u};
@@ -0,0 +1 @@
1
+ import{l as e,o as t,u as n}from"./constants-DRD0PsRw.mjs";import{n as r,t as i}from"./sourceHelpers-DlkCZiTJ.mjs";function a(e){return e.match(/cdn\.jwplayer\.com\/videos\/([^-]+)/)?.[1]??e.match(/cdn\.jwplayer\.com\/manifests\/([^.]+)/)?.[1]??e.match(/^jwplayer:\/\/([^/]+)$/)?.[1]??null}function o(e){let t=e?.advertising?.schedule;return Array.isArray(t)&&t.length?t[0].tag??null:e?.advertising?.tag??null}const s=i(async t=>{let n=await fetch(`${e}/${t}`);if(!n.ok)throw Error(`JW Platform API error: ${n.status}`);let i=(await n.json()).playlist?.[0];if(!i)throw Error(`JW Platform: empty playlist`);let a=r((i.sources??[]).map(e=>({src:e.file,type:e.type})));if(!a.length)throw Error(`JW Platform: no playable sources found`);return{src:a[0].src,type:a[0].type,poster:i.image??null,adTagUrl:o(i)}});async function c(e){let r=a(e);if(!r)throw Error(`JW Platform: unrecognised source URL: ${e}`);let i=await s(r);if(e.startsWith(`jwplayer://`))return i;let o=/\.mp4(\?|#|$)/.test(e)?n:t;return{...i,src:e,type:o}}export{c as resolveSource};
@@ -0,0 +1 @@
1
+ const e={};function t(t,n=t){return e[n]||(e[n]=new Promise((e,n)=>{let r=document.createElement(`script`);r.src=t,r.onload=()=>e(),r.onerror=()=>n(Error(`Failed to load script: ${t}`)),document.head.appendChild(r)})),e[n]}export{t};
@@ -0,0 +1 @@
1
+ function e(e,t){let n=window.pbjs;if(!n)return Promise.resolve(t);let r=e.timeoutMs??1e3;return new Promise(i=>{let a=!1;function o(e){a||(a=!0,i(e||t))}let s=setTimeout(()=>o(t),r);n.que.push(()=>{try{n.addAdUnits(e.adUnit),n.requestBids({adUnitCodes:[e.adUnit.code],timeout:r,bidsBackHandler:()=>{clearTimeout(s);try{o(n.adServers?.gam?.buildVideoUrl({adUnit:e.adUnit,params:e.params}))}catch{o(t)}}})}catch{clearTimeout(s),o(t)}})})}export{e as resolveHeaderBiddingAdTagUrl};
@@ -0,0 +1 @@
1
+ import{C as e}from"./constants-DRD0PsRw.mjs";function t(e,t=(...e)=>String(e[0])){let n={};return async(...r)=>{let i=t(...r);if(n[i])return n[i];let a=await e(...r);return n[i]=a,a}}function n(t){return t.filter(t=>t.src&&e.includes(t.type)).sort((t,n)=>e.indexOf(t.type)-e.indexOf(n.type))}export{n,t};
@@ -0,0 +1 @@
1
+ import{D as e,_ as t}from"./constants-DRD0PsRw.mjs";import{r as n}from"./embedShared-B1B7ZH_3.mjs";import{t as r}from"./loadScript-Du6JsTc2.mjs";function i(e){return e.match(/(?:vimeo\.com\/(?:video\/|channels\/[^/]+\/|groups\/[^/]+\/videos\/)?|player\.vimeo\.com\/video\/)(\d+)/)?.[1]??null}function a(a,o){let s=null,c=1;return n(a,o,{cssClass:t,connect:async({techId:t,emitter:n,state:a,isDisposed:c,consumeQueuedPlay:l})=>{let u=i(o.src);if(!u||(await r(e,`vimeo`),c()||!window.Vimeo))return;let d={id:Number(u),byline:!1,portrait:!1,title:!1,transparent:!0,controls:!!o.nativeUi,autopause:!1,...o.autoplay!==void 0&&{autoplay:o.autoplay},...o.muted!==void 0&&{muted:o.muted}};s=new window.Vimeo.Player(t,d),o.autoplay&&(a.playQueued=!0),s.ready().then(()=>{o.muted&&s?.setMuted(!0).catch(()=>{}),o.volume!==void 0&&s?.setVolume(o.volume).catch(()=>{}),l(()=>void s?.play().catch(()=>{}))}).catch(e=>{a.errorState={code:4,message:e?.message||`This video is unavailable or cannot be embedded here.`},n.trigger(`error`)}),s.on(`play`,()=>{a.paused=!1,n.trigger(`play`),n.trigger(`playing`)}),s.on(`pause`,()=>{a.paused=!0,n.trigger(`pause`)}),s.on(`ended`,()=>{a.paused=!0,n.trigger(`ended`)});let f=!1;s.on(`timeupdate`,e=>{let{seconds:t,duration:r}=e;a.currentTime=t,a.duration=r,n.trigger(`timeupdate`),r&&!f&&(f=!0,n.trigger(`durationchange`))}),s.on(`loaded`,()=>{f=!1,n.trigger(`loadedmetadata`),n.trigger(`durationchange`)}),s.on(`seeking`,e=>{a.currentTime=e.seconds,n.trigger(`seeking`)}),s.on(`seeked`,e=>{a.currentTime=e.seconds,n.trigger(`seeked`),n.trigger(`timeupdate`)}),s.on(`bufferstart`,()=>n.trigger(`waiting`)),s.on(`bufferend`,()=>n.trigger(`canplay`)),s.on(`volumechange`,e=>{a.volume=e.volume,n.trigger(`volumechange`)}),s.on(`error`,()=>n.trigger(`error`))},hasPlayer:()=>!!s,play:()=>void s?.play().catch(()=>{}),pause:()=>void s?.pause().catch(()=>{}),rate:({emitter:e})=>({playbackRate:()=>c,setPlaybackRate:t=>{c=t,s?.setPlaybackRate(t).catch(()=>{}),e.trigger(`ratechange`)}}),setCurrentTime:({emitter:e},t)=>{s?.setCurrentTime(t).catch(()=>{}),e.trigger(`timeupdate`),e.trigger(`seeking`)},volumeToSdk:e=>void s?.setVolume(e).catch(()=>{}),muteToSdk:({emitter:e,schedule:t},n)=>{s?.setMuted(n).then(()=>t(()=>e.trigger(`volumechange`),50)).catch(()=>{})},sdkFullscreenEnter:()=>void s?.requestFullscreen().catch(()=>{}),destroyPlayer:()=>{let e=s;s=null,e?.destroy().catch(()=>{})}})}export{a as createVimeoAdapter};
@@ -0,0 +1 @@
1
+ import{v as e}from"./constants-DRD0PsRw.mjs";import{a as t,d as n,i as r,l as i,n as a,o,t as s,u as c}from"./embedShared-B1B7ZH_3.mjs";import{t as l}from"./loadScript-Du6JsTc2.mjs";function u(e,t){return t===e.PlayerState.PLAYING||t===e.PlayerState.BUFFERING}function d(e){let t={videoId:null,listId:null},n=e.match(/^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|shorts\/|&v=)([^#&?]*).*/);n?.[2]?.length===11&&(t.videoId=n[2]);let r=e.match(/[?&]list=([^#&?]+)/);return r?.[1]&&(t.listId=r[1]),t}let f=!1,p=!1;const m=[];function h(){p||(p=!0,l(`https://www.youtube.com/iframe_api`).then(()=>{window.YT?.ready(()=>{f=!0,m.forEach(e=>e()),m.length=0})}))}function g(l,p){h();let g=n(),{techId:_,wrapper:v}=a(l,e),y=d(p.src),b=null,x=y.videoId,S=!1,C=!1,w=!1,T=null,E=!1,D=null,O=!1,{schedule:k,clearAll:A}=r(),j=null,M={active:!1,wasPaused:!1,timeBefore:0,catchUpInterval:null};function N(){try{let e=b?.getPlayerResponse()?.adPlacements;return Array.isArray(e)&&e.length>0}catch{return!1}}function P(e){b?.loadVideoById({videoId:e})}function F(e){b?.cueVideoById({videoId:e})}function I(){y.videoId&&(M.wasPaused=!1,S?x===y.videoId?b?.playVideo():(P(y.videoId),x=y.videoId):(g.trigger(`waiting`),C=!0))}function L(){M.catchUpInterval&&clearInterval(M.catchUpInterval),M.active=!1,M.wasPaused&&b?.pauseVideo(),g.trigger(`seeked`)}function R(){O=(b?.getAvailablePlaybackRates()??[]).length>1,S=!0,p.muted&&b?.mute(),p.volume!==void 0&&b?.setVolume(p.volume*100),C?I():w&&y.videoId&&(F(y.videoId),x=y.videoId)}function z(e){if(e===T||D!==null)return;T=e;let t=N();t!==E&&(E=t,g.trigger(t?`adstart`:`adend`));let n=window.YT;if(n){switch(e){case-1:g.trigger(`loadstart`),g.trigger(`loadedmetadata`),g.trigger(`durationchange`),g.trigger(`ratechange`);break;case n.PlayerState.ENDED:g.trigger(`ended`);break;case n.PlayerState.PLAYING:g.trigger(`timeupdate`),g.trigger(`durationchange`),g.trigger(`playing`),g.trigger(`play`),M.active&&L();break;case n.PlayerState.PAUSED:g.trigger(`canplay`),M.active||g.trigger(`pause`);break;case n.PlayerState.BUFFERING:g.trigger(`waiting`);break;case n.PlayerState.CUED:g.trigger(`canplay`);break}j&&=(clearInterval(j),null),e===n.PlayerState.PLAYING&&(j=setInterval(()=>g.trigger(`timeupdate`),250))}}function B(){let e={controls:+!!p.nativeUi,modestbranding:1,rel:0,showinfo:0,mute:+!!p.muted,origin:window.location.origin,allowfullscreen:1,fullscreen:1,fs:1,autoplay:0,playsinline:1,...p.customVars};x=y.videoId,b=new window.YT.Player(_,{videoId:x??void 0,playerVars:e,events:{onReady:R,onStateChange:e=>z(e.data),onPlaybackRateChange:()=>g.trigger(`ratechange`),onVolumeChange:()=>g.trigger(`volumechange`),onError:e=>{D=e.data,g.trigger(`error`),k(()=>{D=null})}}})}f?B():m.push(B),p.autoplay?S?I():C=!0:y.videoId&&(w=!0);function V(){if(!b)return;let e=b.getCurrentTime(),{video_id:t}=b.getVideoData();b.pauseVideo();let{overlay:n,reveal:r,finish:a}=i(g),o=document.createElement(`div`);o.id=`yt-fs-${Math.random().toString(36).slice(2)}`,n.appendChild(o);let s=null,c=()=>{document.removeEventListener(`pointerdown`,l,!0),a(()=>{let t=s?.getCurrentTime()??e;try{s?.destroy()}catch{}b?.seekTo(t,!0),g.trigger(`timeupdate`)})};function l(){c()}s=new window.YT.Player(o.id,{videoId:t,playerVars:{playsinline:0,autoplay:0,controls:1,modestbranding:1,rel:0,start:Math.floor(e)},events:{onReady:t=>{r(),t.target.seekTo(e,!0),t.target.playVideo()},onStateChange:e=>{let t=window.YT;t&&(e.data===t.PlayerState.ENDED?c():e.data===t.PlayerState.PAUSED?(document.removeEventListener(`pointerdown`,l,!0),document.addEventListener(`pointerdown`,l,{capture:!0,once:!0})):(document.removeEventListener(`pointerdown`,l,!0),r()))}}})}function H(){t(l,()=>{if(!b)return!1;V()})}return{el:v,play:I,pause:()=>b?.pauseVideo(),paused:()=>{if(!b)return!0;let e=window.YT;return!e||!u(e,T)},currentTime:()=>b?.getCurrentTime()??0,setCurrentTime:e=>{if(!b)return;let t=window.YT;t&&T===t.PlayerState.PAUSED&&(M.timeBefore=b.getCurrentTime()),M.active||(M.wasPaused=!t||!u(t,T)),b.seekTo(e,!0),g.trigger(`timeupdate`),g.trigger(`seeking`),M.active=!0,t&&T===t.PlayerState.PAUSED&&M.timeBefore!==e&&(M.catchUpInterval&&clearInterval(M.catchUpInterval),M.catchUpInterval=setInterval(()=>{T!==t.PlayerState.PAUSED||!M.active?M.catchUpInterval&&clearInterval(M.catchUpInterval):b&&b.getCurrentTime()!==M.timeBefore&&(g.trigger(`timeupdate`),L())},250))},duration:()=>b?.getDuration()??0,volume:()=>b?b.getVolume()/100:1,setVolume:e=>b?.setVolume(e*100),muted:()=>b?.isMuted()??!1,setMuted:e=>{b&&(e?b.mute():b.unMute(),k(()=>g.trigger(`volumechange`),50))},playbackRate:()=>b?.getPlaybackRate()??1,setPlaybackRate:e=>b?.setPlaybackRate(e),bufferedEnd:()=>b?.getVideoLoadedFraction?b.getVideoLoadedFraction()*b.getDuration():0,error:()=>D===null?null:{code:D,message:`This video could not be played.`},setSrc:e=>{let t=d(e);y.videoId=t.videoId,y.listId=t.listId,y.videoId&&(S?(P(y.videoId),x=y.videoId):w=!0)},supportsPlaybackRate:()=>O,...s,enterFullscreen:H,exitFullscreen:o,on:g.on,off:g.off,dispose:()=>{if(A(),j&&clearInterval(j),M.catchUpInterval&&clearInterval(M.catchUpInterval),b)try{b.stopVideo(),b.destroy()}catch{}else{let e=m.indexOf(B);e!==-1&&m.splice(e,1)}b=null,c(l,v,e),g.dispose()}}}export{g as createYoutubeAdapter};
@@ -1 +1 @@
1
- .mvp-scrubber-wrap[data-v-043f1bc8]{width:100%;position:relative}:where(.mvp-scrubber[data-v-043f1bc8]){cursor:pointer;accent-color:currentColor;width:100%}.mvp-scrubber__preview[data-v-043f1bc8]{font-variant-numeric:tabular-nums;pointer-events:none;white-space:nowrap;margin-bottom:.4rem;font-size:.75rem;position:absolute;bottom:100%;transform:translate(-50%)}:where(.mvp-play-button[data-v-218255bd]){all:unset;cursor:pointer;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-play-button svg[data-v-218255bd]){width:1em;height:1em}:where(.mvp-mute-button[data-v-1940b598]){all:unset;cursor:pointer;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-mute-button svg[data-v-1940b598]){width:1em;height:1em}:where(.mvp-fullscreen-button[data-v-b93a5017]){all:unset;cursor:pointer;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-fullscreen-button svg[data-v-b93a5017]){width:1em;height:1em}@keyframes spin-259be2b2{to{transform:rotate(360deg)}}.spinner[data-v-259be2b2]{border-style:solid;border-color:#fffc #ffffff26 #ffffff26;border-radius:50%;animation:.75s linear infinite spin-259be2b2}:where(.mvp-buffering[data-v-454fec7f]){justify-content:center;align-items:center;display:inline-flex}:where(.mvp-loop-button[data-v-e32eda25]){all:unset;cursor:pointer;opacity:.6;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-loop-button--active[data-v-e32eda25]){opacity:1}:where(.mvp-loop-button svg[data-v-e32eda25]){width:1em;height:1em}:where(.mvp-pip-button[data-v-f654d93e]){all:unset;cursor:pointer;opacity:.6;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-pip-button--active[data-v-f654d93e]){opacity:1}:where(.mvp-pip-button svg[data-v-f654d93e]){width:1em;height:1em}:where(.mvp-captions-button[data-v-2572c4f2]){all:unset;cursor:pointer;opacity:.6;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-captions-button--active[data-v-2572c4f2]){opacity:1}:where(.mvp-captions-button svg[data-v-2572c4f2]){width:1em;height:1em}:where(.mvp-quality-button[data-v-d1352878]){all:unset;cursor:pointer;opacity:.6;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-quality-button--active[data-v-d1352878]){opacity:1}:where(.mvp-quality-button svg[data-v-d1352878]){width:1em;height:1em}:where(.mvp-playback-rate-button[data-v-646c9bc1]){all:unset;cursor:pointer;font-variant-numeric:tabular-nums;opacity:.6;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-playback-rate-button--active[data-v-646c9bc1]){opacity:1}.mvp-volume-wrap[data-v-fbb2c86c]{align-items:center;gap:.75rem;width:100%;display:flex}:where(.mvp-volume-slider[data-v-fbb2c86c]){cursor:pointer;accent-color:currentColor;flex:1}:where(.mvp-volume-pct[data-v-fbb2c86c]){font-variant-numeric:tabular-nums;text-align:right;min-width:2rem}:where(.mvp-time-display[data-v-0285c811]){font-variant-numeric:tabular-nums;align-items:center;gap:.35rem;display:inline-flex}:where(.mvp-time-display__dot[data-v-0285c811]){background:currentColor;border-radius:50%;width:6px;height:6px}
1
+ .mvp-scrubber-wrap[data-v-043f1bc8]{width:100%;position:relative}:where(.mvp-scrubber[data-v-043f1bc8]){cursor:pointer;accent-color:currentColor;width:100%}.mvp-scrubber__preview[data-v-043f1bc8]{font-variant-numeric:tabular-nums;pointer-events:none;white-space:nowrap;margin-bottom:.4rem;font-size:.75rem;position:absolute;bottom:100%;transform:translate(-50%)}:where(.mvp-play-button[data-v-218255bd]){all:unset;cursor:pointer;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-play-button svg[data-v-218255bd]){width:1em;height:1em}:where(.mvp-mute-button[data-v-1940b598]){all:unset;cursor:pointer;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-mute-button svg[data-v-1940b598]){width:1em;height:1em}:where(.mvp-fullscreen-button[data-v-b93a5017]){all:unset;cursor:pointer;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-fullscreen-button svg[data-v-b93a5017]){width:1em;height:1em}@keyframes spin-259be2b2{to{transform:rotate(360deg)}}.spinner[data-v-259be2b2]{border-style:solid;border-color:#fffc #ffffff26 #ffffff26;border-radius:50%;animation:.75s linear infinite spin-259be2b2}:where(.mvp-buffering[data-v-454fec7f]){justify-content:center;align-items:center;display:inline-flex}:where(.mvp-loop-button[data-v-e32eda25]){all:unset;cursor:pointer;opacity:.6;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-loop-button--active[data-v-e32eda25]){opacity:1}:where(.mvp-loop-button svg[data-v-e32eda25]){width:1em;height:1em}:where(.mvp-pip-button[data-v-f654d93e]){all:unset;cursor:pointer;opacity:.6;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-pip-button--active[data-v-f654d93e]){opacity:1}:where(.mvp-pip-button svg[data-v-f654d93e]){width:1em;height:1em}:where(.mvp-captions-button[data-v-2572c4f2]){all:unset;cursor:pointer;opacity:.6;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-captions-button--active[data-v-2572c4f2]){opacity:1}:where(.mvp-captions-button svg[data-v-2572c4f2]){width:1em;height:1em}:where(.mvp-quality-button[data-v-d1352878]){all:unset;cursor:pointer;opacity:.6;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-quality-button--active[data-v-d1352878]){opacity:1}:where(.mvp-quality-button svg[data-v-d1352878]){width:1em;height:1em}:where(.mvp-playback-rate-button[data-v-646c9bc1]){all:unset;cursor:pointer;font-variant-numeric:tabular-nums;opacity:.6;justify-content:center;align-items:center;display:inline-flex}:where(.mvp-playback-rate-button--active[data-v-646c9bc1]){opacity:1}.mvp-volume-wrap[data-v-fbb2c86c]{align-items:center;gap:.75rem;width:100%;display:flex}:where(.mvp-volume-slider[data-v-fbb2c86c]){cursor:pointer;accent-color:currentColor;flex:1}:where(.mvp-volume-pct[data-v-fbb2c86c]){font-variant-numeric:tabular-nums;text-align:right;min-width:2rem}:where(.mvp-time-display[data-v-0285c811]){font-variant-numeric:tabular-nums;align-items:center;gap:.35rem;display:inline-flex}:where(.mvp-time-display__dot[data-v-0285c811]){background:currentColor;border-radius:50%;width:6px;height:6px}:where(.mvp-transcript[data-v-c166a2c5]){margin:0;padding:0;list-style:none;overflow-y:auto}:where(.mvp-transcript__cue[data-v-c166a2c5]){all:unset;cursor:pointer;box-sizing:border-box;border-radius:4px;align-items:baseline;gap:.5rem;width:100%;padding:.35rem .5rem;display:flex}:where(.mvp-transcript__cue[data-v-c166a2c5]:hover){background:#7f7f7f26}:where(.mvp-transcript__cue--active[data-v-c166a2c5]){background:#7f7f7f40;font-weight:600}:where(.mvp-transcript__time[data-v-c166a2c5]){font-variant-numeric:tabular-nums;opacity:.7;flex-shrink:0}
@@ -1,3 +1,4 @@
1
+ import "vue";
1
2
  //#region src/types/playback.d.ts
2
3
  interface CaptionTrackInfo {
3
4
  index: number;
@@ -11,7 +12,12 @@ interface QualityLevelInfo {
11
12
  label: string;
12
13
  }
13
14
  //#endregion
14
- //#region src/types.d.ts
15
+ //#region src/types/player.d.ts
16
+ interface TranscriptCue {
17
+ time: number;
18
+ end?: number;
19
+ text: string;
20
+ }
15
21
  interface PlayerHandle {
16
22
  isPlaying: boolean;
17
23
  togglePlay(): void;
@@ -46,58 +52,31 @@ interface PlayerHandle {
46
52
  isAutoQuality: boolean;
47
53
  setQuality(index: number | null): void;
48
54
  supportsPlaybackRate: boolean;
49
- playbackRate: number;
55
+ currentPlaybackRate: number;
50
56
  setPlaybackRate(rate: number): void;
51
57
  }
52
58
  //#endregion
53
- //#region src/elements/controls.d.ts
54
- declare const ScrubberElement: import("vue").VueElementConstructor<{
55
- player?: PlayerHandle | null;
56
- for?: string;
57
- }>;
58
- declare const PlayButtonElement: import("vue").VueElementConstructor<{
59
- player?: PlayerHandle | null;
60
- for?: string;
61
- }>;
62
- declare const MuteButtonElement: import("vue").VueElementConstructor<{
63
- player?: PlayerHandle | null;
64
- for?: string;
65
- }>;
66
- declare const FullscreenButtonElement: import("vue").VueElementConstructor<{
67
- player?: PlayerHandle | null;
68
- for?: string;
69
- }>;
70
- declare const BufferingElement: import("vue").VueElementConstructor<{
71
- player?: PlayerHandle | null;
72
- for?: string;
73
- }>;
74
- declare const LoopButtonElement: import("vue").VueElementConstructor<{
75
- player?: PlayerHandle | null;
76
- for?: string;
77
- }>;
78
- declare const PipButtonElement: import("vue").VueElementConstructor<{
79
- player?: PlayerHandle | null;
80
- for?: string;
81
- }>;
82
- declare const CaptionsButtonElement: import("vue").VueElementConstructor<{
83
- player?: PlayerHandle | null;
84
- for?: string;
85
- }>;
86
- declare const QualityButtonElement: import("vue").VueElementConstructor<{
87
- player?: PlayerHandle | null;
88
- for?: string;
89
- }>;
90
- declare const PlaybackRateButtonElement: import("vue").VueElementConstructor<{
91
- player?: PlayerHandle | null;
92
- for?: string;
93
- }>;
94
- declare const VolumeSliderElement: import("vue").VueElementConstructor<{
95
- player?: PlayerHandle | null;
96
- for?: string;
97
- }>;
98
- declare const TimeDisplayElement: import("vue").VueElementConstructor<{
59
+ //#region src/composables/controls/useResolvedPlayer.d.ts
60
+ interface ResolvedPlayerProps {
99
61
  player?: PlayerHandle | null;
100
62
  for?: string;
63
+ }
64
+ //#endregion
65
+ //#region src/elements/controls.d.ts
66
+ declare const ScrubberElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
67
+ declare const PlayButtonElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
68
+ declare const MuteButtonElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
69
+ declare const FullscreenButtonElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
70
+ declare const BufferingElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
71
+ declare const LoopButtonElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
72
+ declare const PipButtonElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
73
+ declare const CaptionsButtonElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
74
+ declare const QualityButtonElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
75
+ declare const PlaybackRateButtonElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
76
+ declare const VolumeSliderElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
77
+ declare const TimeDisplayElement: import("vue").VueElementConstructor<ResolvedPlayerProps>;
78
+ declare const TranscriptElement: import("vue").VueElementConstructor<ResolvedPlayerProps & {
79
+ cues?: TranscriptCue[] | string;
101
80
  }>;
102
81
  //#endregion
103
- export { BufferingElement, CaptionsButtonElement, FullscreenButtonElement, LoopButtonElement, MuteButtonElement, PipButtonElement, PlayButtonElement, PlaybackRateButtonElement, QualityButtonElement, ScrubberElement, TimeDisplayElement, VolumeSliderElement };
82
+ export { BufferingElement, CaptionsButtonElement, FullscreenButtonElement, LoopButtonElement, MuteButtonElement, PipButtonElement, PlayButtonElement, PlaybackRateButtonElement, QualityButtonElement, ScrubberElement, TimeDisplayElement, TranscriptElement, VolumeSliderElement };