@mottosports/motto-video-player 1.0.0 → 1.0.1-rc.1

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
@@ -20,6 +20,70 @@ React video player component for the Motto platform, powered by Shaka Player wit
20
20
  npm install @motto-ui-components/motto-video-player @tanstack/react-query
21
21
  ```
22
22
 
23
+ ## Next.js SSR Compatibility
24
+
25
+ This component is now fully compatible with Next.js Server-Side Rendering (SSR). The component automatically detects when it's running in a server environment and gracefully handles browser-only APIs.
26
+
27
+ ### Basic Usage in Next.js
28
+
29
+ ```tsx
30
+ import { Event } from '@mottosports/motto-video-player';
31
+
32
+ export default function MyPage() {
33
+ return (
34
+ <Event
35
+ publicKey="your-public-key"
36
+ eventId="your-event-id"
37
+ locale="en"
38
+ />
39
+ );
40
+ }
41
+ ```
42
+
43
+ ### Dynamic Imports (Optional)
44
+
45
+ For optimal performance and to ensure the component only loads on the client side, you can use Next.js dynamic imports:
46
+
47
+ ```tsx
48
+ import dynamic from 'next/dynamic';
49
+
50
+ const Event = dynamic(
51
+ () => import('@mottosports/motto-video-player').then(mod => ({ default: mod.Event })),
52
+ {
53
+ ssr: false,
54
+ loading: () => <div>Loading video player...</div>
55
+ }
56
+ );
57
+
58
+ export default function MyPage() {
59
+ return (
60
+ <Event
61
+ publicKey="your-public-key"
62
+ eventId="your-event-id"
63
+ locale="en"
64
+ />
65
+ );
66
+ }
67
+ ```
68
+
69
+ ### App Router Usage (Next.js 13+)
70
+
71
+ ```tsx
72
+ 'use client';
73
+
74
+ import { Event } from '@mottosports/motto-video-player';
75
+
76
+ export default function VideoPlayer() {
77
+ return (
78
+ <Event
79
+ publicKey="your-public-key"
80
+ eventId="your-event-id"
81
+ locale="en"
82
+ />
83
+ );
84
+ }
85
+ ```
86
+
23
87
  ## Quick Start
24
88
 
25
89
  ### Setup QueryClient (Required for Video wrapper)
package/dist/index.js CHANGED
@@ -309,6 +309,10 @@ var SkipBackButton = class {
309
309
  this.eventManager = { listen: (element, event, handler) => {
310
310
  element.addEventListener(event, handler);
311
311
  } };
312
+ if (typeof document === "undefined") {
313
+ console.warn("SkipBackButton: document is not available (SSR environment)");
314
+ return;
315
+ }
312
316
  this.button_ = document.createElement("button");
313
317
  this.button_.className = "shaka-button motto-native-skip-button";
314
318
  this.button_.innerHTML = `
@@ -339,6 +343,10 @@ var SkipForwardButton = class {
339
343
  this.eventManager = { listen: (element, event, handler) => {
340
344
  element.addEventListener(event, handler);
341
345
  } };
346
+ if (typeof document === "undefined") {
347
+ console.warn("SkipForwardButton: document is not available (SSR environment)");
348
+ return;
349
+ }
342
350
  this.button_ = document.createElement("button");
343
351
  this.button_.className = "shaka-button motto-native-skip-button";
344
352
  this.button_.innerHTML = `
@@ -382,6 +390,10 @@ var MobilePlayButton = class {
382
390
  constructor(parent, controls) {
383
391
  this.parent = parent;
384
392
  this.controls = controls;
393
+ if (typeof document === "undefined") {
394
+ console.warn("MobilePlayButton: document is not available (SSR environment)");
395
+ return;
396
+ }
385
397
  this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
386
398
  if (!this.video) {
387
399
  console.error("MobilePlayButton: No video element found");
@@ -426,6 +438,10 @@ var MobileSkipBackButton = class {
426
438
  constructor(parent, controls, onSkipBack) {
427
439
  this.parent = parent;
428
440
  this.controls = controls;
441
+ if (typeof document === "undefined") {
442
+ console.warn("MobileSkipBackButton: document is not available (SSR environment)");
443
+ return;
444
+ }
429
445
  this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
430
446
  if (!this.video) {
431
447
  console.error("MobileSkipBackButton: No video element found");
@@ -457,6 +473,10 @@ var MobileSkipForwardButton = class {
457
473
  constructor(parent, controls, onSkipForward) {
458
474
  this.parent = parent;
459
475
  this.controls = controls;
476
+ if (typeof document === "undefined") {
477
+ console.warn("MobileSkipForwardButton: document is not available (SSR environment)");
478
+ return;
479
+ }
460
480
  this.video = controls?.getVideo?.() || parent.querySelector("video") || document.querySelector("video");
461
481
  if (!this.video) {
462
482
  console.error("MobileSkipForwardButton: No video element found");
@@ -488,6 +508,10 @@ var MobileControlsContainer = class {
488
508
  constructor(parent, controls, onSkipBack, onSkipForward) {
489
509
  this.parent = parent;
490
510
  this.controls = controls;
511
+ if (typeof document === "undefined") {
512
+ console.warn("MobileControlsContainer: document is not available (SSR environment)");
513
+ return;
514
+ }
491
515
  if (!parent) {
492
516
  console.error("MobileControlsContainer: No parent element provided");
493
517
  return;
@@ -545,6 +569,9 @@ var MobileControlsContainer = class {
545
569
  }
546
570
  }
547
571
  isElementVisible(element) {
572
+ if (typeof window === "undefined") {
573
+ return false;
574
+ }
548
575
  const style = window.getComputedStyle(element);
549
576
  const hasHiddenClass = element.classList.contains("shaka-hidden") || element.classList.contains("hidden") || element.classList.contains("shaka-fade-out");
550
577
  return style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && !element.hidden && !hasHiddenClass;
@@ -563,10 +590,14 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
563
590
  const uiRef = (0, import_react5.useRef)(null);
564
591
  const registeredElements = (0, import_react5.useRef)(/* @__PURE__ */ new Set());
565
592
  const initializeUI = (0, import_react5.useCallback)(async () => {
593
+ if (typeof window === "undefined" || typeof document === "undefined") {
594
+ console.warn("useShakaUI: Cannot initialize UI in SSR environment");
595
+ return null;
596
+ }
566
597
  if (!controls || !containerRef.current || !playerRef.current || !videoRef.current) {
567
598
  return null;
568
599
  }
569
- const isMobile = window.innerWidth <= 767 || /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
600
+ const isMobile = typeof window !== "undefined" && typeof navigator !== "undefined" && (window.innerWidth <= 767 || /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent));
570
601
  if (!registeredElements.current.has("skip_back_button")) {
571
602
  import_shaka_player3.ui.Controls.registerElement("skip_back_button", new SkipBackButtonFactory(onSkipBack));
572
603
  registeredElements.current.add("skip_back_button");
@@ -760,6 +791,9 @@ var useLiveIndicator = (containerRef, options = {}) => {
760
791
  showPulseAnimation = true
761
792
  } = options;
762
793
  (0, import_react9.useEffect)(() => {
794
+ if (typeof window === "undefined" || typeof document === "undefined") {
795
+ return;
796
+ }
763
797
  if (!containerRef.current || !enabled) {
764
798
  return;
765
799
  }
@@ -1822,6 +1856,9 @@ var availableLanguages = {
1822
1856
  fa: fa_default
1823
1857
  };
1824
1858
  var getBrowserLanguage = () => {
1859
+ if (typeof window === "undefined" || typeof navigator === "undefined") {
1860
+ return "en";
1861
+ }
1825
1862
  const language = navigator.language.split("-")[0];
1826
1863
  return availableLanguages[language] ? language : "en";
1827
1864
  };