@mottosports/motto-video-player 1.0.1-rc.8 → 1.0.1-rc.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,6 +8,7 @@ React video player component for the Motto platform, powered by Shaka Player wit
8
8
  - 🔄 **TanStack Query Integration**: Advanced caching, background refetching, and error handling
9
9
  - 📱 **Responsive Design**: Automatic aspect ratio handling and mobile-friendly controls
10
10
  - 🎮 **Skip Controls**: Built-in skip back/forward buttons with customizable durations
11
+ - ⌨️ **Keyboard Controls**: Desktop keyboard shortcuts (arrows for skip, spacebar for play/pause)
11
12
  - 🎯 **Quality Control**: Automatic quality selection and manual quality switching
12
13
  - 📊 **Analytics**: Built-in Mux analytics support
13
14
  - 🖥️ **Chromecast Support**: Cast videos to compatible devices
@@ -20,6 +21,34 @@ React video player component for the Motto platform, powered by Shaka Player wit
20
21
  npm install @motto-ui-components/motto-video-player @tanstack/react-query
21
22
  ```
22
23
 
24
+ ### Tailwind CSS Setup (Required)
25
+
26
+ This package uses Tailwind CSS utility classes. You must have Tailwind CSS configured in your project:
27
+
28
+ 1. **Install Tailwind CSS** (if not already installed):
29
+ ```bash
30
+ npm install -D tailwindcss
31
+ ```
32
+
33
+ 2. **Configure Tailwind to scan the package files**. Add this to your `tailwind.config.js`:
34
+ ```js
35
+ module.exports = {
36
+ content: [
37
+ './src/**/*.{js,jsx,ts,tsx}',
38
+ // Add this line to scan the motto-video-player package
39
+ './node_modules/@mottosports/motto-video-player/dist/**/*.{js,mjs}'
40
+ ],
41
+ // ... rest of your config
42
+ }
43
+ ```
44
+
45
+ 3. **Import Tailwind in your CSS**:
46
+ ```css
47
+ @tailwind base;
48
+ @tailwind components;
49
+ @tailwind utilities;
50
+ ```
51
+
23
52
  ## Quick Start
24
53
 
25
54
  ### Setup QueryClient (Required for Video wrapper)
@@ -126,6 +155,16 @@ function MyPlayer() {
126
155
  />
127
156
  ```
128
157
 
158
+ ### Keyboard Controls
159
+
160
+ Desktop users can control the player using keyboard shortcuts:
161
+
162
+ - **←** Left Arrow: Skip back 15 seconds
163
+ - **→** Right Arrow: Skip forward 15 seconds
164
+ - **Space**: Play/Pause toggle
165
+
166
+ Keyboard controls are automatically enabled on desktop devices (disabled on mobile) and work when the player is focused or when no input fields are active.
167
+
129
168
  ### Responsive Sizing
130
169
 
131
170
  ```jsx
package/dist/index.d.mts CHANGED
@@ -1,6 +1,77 @@
1
1
  import React, { HTMLAttributes } from 'react';
2
2
  import { QueryClient } from '@tanstack/react-query';
3
3
 
4
+ interface VideoData {
5
+ id: string;
6
+ name?: string;
7
+ description?: string;
8
+ playlists?: Playlist[];
9
+ error?: string;
10
+ ad?: {
11
+ adTagUrl?: string;
12
+ };
13
+ }
14
+ interface DVRSettings {
15
+ window_size_seconds: number;
16
+ }
17
+ interface Widevine {
18
+ playlistUrl: string;
19
+ licenseUrl: string;
20
+ }
21
+ interface Fairplay {
22
+ certificateUrl: string;
23
+ licenseUrl: string;
24
+ playlistUrl: string;
25
+ }
26
+ interface Playready {
27
+ playlistUrl: string;
28
+ licenseUrl: string;
29
+ }
30
+ interface DRM {
31
+ token?: string;
32
+ licenseCacheKey?: string;
33
+ widevine?: Widevine;
34
+ fairplay?: Fairplay;
35
+ playready?: Playready;
36
+ }
37
+ interface Playlist {
38
+ id: string;
39
+ url: string;
40
+ format: string;
41
+ dvr_settings?: DVRSettings;
42
+ drm: DRM;
43
+ }
44
+
45
+ interface EventData {
46
+ id: string;
47
+ title: string;
48
+ description?: string;
49
+ startTime: string;
50
+ endTime?: string;
51
+ posterUrl?: string;
52
+ videoIds?: string[];
53
+ error?: string;
54
+ }
55
+ declare enum EventsSortDirection {
56
+ ASC = "asc",
57
+ DESC = "desc"
58
+ }
59
+
60
+ interface CreativeWorkData {
61
+ id: string;
62
+ title: string;
63
+ description?: string;
64
+ releaseTime: string;
65
+ endTime?: string;
66
+ posterUrl?: string;
67
+ videoIds?: string[];
68
+ error?: string;
69
+ }
70
+ declare enum CreativeWorksSortDirection {
71
+ ASC = "asc",
72
+ DESC = "desc"
73
+ }
74
+
4
75
  /**
5
76
  * Unified events interface for both Player and Video wrapper
6
77
  */
@@ -52,6 +123,26 @@ interface PlayerEvents {
52
123
  * Callback when ad error occurs
53
124
  */
54
125
  onAdError?: (error: any) => void;
126
+ /**
127
+ * Callback when ad is skipped
128
+ */
129
+ onAdSkipped?: () => void;
130
+ /**
131
+ * Callback when ad is paused
132
+ */
133
+ onAdPaused?: () => void;
134
+ /**
135
+ * Callback when ad is resumed
136
+ */
137
+ onAdResumed?: () => void;
138
+ /**
139
+ * Callback when ad progress updates
140
+ */
141
+ onAdProgress?: (adProgressData: any) => void;
142
+ /**
143
+ * Callback when all ads are completed
144
+ */
145
+ onAllAdsCompleted?: () => void;
55
146
  /**
56
147
  * Callback when Chromecast state changes
57
148
  */
@@ -76,6 +167,14 @@ interface PlayerEvents {
76
167
  * Callback when live state changes
77
168
  */
78
169
  onLiveStateChange?: (isLive: boolean) => void;
170
+ /**
171
+ * Callback when live status changes (includes edge proximity)
172
+ */
173
+ onLiveStatusChange?: (status: {
174
+ isLive: boolean;
175
+ isNearEdge: boolean;
176
+ liveEdge?: number;
177
+ }) => void;
79
178
  }
80
179
  /**
81
180
  * Seekbar color configuration
@@ -94,11 +193,30 @@ interface SeekbarConfig {
94
193
  */
95
194
  played?: string;
96
195
  }
196
+ /**
197
+ * Icon size configuration
198
+ */
199
+ interface IconSizes {
200
+ /**
201
+ * Size for skip back/forward buttons (in pixels)
202
+ */
203
+ skipButtons?: number;
204
+ /**
205
+ * Size for the big play button (in pixels)
206
+ */
207
+ bigPlayButton?: number;
208
+ }
97
209
  interface PlayerProps extends Omit<HTMLAttributes<HTMLVideoElement>, 'src' | 'onError'> {
98
210
  /**
99
- * The source URL of the video (DASH, HLS, or regular MP4)
211
+ * The source URL of the video (DASH, HLS, or regular MP4) or playlist object with DRM info.
212
+ * Can be a plain URL string or a Playlist object.
100
213
  */
101
- src: string;
214
+ src: Playlist | string;
215
+ /**
216
+ * When true, player only reinitializes based on playlist presence rather than src changes.
217
+ * Used internally by Event, CreativeWork, and Video wrappers to optimize reinitialization.
218
+ */
219
+ managedMode?: boolean;
102
220
  /**
103
221
  * Whether the video should autoplay
104
222
  */
@@ -138,7 +256,7 @@ interface PlayerProps extends Omit<HTMLAttributes<HTMLVideoElement>, 'src' | 'on
138
256
  */
139
257
  shakaConfig?: any;
140
258
  /**
141
- * DRM configuration for protected content
259
+ * DRM configuration for protected content (deprecated - now derived from src playlist)
142
260
  */
143
261
  drmConfig?: {
144
262
  clearKeys?: {
@@ -152,6 +270,10 @@ interface PlayerProps extends Omit<HTMLAttributes<HTMLVideoElement>, 'src' | 'on
152
270
  * Mux Analytics configuration
153
271
  */
154
272
  muxConfig?: MuxAnalyticsConfig;
273
+ /**
274
+ * System73 SDK configuration
275
+ */
276
+ system73Config?: System73Config;
155
277
  /**
156
278
  * IMA (Interactive Media Ads) configuration
157
279
  */
@@ -180,21 +302,15 @@ interface PlayerProps extends Omit<HTMLAttributes<HTMLVideoElement>, 'src' | 'on
180
302
  nonLinearAdSlotHeight?: number;
181
303
  };
182
304
  /**
183
- * Chromecast configuration
305
+ * Chromecast configuration (optional)
306
+ * Chromecast is always enabled by default. This config allows customization.
184
307
  */
185
308
  chromecastConfig?: {
186
- /**
187
- * Whether to enable Chromecast support
188
- */
189
- enabled?: boolean;
190
309
  /**
191
310
  * Custom receiver application ID
311
+ * Defaults to 'CC1AD845' (Google's default media receiver)
192
312
  */
193
313
  receiverApplicationId?: string;
194
- /**
195
- * Whether to auto-join cast sessions
196
- */
197
- autoJoinPolicy?: string;
198
314
  };
199
315
  /**
200
316
  * Quality selection configuration
@@ -221,11 +337,36 @@ interface PlayerProps extends Omit<HTMLAttributes<HTMLVideoElement>, 'src' | 'on
221
337
  * Seekbar color configuration
222
338
  */
223
339
  seekbarConfig?: SeekbarConfig;
340
+ /**
341
+ * Icon size configuration
342
+ */
343
+ iconSizes?: IconSizes;
224
344
  /**
225
345
  * Event callbacks
226
346
  */
227
347
  events?: PlayerEvents;
348
+ /**
349
+ * Locale for Shaka Player UI localization (e.g., 'en', 'ar', 'es')
350
+ * Defaults to 'en' if not provided
351
+ */
352
+ locale?: string;
228
353
  containerClassName?: string;
354
+ /**
355
+ * Threshold in seconds to consider "near live edge" for live streams (default: 15)
356
+ */
357
+ liveThresholdSeconds?: number;
358
+ /**
359
+ * Motto public key used for authenticated requests
360
+ */
361
+ publicKey?: string;
362
+ /**
363
+ * Authentication context for player operations
364
+ */
365
+ auth?: {
366
+ mottoToken?: string;
367
+ userId?: string;
368
+ apiToken?: string;
369
+ };
229
370
  }
230
371
  /**
231
372
  * Mux Analytics type definitions
@@ -319,64 +460,51 @@ interface MuxAnalyticsConfig {
319
460
  */
320
461
  metadata?: MuxMetadata;
321
462
  }
322
-
323
- declare const Player: React.ForwardRefExoticComponent<PlayerProps & React.RefAttributes<HTMLVideoElement>>;
324
-
325
- interface VideoData {
326
- id: string;
327
- name?: string;
328
- description?: string;
329
- playlists?: Array<{
330
- url: string;
331
- format: string;
332
- }>;
333
- error?: string;
334
- }
335
- interface VideoListItem {
336
- id: string;
337
- name?: string;
338
- description?: string;
339
- playlists?: Array<{
340
- url: string;
341
- format: string;
342
- }>;
343
- error?: string;
344
- }
345
-
346
- interface EventData {
347
- id: string;
348
- title: string;
349
- description?: string;
350
- startTime: string;
351
- endTime?: string;
352
- posterUrl?: string;
353
- videoIds?: string[];
354
- error?: string;
463
+ /**
464
+ * System73 SDK configuration
465
+ */
466
+ interface System73Config {
467
+ /**
468
+ * System73 API key (required for authentication)
469
+ */
470
+ apiKey: string;
471
+ /**
472
+ * Content steering endpoint URI (optional)
473
+ */
474
+ contentSteeringEndpoint?: string;
475
+ /**
476
+ * Channel identifier (optional)
477
+ */
478
+ channelId?: string;
355
479
  }
356
- declare enum EventsSortDirection {
357
- ASC = "asc",
358
- DESC = "desc"
480
+ /**
481
+ * System73 SDK wrapper interface
482
+ */
483
+ declare global {
484
+ interface Window {
485
+ S73ShakaPlayerWrapper?: (config: System73Config, shakaInstance: {
486
+ shaka: any;
487
+ }) => {
488
+ wrapPlayerConfig: (config: any) => void;
489
+ wrapPlayer: (player: any) => void;
490
+ };
491
+ }
359
492
  }
360
493
 
361
- interface CreativeWorkData {
362
- id: string;
363
- title: string;
364
- description?: string;
365
- releaseTime: string;
366
- endTime?: string;
367
- posterUrl?: string;
368
- videoIds?: string[];
369
- error?: string;
370
- }
371
- declare enum CreativeWorksSortDirection {
372
- ASC = "asc",
373
- DESC = "desc"
494
+ declare global {
495
+ namespace google {
496
+ namespace ima {
497
+ class AdsRequest {
498
+ adTagUrl: string;
499
+ }
500
+ }
501
+ }
374
502
  }
503
+ declare const Player: React.ForwardRefExoticComponent<PlayerProps & React.RefAttributes<HTMLVideoElement>>;
375
504
 
376
505
  interface VideoProps extends Omit<PlayerProps, 'src'> {
377
506
  videoId?: string;
378
507
  publicKey?: string;
379
- mottoToken?: string;
380
508
  videoData?: VideoData;
381
509
  refetchInterval?: number;
382
510
  playerName?: string;
@@ -391,9 +519,24 @@ interface VideoProps extends Omit<PlayerProps, 'src'> {
391
519
  onLoadStart?: () => void;
392
520
  onCanPlay?: () => void;
393
521
  onPlayerReady?: () => void;
522
+ onAdStart?: () => void;
523
+ onAdComplete?: () => void;
524
+ onAdError?: (error: any) => void;
525
+ onAdSkipped?: () => void;
526
+ onAdPaused?: () => void;
527
+ onAdResumed?: () => void;
528
+ onAdProgress?: (adProgressData: any) => void;
529
+ onAllAdsCompleted?: () => void;
394
530
  };
395
531
  children?: React.ReactNode;
396
532
  className?: string;
533
+ auth?: {
534
+ mottoToken?: string;
535
+ userId?: string;
536
+ };
537
+ settings?: {
538
+ backgroundImageUrl?: string;
539
+ };
397
540
  queryOptions?: {
398
541
  enabled?: boolean;
399
542
  staleTime?: number;
@@ -401,10 +544,11 @@ interface VideoProps extends Omit<PlayerProps, 'src'> {
401
544
  retry?: number;
402
545
  retryDelay?: number;
403
546
  };
547
+ adsEnabled?: boolean;
404
548
  }
405
549
  declare const Video: React.FC<VideoProps>;
406
550
 
407
- interface EventProps extends Omit<PlayerProps, 'src'> {
551
+ interface EventProps extends Omit<PlayerProps, 'src' | 'drmConfig'> {
408
552
  publicKey: string;
409
553
  eventId: string;
410
554
  hideTitle?: boolean;
@@ -413,7 +557,7 @@ interface EventProps extends Omit<PlayerProps, 'src'> {
413
557
  order?: EventsSortDirection;
414
558
  events?: {
415
559
  onEventData?: (event: EventData) => void;
416
- onVideoData?: (video: VideoListItem) => void;
560
+ onVideoData?: (video: VideoData) => void;
417
561
  onEmptyPlaylists?: () => void;
418
562
  onError?: (error: Error) => void;
419
563
  onPlay?: () => void;
@@ -422,6 +566,14 @@ interface EventProps extends Omit<PlayerProps, 'src'> {
422
566
  onLoadStart?: () => void;
423
567
  onCanPlay?: () => void;
424
568
  onPlayerReady?: () => void;
569
+ onAdStart?: () => void;
570
+ onAdComplete?: () => void;
571
+ onAdError?: (error: any) => void;
572
+ onAdSkipped?: () => void;
573
+ onAdPaused?: () => void;
574
+ onAdResumed?: () => void;
575
+ onAdProgress?: (adProgressData: any) => void;
576
+ onAllAdsCompleted?: () => void;
425
577
  };
426
578
  className?: string;
427
579
  settings?: {
@@ -439,6 +591,7 @@ interface EventProps extends Omit<PlayerProps, 'src'> {
439
591
  retry?: number;
440
592
  retryDelay?: number;
441
593
  };
594
+ adsEnabled?: boolean;
442
595
  }
443
596
  declare const Event: React.FC<EventProps>;
444
597
 
@@ -451,7 +604,7 @@ interface CreativeWorkProps extends Omit<PlayerProps, 'src'> {
451
604
  order?: CreativeWorksSortDirection;
452
605
  events?: {
453
606
  onCreativeWorkData?: (creativeWork: CreativeWorkData) => void;
454
- onVideoData?: (video: VideoListItem) => void;
607
+ onVideoData?: (video: VideoData) => void;
455
608
  onEmptyPlaylists?: () => void;
456
609
  onError?: (error: Error) => void;
457
610
  onPlay?: () => void;
@@ -460,6 +613,14 @@ interface CreativeWorkProps extends Omit<PlayerProps, 'src'> {
460
613
  onLoadStart?: () => void;
461
614
  onCanPlay?: () => void;
462
615
  onPlayerReady?: () => void;
616
+ onAdStart?: () => void;
617
+ onAdComplete?: () => void;
618
+ onAdError?: (error: any) => void;
619
+ onAdSkipped?: () => void;
620
+ onAdPaused?: () => void;
621
+ onAdResumed?: () => void;
622
+ onAdProgress?: (adProgressData: any) => void;
623
+ onAllAdsCompleted?: () => void;
463
624
  };
464
625
  className?: string;
465
626
  settings?: {
@@ -477,6 +638,7 @@ interface CreativeWorkProps extends Omit<PlayerProps, 'src'> {
477
638
  retry?: number;
478
639
  retryDelay?: number;
479
640
  };
641
+ adsEnabled?: boolean;
480
642
  }
481
643
  declare const CreativeWork: React.FC<CreativeWorkProps>;
482
644
 
@@ -486,4 +648,22 @@ interface QueryProviderProps {
486
648
  }
487
649
  declare const QueryProvider: React.FC<QueryProviderProps>;
488
650
 
489
- export { CreativeWork, type CreativeWorkData, type CreativeWorkProps, CreativeWorksSortDirection, Event, type EventData, type EventProps, EventsSortDirection, Player, type PlayerEvents, type PlayerProps, QueryProvider, Video, type VideoData, type VideoListItem, type VideoProps, queryClient };
651
+ interface SkipBackIconProps {
652
+ size?: number;
653
+ className?: string;
654
+ }
655
+ declare const SkipBackIcon: React.FC<SkipBackIconProps>;
656
+
657
+ interface SkipForwardIconProps {
658
+ size?: number;
659
+ className?: string;
660
+ }
661
+ declare const SkipForwardIcon: React.FC<SkipForwardIconProps>;
662
+
663
+ interface BigPlayIconProps {
664
+ size?: number;
665
+ className?: string;
666
+ }
667
+ declare const BigPlayIcon: React.FC<BigPlayIconProps>;
668
+
669
+ export { BigPlayIcon, CreativeWork, type CreativeWorkData, type CreativeWorkProps, CreativeWorksSortDirection, Event, type EventData, type EventProps, EventsSortDirection, type IconSizes, Player, type PlayerEvents, type PlayerProps, QueryProvider, SkipBackIcon, SkipForwardIcon, Video, type VideoData, type VideoProps, queryClient };