@gcorevideo/player 2.24.13 → 2.25.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 (41) hide show
  1. package/assets/clips/clips.ejs +1 -1
  2. package/assets/clips/clips.scss +7 -5
  3. package/assets/dvr-controls/dvr_controls.scss +19 -20
  4. package/assets/media-control/width370.scss +3 -5
  5. package/dist/core.js +1 -1
  6. package/dist/index.css +689 -693
  7. package/dist/index.embed.js +172 -101
  8. package/dist/index.js +150 -78
  9. package/dist/player.d.ts +106 -42
  10. package/docs/api/player.md +18 -20
  11. package/docs/api/player.mediacontrol.defaultsettings.md +32 -0
  12. package/docs/api/player.mediacontrol.extendsettings.md +77 -0
  13. package/docs/api/player.mediacontrol.md +31 -11
  14. package/docs/api/player.mediacontrol.mount.md +8 -8
  15. package/docs/api/player.mediacontrol.slot.md +97 -0
  16. package/docs/api/player.mediacontrolelement.md +6 -3
  17. package/docs/api/player.mediacontrolpluginsettings.md +13 -0
  18. package/docs/api/player.mediacontrolsettings.md +5 -5
  19. package/docs/api/{player.mediacontrol.enablecontrolbutton.md → player.mediacontrolslotmountpoint.md} +4 -8
  20. package/docs/api/{player.mediacontrol.disabledcontrolbutton.md → player.standardmediacontrolelement.md} +4 -8
  21. package/lib/plugins/clips/Clips.d.ts +1 -0
  22. package/lib/plugins/clips/Clips.d.ts.map +1 -1
  23. package/lib/plugins/clips/Clips.js +16 -2
  24. package/lib/plugins/dvr-controls/DvrControls.js +1 -1
  25. package/lib/plugins/media-control/MediaControl.d.ts +87 -34
  26. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  27. package/lib/plugins/media-control/MediaControl.js +121 -76
  28. package/package.json +1 -1
  29. package/src/plugins/clips/Clips.ts +17 -2
  30. package/src/plugins/clips/__tests__/Clips.test.ts +1 -1
  31. package/src/plugins/clips/__tests__/__snapshots__/Clips.test.ts.snap +1 -1
  32. package/src/plugins/dvr-controls/DvrControls.ts +1 -1
  33. package/src/plugins/dvr-controls/__tests__/DvrControls.test.ts +1 -1
  34. package/src/plugins/media-control/MediaControl.ts +170 -141
  35. package/src/plugins/media-control/__tests__/MediaControl.test.ts +24 -17
  36. package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +125 -93
  37. package/temp/player.api.json +186 -108
  38. package/tsconfig.tsbuildinfo +1 -1
  39. package/docs/api/player.mediacontrollayerelement.md +0 -16
  40. package/docs/api/player.mediacontrolleftelement.md +0 -16
  41. package/docs/api/player.mediacontrolrightelement.md +0 -16
@@ -38,60 +38,36 @@ import volumeOffIcon from '../../../assets/icons/new/volume-off.svg'
38
38
  import fullscreenOffIcon from '../../../assets/icons/new/fullscreen-off.svg'
39
39
  import fullscreenOnIcon from '../../../assets/icons/new/fullscreen-on.svg'
40
40
 
41
+ const STANDARD_MEDIA_CONTROL_ELEMENTS: string[] = [
42
+ 'duration',
43
+ 'fullscreen',
44
+ 'hd-indicator',
45
+ 'playpause',
46
+ 'playstop',
47
+ 'position',
48
+ 'seekbar',
49
+ 'volume',
50
+ ]
51
+
41
52
  /**
42
- * Media control elements that appear in the left area.
53
+ * Built-in media control elements.
43
54
  * @beta
44
55
  */
45
- export type MediaControlLeftElement =
46
- | 'clipText' // TODO lowercase
56
+ export type StandardMediaControlElement =
47
57
  | 'duration'
48
- | 'dvr'
58
+ | 'fullscreen'
59
+ | 'hd-indicator'
49
60
  | 'playpause'
50
61
  | 'playstop'
51
62
  | 'position'
63
+ | 'seekbar'
52
64
  | 'volume'
53
- | 'clips'
54
65
 
55
66
  /**
56
- * Media control elements that appear in main layer, spanning the entire width of the player.
67
+ * Identifies a location for mounting custom media control elements.
57
68
  * @beta
58
69
  */
59
- export type MediaControlLayerElement = 'seekbar' | 'seekBarContainer' | '_' // TODO remove seekbar
60
-
61
- /**
62
- * Media control elements that appear in the right area.
63
- * @beta
64
- */
65
- export type MediaControlRightElement =
66
- | 'audiotracks'
67
- | 'cc'
68
- | 'fullscreen'
69
- | 'hd-indicator'
70
- | 'gear'
71
- | 'multicamera'
72
- | 'pip'
73
- | 'vr'
74
-
75
- /**
76
- * Built-in media control elements.
77
- * @beta
78
- */
79
- export type MediaControlElement =
80
- | MediaControlLeftElement
81
- | MediaControlLayerElement
82
- | MediaControlRightElement
83
-
84
- const MANAGED_ELEMENTS: MediaControlElement[] = [
85
- 'dvr',
86
- 'duration',
87
- 'fullscreen',
88
- 'hd-indicator',
89
- 'position',
90
- 'seekbar',
91
- 'volume',
92
- ]
93
-
94
- export type MediaControlSlotSelector =
70
+ export type MediaControlSlotMountPoint =
95
71
  | 'root'
96
72
  | 'base'
97
73
  | 'left'
@@ -100,28 +76,36 @@ export type MediaControlSlotSelector =
100
76
  | 'seekbar'
101
77
 
102
78
  /**
103
- * Specifies the allowed media control elements in each area.
104
- * Can be used to restrict rendered media control elements.
79
+ * Media control element.
80
+ * Each element's token in the media control layout settings determines where the element is rendered.
81
+ * @beta
82
+ * @remarks
83
+ * Standard media control elements are defined in the {@link StandardMediaControlElement} type.
84
+ * Custom media control elements can be identified by a unique token.
85
+ */
86
+ export type MediaControlElement = string
87
+
88
+ /**
89
+ * Specifies the layout of media control elements.
90
+ * Actual elements will be rendered according to the playback settings. Custom elements rendered by the plugins
91
+ * will be mounted at the specified locations.
105
92
  * @beta
106
93
  */
107
94
  export type MediaControlSettings = {
108
- left: MediaControlLeftElement[]
109
- right: MediaControlRightElement[]
110
- default: MediaControlLayerElement[]
95
+ left: MediaControlElement[]
96
+ right: MediaControlElement[]
97
+ default: MediaControlElement[]
111
98
  seekEnabled: boolean
112
99
  }
113
100
 
101
+ // TODO export
114
102
  const DEFAULT_SETTINGS: MediaControlSettings = {
115
- default: [],
116
- left: ['dvr'],
103
+ default: ['seekbar'],
104
+ left: ['playpause', 'playstop', 'position', 'duration', 'volume'],
117
105
  right: [
118
- 'audiotracks',
119
- 'cc',
106
+ '*',
107
+ // 'hd-indicator',
120
108
  'fullscreen',
121
- 'gear',
122
- 'multicamera',
123
- 'pip',
124
- 'vr',
125
109
  ],
126
110
  seekEnabled: true,
127
111
  }
@@ -135,15 +119,6 @@ const INITIAL_SETTINGS: MediaControlSettings = {
135
119
 
136
120
  const T = 'plugins.media_control'
137
121
 
138
- const LEFT_ORDER = [
139
- 'playpause',
140
- 'playstop',
141
- 'volume',
142
- 'position',
143
- 'duration',
144
- 'dvr',
145
- ]
146
-
147
122
  /**
148
123
  * Extended events for the {@link MediaControl} plugin
149
124
  * @beta
@@ -155,33 +130,25 @@ export enum ExtendedEvents {
155
130
 
156
131
  const { Config, Fullscreen, formatTime, extend, removeArrayItem } = Utils
157
132
 
158
- function orderByOrderPattern(arr: string[], order: string[]): string[] {
159
- const arrWithoutDuplicates = [...new Set(arr)]
160
- const ordered = order.filter((item) => arrWithoutDuplicates.includes(item))
161
-
162
- const rest = arrWithoutDuplicates.filter((item) => !order.includes(item))
163
-
164
- return [...ordered, ...rest]
165
- }
166
-
167
- type DisabledClickable = {
168
- el: ZeptoResult
169
- pointerEventValue: string
133
+ export type MediaControlPluginSettings = {
134
+ hideMediaControlDelay?: number
170
135
  }
171
136
 
172
137
  /**
173
- * `PLUGIN` that provides basic playback controls UI and a foundation for developing custom UI.
138
+ * `PLUGIN` that provides framework for building media control UI.
174
139
  * @beta
175
140
  * @remarks
176
141
  * The methods exposed are to be used by the other plugins that extend the media control UI.
177
142
  *
178
- * Configuration options:
143
+ * Configuration options (root level)
144
+ *
145
+ * - `hideMediaControlDelay`: number - specifies the delay in milliseconds before the media control UI is hidden after the last user interaction
179
146
  *
180
- * - `mediaControl`: {@link MediaControlSettings} - specifies the allowed media control elements in each area
147
+ * - `mediaControl`: {@link MediaControlSettings} - specifies the media control dashboard layout
181
148
  *
182
149
  * - `persistConfig`: boolean - `common` option, makes the plugin persist the media control settings
183
150
  *
184
- * - `chromeless`: boolean
151
+ * - `chromeless`: boolean - `common` option, hides the media control UI
185
152
  */
186
153
  export class MediaControl extends UICorePlugin {
187
154
  // private advertisementPlaying = false
@@ -192,7 +159,7 @@ export class MediaControl extends UICorePlugin {
192
159
  private currentPositionValue: number = 0
193
160
  private currentSeekBarPercentage = 0
194
161
 
195
- private disabledClickableList: DisabledClickable[] = []
162
+ // private disabledClickableList: DisabledClickable[] = []
196
163
  private displayedDuration: string | null = null
197
164
  private displayedPosition: string | null = null
198
165
  private displayedSeekBarPercentage: number | null = null
@@ -236,8 +203,6 @@ export class MediaControl extends UICorePlugin {
236
203
 
237
204
  private $fullscreenToggle: ZeptoResult | null = null
238
205
 
239
- private $multiCameraSelector: ZeptoResult | null = null
240
-
241
206
  private $playPauseToggle: ZeptoResult | null = null
242
207
 
243
208
  private $playStopToggle: ZeptoResult | null = null
@@ -282,6 +247,48 @@ export class MediaControl extends UICorePlugin {
282
247
  return { min: CLAPPR_VERSION }
283
248
  }
284
249
 
250
+ /**
251
+ * @returns Default media control layout settings
252
+ * @remark
253
+ * The method can be used to change the default dashboard layout, for example, removing the standard UI elements
254
+ * @example
255
+ * ```ts
256
+ * const settings = MediaControl.defaultSettings()
257
+ * settings.left = settings.filter(item => item !== 'playpause' && item !== 'playstop')
258
+ * ...
259
+ * new Player({
260
+ * mediaControl: settings,
261
+ * })
262
+ * ```
263
+ */
264
+ static defaultSettings() {
265
+ return $.extend(true, {}, DEFAULT_SETTINGS)
266
+ }
267
+
268
+ /**
269
+ * Extend the default media control layout settings
270
+ * @param settings - Additional settings
271
+ * @returns The extended settings
272
+ * @remarks
273
+ * This method allows adding custom elements to the media control dashboard.
274
+ * The default settings are not modified.
275
+ * @example
276
+ * ```ts
277
+ * new Player({
278
+ * mediaControl: MediaControl.extendSettings({
279
+ * left: ['*'], // add all custom elements to the left panel
280
+ * }),
281
+ * })
282
+ * ```
283
+ */
284
+ static extendSettings(settings: Partial<MediaControlSettings>) {
285
+ return {
286
+ left: mergeElements(DEFAULT_SETTINGS.left, settings.left ?? []),
287
+ right: mergeElements(DEFAULT_SETTINGS.right, settings.right ?? []),
288
+ default: mergeElements(DEFAULT_SETTINGS.default, settings.default ?? []),
289
+ }
290
+ }
291
+
285
292
  private get disabled() {
286
293
  const playbackIsNOOP =
287
294
  this.core.activeContainer &&
@@ -648,10 +655,8 @@ export class MediaControl extends UICorePlugin {
648
655
  }
649
656
 
650
657
  private changeTogglePlay() {
651
- // assert.ok(this.$playPauseToggle, 'play/pause toggle must be present');
652
658
  this.$playPauseToggle?.html('')
653
659
 
654
- // assert.ok(this.$playStopToggle, 'play/stop toggle must be present');
655
660
  this.$playStopToggle?.html('')
656
661
  if (this.container && this.container.isPlaying()) {
657
662
  this.$playPauseToggle?.append(pauseIcon)
@@ -1099,7 +1104,8 @@ export class MediaControl extends UICorePlugin {
1099
1104
  }
1100
1105
 
1101
1106
  private updateSettings() {
1102
- const newSettings = $.extend(
1107
+ // TODO use this.options.mediaControl to additionally filter the settings
1108
+ const container = $.extend(
1103
1109
  true,
1104
1110
  {
1105
1111
  left: [],
@@ -1109,44 +1115,34 @@ export class MediaControl extends UICorePlugin {
1109
1115
  this.core.activeContainer.settings,
1110
1116
  )
1111
1117
 
1112
- newSettings.left.push('clips') // TODO settings
1113
- // TODO make order controlled via CSS
1114
- newSettings.left = orderByOrderPattern(
1115
- [...newSettings.left, 'volume', 'clips'],
1116
- LEFT_ORDER,
1117
- )
1118
- if (
1119
- this.core.activePlayback.getPlaybackType() === Playback.LIVE &&
1120
- this.core.activePlayback.dvrEnabled
1121
- ) {
1122
- newSettings.left.push('dvr')
1123
- }
1118
+ container.left.push('volume')
1124
1119
 
1125
- // actual order of the items appear rendered is controlled by CSS
1126
- newSettings.right = DEFAULT_SETTINGS.right // TODO get from the options
1120
+ const setup = this.options.mediaControl ?? DEFAULT_SETTINGS
1127
1121
 
1128
1122
  if (
1129
1123
  (!this.fullScreenOnVideoTagSupported && !fullscreenEnabled()) ||
1130
1124
  this.options.fullscreenDisable
1131
1125
  ) {
1132
1126
  // remove fullscreen from settings if it is not available
1133
- removeArrayItem(newSettings.default, 'fullscreen')
1134
- removeArrayItem(newSettings.left, 'fullscreen')
1135
- removeArrayItem(newSettings.right, 'fullscreen')
1127
+ removeArrayItem(container.default, 'fullscreen')
1128
+ removeArrayItem(container.left, 'fullscreen')
1129
+ removeArrayItem(container.right, 'fullscreen')
1136
1130
  }
1137
1131
 
1138
- removeArrayItem(newSettings.default, 'hd-indicator')
1139
- removeArrayItem(newSettings.left, 'hd-indicator')
1140
-
1141
1132
  // TODO get from container's settings
1142
1133
  if (this.core.activePlayback.name === 'html5_video') {
1143
- newSettings.seekEnabled = this.isSeekEnabledForHtml5Playback()
1134
+ container.seekEnabled = this.isSeekEnabledForHtml5Playback()
1135
+ // TODO remove seekbar if seek is disabled?
1144
1136
  }
1145
1137
 
1146
- const settingsChanged = !isEqualSettings(this.settings, newSettings)
1138
+ container.left = evalSettings(container.left, setup.left)
1139
+ container.right = evalSettings(container.right, setup.right)
1140
+ container.default = evalSettings(container.default, setup.default)
1141
+
1142
+ const settingsChanged = !isEqualSettings(this.settings, container)
1147
1143
 
1148
1144
  if (settingsChanged) {
1149
- this.settings = newSettings
1145
+ this.settings = container
1150
1146
  this.hasUpdate = true
1151
1147
  this.render()
1152
1148
  }
@@ -1181,18 +1177,38 @@ export class MediaControl extends UICorePlugin {
1181
1177
  this.$volumeBarBackground = this.$el.find('.bar-background[data-volume]')
1182
1178
  this.$volumeBarFill = this.$el.find('.bar-fill-1[data-volume]')
1183
1179
  this.$volumeBarScrubber = this.$el.find('.bar-scrubber[data-volume]')
1184
- this.$multiCameraSelector = this.$el.find(
1185
- '.media-control-multicamera[data-multicamera]',
1186
- )
1187
1180
  this.resetIndicators()
1188
1181
  this.initializeIcons()
1189
1182
  }
1190
1183
 
1191
1184
  /**
1192
- * Get a media control element DOM node
1185
+ * Mount a media control to its configured location
1193
1186
  * @param name - The name of the media control element
1194
1187
  * @param element - The DOM node/fragment to mount
1195
- * @deprecated Use {@link MediaControl.mount} instead
1188
+ * @remarks
1189
+ * Media controls layout is configured via {@link MediaControlSettings}.
1190
+ * A plugin implementing custom elements on the media control dashboard,
1191
+ * should use this method to mount the element to the correct location.
1192
+ * The actual location is defined by the occurence of the element token in the `left`, `right` or `default` section
1193
+ * of the {@link MediaControlSettings}.
1194
+ * @example
1195
+ * ```ts
1196
+ * class MyPlugin extends UICorePlugin {
1197
+ * override render() {
1198
+ * // mount the element where it is configured in the layout
1199
+ * this.core.getPlugin('media_control').slot('my-element', this.$el)
1200
+ * }
1201
+ * }
1202
+ * ...
1203
+ * Player.registerPlugin(MyPlugin)
1204
+ * ...
1205
+ * // Configuration of the media control layout
1206
+ * new Player({
1207
+ * mediaControl: {
1208
+ * left: ['my-element'], // the element will be mounted to the left panel
1209
+ * },
1210
+ * })
1211
+ * ```
1196
1212
  */
1197
1213
  slot(name: MediaControlElement, element: ZeptoResult): void {
1198
1214
  const panel = this.getElementLocation(name)
@@ -1219,11 +1235,11 @@ export class MediaControl extends UICorePlugin {
1219
1235
  * }
1220
1236
  * ```
1221
1237
  */
1222
- mount(name: MediaControlSlotSelector, element: ZeptoResult) {
1238
+ mount(name: MediaControlSlotMountPoint, element: ZeptoResult) {
1223
1239
  mountTo(this.getMountParent(name), element)
1224
1240
  }
1225
1241
 
1226
- private getMountParent(name: MediaControlSlotSelector): ZeptoResult {
1242
+ private getMountParent(name: MediaControlSlotMountPoint): ZeptoResult {
1227
1243
  switch (name) {
1228
1244
  case 'root':
1229
1245
  return this.$el
@@ -1451,7 +1467,6 @@ export class MediaControl extends UICorePlugin {
1451
1467
  }
1452
1468
  const timeout = this.options.hideMediaControlDelay || 2000
1453
1469
 
1454
- trace(`${T} render`, { settings: this.settings })
1455
1470
  this.$el.html(MediaControl.template({ settings: this.settings }))
1456
1471
  // const style = Styler.getStyleFor(mediaControlStyle, { baseUrl: this.options.baseUrl });
1457
1472
  // this.$el.append(style[0]);
@@ -1572,24 +1587,6 @@ export class MediaControl extends UICorePlugin {
1572
1587
  return 0
1573
1588
  }
1574
1589
 
1575
- /**
1576
- * Enable the user interaction disabled earlier
1577
- */
1578
- enableControlButton() {
1579
- this.disabledClickableList.forEach((element) => {
1580
- element.el.css({ 'pointer-events': element.pointerEventValue })
1581
- })
1582
- }
1583
-
1584
- /**
1585
- * Disable the user interaction for the control buttons
1586
- */
1587
- disabledControlButton() {
1588
- this.disabledClickableList.forEach((element) => {
1589
- element.el.css({ 'pointer-events': 'none' })
1590
- })
1591
- }
1592
-
1593
1590
  // TODO drop
1594
1591
  private isSeekEnabledForHtml5Playback() {
1595
1592
  if (this.core.getPlaybackType() === Playback.LIVE) {
@@ -1600,13 +1597,16 @@ export class MediaControl extends UICorePlugin {
1600
1597
  }
1601
1598
 
1602
1599
  private getElementLocation(name: MediaControlElement) {
1603
- if (this.settings.right?.includes(name as MediaControlRightElement)) {
1604
- return this.getRightPanel()
1605
- }
1606
- if (this.settings.left?.includes(name as MediaControlLeftElement)) {
1600
+ if (this.settings.left.includes(name) || this.settings.left.includes('*')) {
1607
1601
  return this.getLeftPanel()
1608
1602
  }
1609
- if (this.settings.default?.includes(name as MediaControlLayerElement)) {
1603
+ if (
1604
+ this.settings.right.includes(name) ||
1605
+ this.settings.right.includes('*')
1606
+ ) {
1607
+ return this.getRightPanel()
1608
+ }
1609
+ if (this.settings.default.includes(name)) {
1610
1610
  return this.getCenterPanel()
1611
1611
  }
1612
1612
  return null
@@ -1626,7 +1626,8 @@ MediaControl.extend = function (properties) {
1626
1626
  }
1627
1627
 
1628
1628
  function serializeSettings(s: MediaControlSettings) {
1629
- return (s.left.slice() as MediaControlElement[])
1629
+ return s.left
1630
+ .slice()
1630
1631
  .sort()
1631
1632
  .concat(s.right.slice().sort())
1632
1633
  .concat(s.default.slice().sort())
@@ -1643,3 +1644,31 @@ function mountTo(parent: ZeptoResult, element: ZeptoResult) {
1643
1644
  parent.append(element)
1644
1645
  }
1645
1646
  }
1647
+
1648
+ function isStandardMediaControl(name: MediaControlElement) {
1649
+ return STANDARD_MEDIA_CONTROL_ELEMENTS.includes(name)
1650
+ }
1651
+
1652
+ function evalSettings(
1653
+ container: MediaControlElement[],
1654
+ setup: MediaControlElement[],
1655
+ ): MediaControlElement[] {
1656
+ return setup.filter((item) => {
1657
+ if (isStandardMediaControl(item)) {
1658
+ return container.includes(item)
1659
+ }
1660
+ return true
1661
+ })
1662
+ }
1663
+
1664
+ function mergeElements(
1665
+ a: MediaControlElement[],
1666
+ b: MediaControlElement[],
1667
+ ): MediaControlElement[] {
1668
+ return b.reduce((acc, item) => {
1669
+ if (!acc.includes(item)) {
1670
+ acc.push(item)
1671
+ }
1672
+ return acc
1673
+ }, a)
1674
+ }
@@ -1,9 +1,8 @@
1
1
  import { describe, it, expect, vi, beforeEach, MockedFunction } from 'vitest'
2
2
  import {
3
3
  MediaControl,
4
- MediaControlElement,
5
4
  MediaControlSettings,
6
- MediaControlSlotSelector,
5
+ MediaControlSlotMountPoint,
7
6
  } from '../MediaControl'
8
7
  import { createMockCore } from '../../../testUtils'
9
8
  import { $, Events, Playback } from '@clappr/core'
@@ -122,9 +121,13 @@ describe('MediaControl', () => {
122
121
  })
123
122
  })
124
123
  })
125
- // TODO drop, deprecated
126
124
  describe('slot', () => {
127
125
  beforeEach(async () => {
126
+ core.options.mediaControl = MediaControl.extendSettings({
127
+ left: ['dvr', 'clips'],
128
+ right: ['pip', 'gear', 'cc', 'audiotracks'],
129
+ default: ['seekbar'],
130
+ })
128
131
  mediaControl = new MediaControl(core)
129
132
  core.emit(Events.CORE_READY)
130
133
  core.emit(Events.CORE_ACTIVE_CONTAINER_CHANGED, core.activeContainer)
@@ -133,36 +136,40 @@ describe('MediaControl', () => {
133
136
  await runMetadataLoaded(core)
134
137
  })
135
138
  describe.each([
136
- ['pip' as MediaControlElement],
137
- ['gear' as MediaControlElement],
138
- ['cc' as MediaControlElement],
139
- // ['multicamera' as MediaControlElement],
140
- // ['playbackrate' as MediaControlElement],
141
- // ['vr' as MediaControlElement],
142
- ['audiotracks' as MediaControlElement],
139
+ ['pip', '.media-control-right-panel'],
140
+ ['gear', '.media-control-right-panel'],
141
+ ['cc', '.media-control-right-panel'],
142
+ ['audiotracks', '.media-control-right-panel'],
143
+ ['dvr', '.media-control-left-panel'],
144
+ ['clips', '.media-control-left-panel'],
143
145
  // dvr controls
144
- ])('%s', (mcName) => {
145
- it('should put the element in the right panel', () => {
146
+ ])('%s', (mcName, checkSelector) => {
147
+ it('should put the element according to layout', () => {
146
148
  const element = document.createElement('div')
147
149
  element.className = 'my-media-control'
150
+ element.id = 'my-media-control'
148
151
  element.textContent = 'test'
149
152
  mediaControl.slot(mcName, $(element))
150
153
 
151
154
  expect(mediaControl.el.innerHTML).toMatchSnapshot()
152
155
  expect(
153
- mediaControl.$el.find('.media-control-right-panel .my-media-control')
154
- .length,
156
+ mediaControl.$el.find(`${checkSelector} #my-media-control`).length,
155
157
  ).toEqual(1)
156
158
  })
157
159
  })
158
160
  })
159
161
  describe('mount', () => {
160
162
  beforeEach(async () => {
161
- mediaControl = new MediaControl(core)
162
163
  core.emit(Events.CORE_READY)
164
+ core.options.mediaControl = {
165
+ left: ['playpause', 'position', 'duration', 'volume'],
166
+ default: ['_'], // placeholder is needed because otherwise the panel is not rendered
167
+ right: ['fullscreen', 'hd-indicator'],
168
+ } as MediaControlSettings
169
+ mediaControl = new MediaControl(core)
163
170
  core.activeContainer.settings = {
164
171
  left: ['playpause', 'position', 'duration', 'volume'],
165
- default: ['_'],
172
+ default: [], // placeholder is needed because otherwise the panel is not rendered
166
173
  right: ['fullscreen', 'hd-indicator'],
167
174
  seekEnabled: true,
168
175
  } as MediaControlSettings
@@ -179,7 +186,7 @@ describe('MediaControl', () => {
179
186
  ])('%s', (name: string, checkSelector: string) => {
180
187
  it('should attach node to DOM tree', () => {
181
188
  mediaControl.mount(
182
- name as MediaControlSlotSelector,
189
+ name as MediaControlSlotMountPoint,
183
190
  $('<div id="test-element">test</div>'),
184
191
  )
185
192
  expect(mediaControl.el.innerHTML).toMatchSnapshot()