@mux/mux-player 0.1.0-beta.23 → 0.1.0-beta.26

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 (73) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +38 -36
  3. package/coverage/lcov-report/index.html +31 -31
  4. package/coverage/lcov-report/src/dialog.ts.html +1 -1
  5. package/coverage/lcov-report/src/errors.ts.html +1 -1
  6. package/coverage/lcov-report/src/helpers.ts.html +30 -9
  7. package/coverage/lcov-report/src/html.ts.html +159 -9
  8. package/coverage/lcov-report/src/index.html +52 -52
  9. package/coverage/lcov-report/src/index.ts.html +156 -27
  10. package/coverage/lcov-report/src/logger.ts.html +1 -1
  11. package/coverage/lcov-report/src/media-chrome/dialog.ts.html +1 -1
  12. package/coverage/lcov-report/src/media-chrome/index.html +1 -1
  13. package/coverage/lcov-report/src/media-chrome/time-display.ts.html +1 -1
  14. package/coverage/lcov-report/src/media-theme-mux/icons/airplay.svg.html +1 -1
  15. package/coverage/lcov-report/src/media-theme-mux/icons/captions-off.svg.html +1 -1
  16. package/coverage/lcov-report/src/media-theme-mux/icons/captions-on.svg.html +1 -1
  17. package/coverage/lcov-report/src/media-theme-mux/icons/cast-enter.svg.html +103 -0
  18. package/coverage/lcov-report/src/media-theme-mux/icons/cast-exit.svg.html +106 -0
  19. package/coverage/lcov-report/src/media-theme-mux/icons/fullscreen-enter.svg.html +1 -1
  20. package/coverage/lcov-report/src/media-theme-mux/icons/fullscreen-exit.svg.html +1 -1
  21. package/coverage/lcov-report/src/media-theme-mux/icons/index.html +33 -3
  22. package/coverage/lcov-report/src/media-theme-mux/icons/pause.svg.html +1 -1
  23. package/coverage/lcov-report/src/media-theme-mux/icons/pip-enter.svg.html +1 -1
  24. package/coverage/lcov-report/src/media-theme-mux/icons/pip-exit.svg.html +1 -1
  25. package/coverage/lcov-report/src/media-theme-mux/icons/play.svg.html +1 -1
  26. package/coverage/lcov-report/src/media-theme-mux/icons/seek-backward.svg.html +1 -1
  27. package/coverage/lcov-report/src/media-theme-mux/icons/seek-forward.svg.html +1 -1
  28. package/coverage/lcov-report/src/media-theme-mux/icons/volume-high.svg.html +1 -1
  29. package/coverage/lcov-report/src/media-theme-mux/icons/volume-low.svg.html +1 -1
  30. package/coverage/lcov-report/src/media-theme-mux/icons/volume-medium.svg.html +1 -1
  31. package/coverage/lcov-report/src/media-theme-mux/icons/volume-off.svg.html +1 -1
  32. package/coverage/lcov-report/src/media-theme-mux/icons.ts.html +18 -6
  33. package/coverage/lcov-report/src/media-theme-mux/index.html +26 -26
  34. package/coverage/lcov-report/src/media-theme-mux/media-theme-mux.ts.html +342 -177
  35. package/coverage/lcov-report/src/media-theme-mux/styles.css.html +117 -18
  36. package/coverage/lcov-report/src/styles.css.html +1 -1
  37. package/coverage/lcov-report/src/template.ts.html +128 -65
  38. package/coverage/lcov-report/src/utils.ts.html +1 -1
  39. package/coverage/lcov-report/src/video-api.ts.html +91 -13
  40. package/coverage/lcov.info +1595 -1273
  41. package/dist/index.cjs.js +503 -343
  42. package/dist/index.mjs +296 -228
  43. package/dist/mux-player.js +556 -396
  44. package/dist/mux-player.mjs +556 -396
  45. package/dist/tsconfig.tsbuildinfo +1 -1
  46. package/dist/types/helpers.d.ts +1 -0
  47. package/dist/types/html.d.ts +5 -0
  48. package/dist/types/index.d.ts +5 -3
  49. package/dist/types/media-theme-mux/icons.d.ts +2 -0
  50. package/dist/types/media-theme-mux/media-theme-mux.d.ts +32 -12
  51. package/dist/types/template.d.ts +0 -1
  52. package/dist/types/video-api.d.ts +4 -0
  53. package/dist/types-ts3.4/helpers.d.ts +1 -0
  54. package/dist/types-ts3.4/html.d.ts +5 -0
  55. package/dist/types-ts3.4/index.d.ts +4 -3
  56. package/dist/types-ts3.4/media-theme-mux/icons.d.ts +2 -0
  57. package/dist/types-ts3.4/media-theme-mux/media-theme-mux.d.ts +32 -12
  58. package/dist/types-ts3.4/template.d.ts +0 -1
  59. package/dist/types-ts3.4/video-api.d.ts +2 -0
  60. package/package.json +5 -5
  61. package/src/helpers.ts +7 -0
  62. package/src/html.ts +50 -0
  63. package/src/index.ts +58 -15
  64. package/src/media-theme-mux/icons/cast-enter.svg +6 -0
  65. package/src/media-theme-mux/icons/cast-exit.svg +7 -0
  66. package/src/media-theme-mux/icons.ts +4 -0
  67. package/src/media-theme-mux/media-theme-mux.ts +179 -124
  68. package/src/media-theme-mux/styles.css +47 -14
  69. package/src/template.ts +78 -57
  70. package/src/types.d.ts +3 -0
  71. package/src/video-api.ts +27 -1
  72. package/test/player.test.js +34 -0
  73. package/test/template.test.js +6 -4
package/src/template.ts CHANGED
@@ -1,7 +1,12 @@
1
- import './media-theme-mux/media-theme-mux';
1
+ import { parts } from './media-theme-mux/media-theme-mux';
2
2
  import './dialog';
3
- import { getSrcFromPlaybackId, getPosterURLFromPlaybackId, getStoryboardURLFromPlaybackId } from './helpers';
4
- import { html } from './html';
3
+ import {
4
+ castThemeName,
5
+ getSrcFromPlaybackId,
6
+ getPosterURLFromPlaybackId,
7
+ getStoryboardURLFromPlaybackId,
8
+ } from './helpers';
9
+ import { html, unsafeStatic } from './html';
5
10
  // @ts-ignore
6
11
  import cssStr from './styles.css';
7
12
  import { i18n, stylePropsToString } from './utils';
@@ -16,21 +21,26 @@ export const template = (props: MuxTemplateProps) => html`
16
21
  ${content(props)}
17
22
  `;
18
23
 
24
+ const flatCSSParts = Object.values(parts).flatMap((group) => group.split(' '));
25
+ const forwardUniqueCSSParts = [...new Set(flatCSSParts)].join(', ');
26
+
19
27
  export const content = (props: MuxTemplateProps) => html`
20
- <media-theme-mux
28
+ <${unsafeStatic(castThemeName(props.theme) ?? 'media-theme-mux')}
29
+ nohotkeys="${props.noHotKeys ?? false}"
21
30
  audio="${props.audio || false}"
22
- style="${stylePropsToString({
23
- '--primary-color': props.primaryColor,
24
- '--secondary-color': props.secondaryColor,
25
- '--mux-time-range-padding': props.secondaryColor ? '0' : null,
26
- '--media-range-track-border-radius': props.secondaryColor ? '0' : null,
27
- }) ?? false}"
28
- class="size-${props.playerSize}"
31
+ style="${
32
+ stylePropsToString({
33
+ '--primary-color': props.primaryColor,
34
+ '--secondary-color': props.secondaryColor,
35
+ }) ?? false
36
+ }"
37
+ class="size-${props.playerSize}${props.secondaryColor ? ' two-tone' : ''}"
29
38
  stream-type="${props.streamType}"
30
39
  player-size="${props.playerSize}"
31
40
  default-hidden-captions="${props.defaultHiddenCaptions}"
32
41
  forward-seek-offset="${props.forwardSeekOffset}"
33
42
  backward-seek-offset="${props.backwardSeekOffset}"
43
+ exportparts="seek-live, ${forwardUniqueCSSParts}"
34
44
  >
35
45
  <mux-video
36
46
  slot="media"
@@ -43,52 +53,62 @@ export const content = (props: MuxTemplateProps) => html`
43
53
  debug="${props.debug ?? false}"
44
54
  prefer-mse="${props.preferMse ?? false}"
45
55
  start-time="${props.startTime != null ? props.startTime : false}"
46
- metadata-video-id="${props.metadataVideoId ?? props.metadata?.video_id ?? false}"
47
- metadata-video-title="${props.metadataVideoTitle ?? props.metadata?.video_title ?? false}"
48
- metadata-viewer-user-id="${props.metadataViewerUserId ?? props.metadata?.viewer_user_id ?? false}"
56
+ metadata-video-id="${props.metadataVideoId ?? false}"
57
+ metadata-video-title="${props.metadataVideoTitle ?? false}"
58
+ metadata-viewer-user-id="${props.metadataViewerUserId ?? false}"
49
59
  beacon-collection-domain="${props.beaconCollectionDomain ?? false}"
50
60
  player-software-name="${props.playerSoftwareName}"
51
61
  player-software-version="${props.playerSoftwareVersion}"
52
62
  env-key="${props.envKey ?? false}"
53
63
  stream-type="${props.streamType ?? false}"
54
64
  custom-domain="${props.customDomain ?? false}"
55
- src="${!!props.src
56
- ? props.src
57
- : props.playbackId
58
- ? getSrcFromPlaybackId(props.playbackId, { domain: props.customDomain, token: props.tokens.playback })
59
- : false}"
60
- poster="${!!props.poster
61
- ? props.poster
62
- : props.playbackId && !props.audio
63
- ? getPosterURLFromPlaybackId(props.playbackId, {
64
- domain: props.customDomain,
65
- thumbnailTime: props.thumbnailTime ?? props.startTime,
66
- token: props.tokens.thumbnail,
67
- })
68
- : false}"
69
- cast-src="${!!props.src
70
- ? props.src
71
- : props.playbackId
72
- ? getSrcFromPlaybackId(props.playbackId, { domain: props.customDomain, token: props.tokens.playback })
73
- : false}"
65
+ src="${
66
+ !!props.src
67
+ ? props.src
68
+ : props.playbackId
69
+ ? getSrcFromPlaybackId(props.playbackId, { domain: props.customDomain, token: props.tokens.playback })
70
+ : false
71
+ }"
72
+ poster="${
73
+ !!props.poster
74
+ ? props.poster
75
+ : props.playbackId && !props.audio
76
+ ? getPosterURLFromPlaybackId(props.playbackId, {
77
+ domain: props.customDomain,
78
+ thumbnailTime: props.thumbnailTime ?? props.startTime,
79
+ token: props.tokens.thumbnail,
80
+ })
81
+ : false
82
+ }"
83
+ cast-src="${
84
+ !!props.src
85
+ ? props.src
86
+ : props.playbackId
87
+ ? getSrcFromPlaybackId(props.playbackId, { domain: props.customDomain, token: props.tokens.playback })
88
+ : false
89
+ }"
74
90
  cast-stream-type="${[StreamTypes.LIVE, StreamTypes.LL_LIVE].includes(props.streamType as any) ? 'live' : false}"
75
91
  >
76
- ${props.playbackId &&
77
- !props.audio &&
78
- ![StreamTypes.LIVE, StreamTypes.LL_LIVE, StreamTypes.DVR, StreamTypes.LL_DVR].includes(props.streamType as any)
79
- ? html`<track
80
- label="thumbnails"
81
- default
82
- kind="metadata"
83
- src="${getStoryboardURLFromPlaybackId(props.playbackId, {
84
- domain: props.customDomain,
85
- token: props.tokens.storyboard,
86
- })}"
87
- />`
88
- : html``}
92
+ ${
93
+ props.playbackId &&
94
+ !props.audio &&
95
+ ![StreamTypes.LIVE, StreamTypes.LL_LIVE, StreamTypes.DVR, StreamTypes.LL_DVR].includes(props.streamType as any)
96
+ ? html`<track
97
+ label="thumbnails"
98
+ default
99
+ kind="metadata"
100
+ src="${getStoryboardURLFromPlaybackId(props.playbackId, {
101
+ domain: props.customDomain,
102
+ token: props.tokens.storyboard,
103
+ })}"
104
+ />`
105
+ : html``
106
+ }
89
107
  </mux-video>
90
108
  <button
91
109
  slot="seek-to-live-button"
110
+ part="seek-live button"
111
+ class="mxp-seek-to-live-button"
92
112
  aria-disabled="${props.inLiveWindow}"
93
113
  onclick="${function (this: HTMLButtonElement, evt: Event) {
94
114
  props.onSeekToLive?.(evt);
@@ -97,7 +117,6 @@ export const content = (props: MuxTemplateProps) => html`
97
117
  (this as HTMLButtonElement).dispatchEvent(playRequestEvt);
98
118
  }
99
119
  }}"
100
- class="mxp-seek-to-live-button"
101
120
  >
102
121
  Live
103
122
  </button>
@@ -110,16 +129,18 @@ export const content = (props: MuxTemplateProps) => html`
110
129
  ${props.dialog?.title ? html`<h3>${props.dialog.title}</h3>` : html``}
111
130
  <p>
112
131
  ${props.dialog?.message}
113
- ${props.dialog?.linkUrl
114
- ? html`<a
115
- href="${props.dialog.linkUrl}"
116
- target="_blank"
117
- rel="external noopener"
118
- aria-label="${props.dialog.linkText ?? ''} ${i18n(`(opens in a new window)`)}"
119
- >${props.dialog.linkText ?? props.dialog.linkUrl}</a
120
- >`
121
- : html``}
132
+ ${
133
+ props.dialog?.linkUrl
134
+ ? html`<a
135
+ href="${props.dialog.linkUrl}"
136
+ target="_blank"
137
+ rel="external noopener"
138
+ aria-label="${props.dialog.linkText ?? ''} ${i18n(`(opens in a new window)`)}"
139
+ >${props.dialog.linkText ?? props.dialog.linkUrl}</a
140
+ >`
141
+ : html``
142
+ }
122
143
  </p>
123
144
  </mxp-dialog>
124
- </media-theme-mux>
145
+ </${unsafeStatic(castThemeName(props.theme) ?? 'media-theme-mux')}>
125
146
  `;
package/src/types.d.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  import type MuxVideoElement, { MediaError } from '@mux/mux-video';
2
2
 
3
3
  export type MuxPlayerProps = Partial<MuxVideoElement> & {
4
+ nohotkeys?: boolean;
4
5
  preferMse?: boolean;
5
6
  };
6
7
 
7
8
  export type MuxTemplateProps = Partial<MuxPlayerProps> & {
8
9
  audio: boolean;
10
+ theme?: string;
9
11
  playerSize: string;
10
12
  showLoading: boolean;
11
13
  thumbnailTime: number;
@@ -28,6 +30,7 @@ export type MuxTemplateProps = Partial<MuxPlayerProps> & {
28
30
  metadataVideoId: string;
29
31
  metadataVideoTitle: string;
30
32
  metadataViewerUserId: string;
33
+ noHotKeys: boolean;
31
34
  };
32
35
 
33
36
  export type DialogOptions = {
package/src/video-api.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { VideoEvents } from '@mux/mux-video';
2
2
  import type MuxVideoElement from '@mux/mux-video';
3
3
  import * as logger from './logger';
4
+ import { toNumberOrUndefined } from './utils';
4
5
 
5
6
  export type CastOptions = {
6
7
  receiverApplicationId: string;
@@ -99,6 +100,7 @@ class VideoApiElement extends HTMLElement {
99
100
  case CustomVideoAttributes.MUTED: {
100
101
  if (this.media) {
101
102
  this.media.muted = newValue != null;
103
+ this.media.defaultMuted = newValue != null;
102
104
  }
103
105
  return;
104
106
  }
@@ -113,6 +115,7 @@ class VideoApiElement extends HTMLElement {
113
115
  const val = +newValue;
114
116
  if (this.media && !Number.isNaN(val)) {
115
117
  this.media.playbackRate = val;
118
+ this.media.defaultPlaybackRate = val;
116
119
  }
117
120
  return;
118
121
  }
@@ -217,6 +220,19 @@ class VideoApiElement extends HTMLElement {
217
220
  }
218
221
  }
219
222
 
223
+ get defaultPlaybackRate() {
224
+ return toNumberOrUndefined(this.getAttribute(CustomVideoAttributes.PLAYBACKRATE)) ?? 1;
225
+ }
226
+
227
+ set defaultPlaybackRate(val) {
228
+ if (val != null) {
229
+ this.setAttribute(CustomVideoAttributes.PLAYBACKRATE, `${val}`);
230
+ } else {
231
+ // Remove boolean attribute if false, 0, '', null, undefined.
232
+ this.removeAttribute(CustomVideoAttributes.PLAYBACKRATE);
233
+ }
234
+ }
235
+
220
236
  get crossOrigin() {
221
237
  return getVideoAttribute(this, AllowedVideoAttributes.CROSSORIGIN);
222
238
  }
@@ -252,10 +268,20 @@ class VideoApiElement extends HTMLElement {
252
268
  }
253
269
 
254
270
  get muted() {
255
- return getVideoAttribute(this, AllowedVideoAttributes.MUTED) != null;
271
+ return this.media?.muted ?? false;
256
272
  }
257
273
 
258
274
  set muted(val) {
275
+ if (this.media) {
276
+ this.media.muted = Boolean(val);
277
+ }
278
+ }
279
+
280
+ get defaultMuted() {
281
+ return getVideoAttribute(this, AllowedVideoAttributes.MUTED) != null;
282
+ }
283
+
284
+ set defaultMuted(val) {
259
285
  if (val) {
260
286
  this.setAttribute(AllowedVideoAttributes.MUTED, '');
261
287
  } else {
@@ -283,17 +283,29 @@ describe('<mux-player>', () => {
283
283
  assert(muxVideo.muted, 'muxVideo.muted is true');
284
284
  assert(nativeVideo.muted, 'nativeVideo.muted is true');
285
285
 
286
+ assert(player.defaultMuted, 'player.defaultMuted is true');
287
+ assert(muxVideo.defaultMuted, 'muxVideo.defaultMuted is true');
288
+ assert(nativeVideo.defaultMuted, 'nativeVideo.defaultMuted is true');
289
+
286
290
  player.removeAttribute('muted');
287
291
 
288
292
  assert(!player.muted, 'player.muted is false');
289
293
  assert(!muxVideo.muted, 'muxVideo.muted is false');
290
294
  assert(!nativeVideo.muted, 'nativeVideo.muted is false');
291
295
 
296
+ assert(!player.defaultMuted, 'player.defaultMuted is false');
297
+ assert(!muxVideo.defaultMuted, 'muxVideo.defaultMuted is false');
298
+ assert(!nativeVideo.defaultMuted, 'nativeVideo.defaultMuted is false');
299
+
292
300
  player.setAttribute('muted', '');
293
301
 
294
302
  assert(player.muted, 'player.muted is true');
295
303
  assert(muxVideo.muted, 'muxVideo.muted is true');
296
304
  assert(nativeVideo.muted, 'nativeVideo.muted is true');
305
+
306
+ assert(player.defaultMuted, 'player.defaultMuted is true');
307
+ assert(muxVideo.defaultMuted, 'muxVideo.defaultMuted is true');
308
+ assert(nativeVideo.defaultMuted, 'nativeVideo.defaultMuted is true');
297
309
  });
298
310
 
299
311
  it('volume attribute behaves like expected', async function () {
@@ -342,6 +354,28 @@ describe('<mux-player>', () => {
342
354
  assert.equal(nativeVideo.playbackRate, 0.7, 'nativeVideo.playbackRate is 0.7');
343
355
  });
344
356
 
357
+ it('defaultPlaybackRate property behaves like expected', async function () {
358
+ const player = await fixture(`<mux-player
359
+ playback-id="DS00Spx1CV902MCtPj5WknGlR102V5HFkDe"
360
+ stream-type="on-demand"
361
+ ></mux-player>`);
362
+
363
+ assert.equal(player.defaultPlaybackRate, 1);
364
+
365
+ const muxVideo = player.media;
366
+ const nativeVideo = muxVideo.shadowRoot.querySelector('video');
367
+
368
+ assert.equal(player.defaultPlaybackRate, 1, 'player.defaultPlaybackRate is 1');
369
+ assert.equal(muxVideo.defaultPlaybackRate, 1, 'muxVideo.defaultPlaybackRate is 1');
370
+ assert.equal(nativeVideo.defaultPlaybackRate, 1, 'nativeVideo.defaultPlaybackRate is 1');
371
+
372
+ player.defaultPlaybackRate = 0.7;
373
+
374
+ assert.equal(player.defaultPlaybackRate, 0.7, 'player.defaultPlaybackRate is 0.7');
375
+ assert.equal(muxVideo.defaultPlaybackRate, 0.7, 'muxVideo.defaultPlaybackRate is 0.7');
376
+ assert.equal(nativeVideo.defaultPlaybackRate, 0.7, 'nativeVideo.defaultPlaybackRate is 0.7');
377
+ });
378
+
345
379
  it("signing tokens generate correct asset URL's", async function () {
346
380
  // tokens expire in 10 years
347
381
  const player = await fixture(`<mux-player
@@ -7,11 +7,13 @@ const minify = (html) => html.trim().replace(/>\s+</g, '><');
7
7
  describe('<mux-player> template render', () => {
8
8
  const div = document.createElement('div');
9
9
 
10
+ const exportParts = `seek-live, layer, media-layer, poster-layer, vertical-layer, centered-layer, center, play, button, seek-backward, seek-forward, mute, captions, airplay, pip, fullscreen, cast, playbackrate, volume, range, time, display`;
11
+
10
12
  it('default template without props', function () {
11
13
  render(content({}), div);
12
14
  assert.equal(
13
15
  minify(div.innerHTML),
14
- '<media-theme-mux class="size-" stream-type="" player-size="" default-hidden-captions="" forward-seek-offset="" backward-seek-offset=""><mux-video slot="media" crossorigin="" playsinline="" player-software-name="" player-software-version=""></mux-video><button slot="seek-to-live-button" aria-disabled="" class="mxp-seek-to-live-button">\n Live\n </button><mxp-dialog no-auto-hide="" open=""><p></p></mxp-dialog></media-theme-mux>'
16
+ `<media-theme-mux class="size-" stream-type="" player-size="" default-hidden-captions="" forward-seek-offset="" backward-seek-offset="" exportparts="${exportParts}"><mux-video slot="media" crossorigin="" playsinline="" player-software-name="" player-software-version=""></mux-video><button slot="seek-to-live-button" part="seek-live button" class="mxp-seek-to-live-button" aria-disabled="">\n Live\n </button><mxp-dialog no-auto-hide="" open=""><p></p></mxp-dialog></media-theme-mux>`
15
17
  );
16
18
  });
17
19
 
@@ -29,7 +31,7 @@ describe('<mux-player> template render', () => {
29
31
  div.querySelectorAll('svg').forEach((svg) => svg.remove());
30
32
  assert.equal(
31
33
  minify(div.innerHTML),
32
- '<media-theme-mux class="size-extra-small" stream-type="on-demand" player-size="extra-small" default-hidden-captions="" forward-seek-offset="" backward-seek-offset=""><mux-video slot="media" crossorigin="" playsinline="" player-software-name="" player-software-version="" stream-type="on-demand"></mux-video><button slot="seek-to-live-button" aria-disabled="" class="mxp-seek-to-live-button">\n Live\n </button><mxp-dialog no-auto-hide="" open=""><h3>Errr</h3><p></p></mxp-dialog></media-theme-mux>'
34
+ `<media-theme-mux class="size-extra-small" stream-type="on-demand" player-size="extra-small" default-hidden-captions="" forward-seek-offset="" backward-seek-offset="" exportparts="${exportParts}"><mux-video slot="media" crossorigin="" playsinline="" player-software-name="" player-software-version="" stream-type="on-demand"></mux-video><button slot="seek-to-live-button" part="seek-live button" class="mxp-seek-to-live-button" aria-disabled="">\n Live\n </button><mxp-dialog no-auto-hide="" open=""><h3>Errr</h3><p></p></mxp-dialog></media-theme-mux>`
33
35
  );
34
36
  });
35
37
 
@@ -45,7 +47,7 @@ describe('<mux-player> template render', () => {
45
47
  div.querySelectorAll('svg').forEach((svg) => svg.remove());
46
48
  assert.equal(
47
49
  minify(div.innerHTML),
48
- '<media-theme-mux class="size-large" stream-type="on-demand" player-size="large" default-hidden-captions="" forward-seek-offset="" backward-seek-offset=""><mux-video slot="media" crossorigin="" playsinline="" player-software-name="" player-software-version="" stream-type="on-demand"></mux-video><button slot="seek-to-live-button" aria-disabled="" class="mxp-seek-to-live-button">\n Live\n </button><mxp-dialog no-auto-hide="" open=""><p></p></mxp-dialog></media-theme-mux>'
50
+ `<media-theme-mux class="size-large" stream-type="on-demand" player-size="large" default-hidden-captions="" forward-seek-offset="" backward-seek-offset="" exportparts="${exportParts}"><mux-video slot="media" crossorigin="" playsinline="" player-software-name="" player-software-version="" stream-type="on-demand"></mux-video><button slot="seek-to-live-button" part="seek-live button" class="mxp-seek-to-live-button" aria-disabled="">\n Live\n </button><mxp-dialog no-auto-hide="" open=""><p></p></mxp-dialog></media-theme-mux>`
49
51
  );
50
52
  });
51
53
 
@@ -64,7 +66,7 @@ describe('<mux-player> template render', () => {
64
66
  div.querySelectorAll('svg').forEach((svg) => svg.remove());
65
67
  assert.equal(
66
68
  minify(div.innerHTML),
67
- '<media-theme-mux class="size-large" stream-type="on-demand" player-size="large" default-hidden-captions="" forward-seek-offset="" backward-seek-offset=""><mux-video slot="media" crossorigin="" playsinline="" player-software-name="" player-software-version="" stream-type="on-demand"></mux-video><button slot="seek-to-live-button" aria-disabled="" class="mxp-seek-to-live-button">\n Live\n </button><mxp-dialog no-auto-hide="" open=""><h3>Errr</h3><p></p></mxp-dialog></media-theme-mux>'
69
+ `<media-theme-mux class="size-large" stream-type="on-demand" player-size="large" default-hidden-captions="" forward-seek-offset="" backward-seek-offset="" exportparts="${exportParts}"><mux-video slot="media" crossorigin="" playsinline="" player-software-name="" player-software-version="" stream-type="on-demand"></mux-video><button slot="seek-to-live-button" part="seek-live button" class="mxp-seek-to-live-button" aria-disabled="">\n Live\n </button><mxp-dialog no-auto-hide="" open=""><h3>Errr</h3><p></p></mxp-dialog></media-theme-mux>`
68
70
  );
69
71
  });
70
72
  });