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

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/dist/index.d.mts CHANGED
@@ -163,10 +163,6 @@ interface PlayerEvents {
163
163
  * Callback when Mux analytics updates data
164
164
  */
165
165
  onMuxDataUpdate?: (data: MuxDataUpdatePayload) => void;
166
- /**
167
- * Callback when live state changes
168
- */
169
- onLiveStateChange?: (isLive: boolean) => void;
170
166
  /**
171
167
  * Callback when live status changes (includes edge proximity)
172
168
  */
@@ -175,6 +171,40 @@ interface PlayerEvents {
175
171
  isNearEdge: boolean;
176
172
  liveEdge?: number;
177
173
  }) => void;
174
+ /**
175
+ * Callback when video time updates
176
+ * Provides different data for regular videos vs live streams
177
+ */
178
+ onTimeUpdate?: (timeData: TimeUpdateData) => void;
179
+ }
180
+ /**
181
+ * Time update data for both regular videos and live streams
182
+ */
183
+ interface TimeUpdateData {
184
+ /**
185
+ * Current playback position in seconds
186
+ */
187
+ currentTime: number;
188
+ /**
189
+ * Total duration in seconds (Infinity for live streams)
190
+ */
191
+ duration: number;
192
+ /**
193
+ * Whether this is a live stream
194
+ */
195
+ isLive: boolean;
196
+ /**
197
+ * For live streams: the live edge position in seconds
198
+ */
199
+ liveEdge?: number;
200
+ /**
201
+ * For live streams: how far behind the live edge (in seconds)
202
+ */
203
+ timeBehindLive?: number;
204
+ /**
205
+ * For regular videos: playback progress as percentage (0-100)
206
+ */
207
+ progress?: number;
178
208
  }
179
209
  /**
180
210
  * Seekbar color configuration
@@ -666,4 +696,4 @@ interface BigPlayIconProps {
666
696
  }
667
697
  declare const BigPlayIcon: React.FC<BigPlayIconProps>;
668
698
 
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 };
699
+ export { BigPlayIcon, CreativeWork, type CreativeWorkData, type CreativeWorkProps, CreativeWorksSortDirection, Event, type EventData, type EventProps, EventsSortDirection, type IconSizes, Player, type PlayerEvents, type PlayerProps, QueryProvider, SkipBackIcon, SkipForwardIcon, type TimeUpdateData, Video, type VideoData, type VideoProps, queryClient };
package/dist/index.d.ts CHANGED
@@ -163,10 +163,6 @@ interface PlayerEvents {
163
163
  * Callback when Mux analytics updates data
164
164
  */
165
165
  onMuxDataUpdate?: (data: MuxDataUpdatePayload) => void;
166
- /**
167
- * Callback when live state changes
168
- */
169
- onLiveStateChange?: (isLive: boolean) => void;
170
166
  /**
171
167
  * Callback when live status changes (includes edge proximity)
172
168
  */
@@ -175,6 +171,40 @@ interface PlayerEvents {
175
171
  isNearEdge: boolean;
176
172
  liveEdge?: number;
177
173
  }) => void;
174
+ /**
175
+ * Callback when video time updates
176
+ * Provides different data for regular videos vs live streams
177
+ */
178
+ onTimeUpdate?: (timeData: TimeUpdateData) => void;
179
+ }
180
+ /**
181
+ * Time update data for both regular videos and live streams
182
+ */
183
+ interface TimeUpdateData {
184
+ /**
185
+ * Current playback position in seconds
186
+ */
187
+ currentTime: number;
188
+ /**
189
+ * Total duration in seconds (Infinity for live streams)
190
+ */
191
+ duration: number;
192
+ /**
193
+ * Whether this is a live stream
194
+ */
195
+ isLive: boolean;
196
+ /**
197
+ * For live streams: the live edge position in seconds
198
+ */
199
+ liveEdge?: number;
200
+ /**
201
+ * For live streams: how far behind the live edge (in seconds)
202
+ */
203
+ timeBehindLive?: number;
204
+ /**
205
+ * For regular videos: playback progress as percentage (0-100)
206
+ */
207
+ progress?: number;
178
208
  }
179
209
  /**
180
210
  * Seekbar color configuration
@@ -666,4 +696,4 @@ interface BigPlayIconProps {
666
696
  }
667
697
  declare const BigPlayIcon: React.FC<BigPlayIconProps>;
668
698
 
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 };
699
+ export { BigPlayIcon, CreativeWork, type CreativeWorkData, type CreativeWorkProps, CreativeWorksSortDirection, Event, type EventData, type EventProps, EventsSortDirection, type IconSizes, Player, type PlayerEvents, type PlayerProps, QueryProvider, SkipBackIcon, SkipForwardIcon, type TimeUpdateData, Video, type VideoData, type VideoProps, queryClient };
package/dist/index.js CHANGED
@@ -490,7 +490,7 @@ var supportsWidevinePersistentLicenses = () => {
490
490
  var import_mux_data_shakaplayer = __toESM(require("@mux/mux-data-shakaplayer"));
491
491
 
492
492
  // package.json
493
- var version = "1.0.1-rc.80";
493
+ var version = "1.0.1-rc.82";
494
494
 
495
495
  // src/utils/licenseCache.ts
496
496
  var PERSISTENT_LICENSE_PREFIX = "motto_lic_";
@@ -1611,17 +1611,43 @@ var useShakaUI = (playerRef, containerRef, videoRef, controls, chromecastConfig,
1611
1611
 
1612
1612
  // src/hooks/useEventHandlers.ts
1613
1613
  var import_react7 = require("react");
1614
- var useEventHandlers = (videoRef, handlers) => {
1614
+ var useEventHandlers = (videoRef, playerRef, handlers) => {
1615
+ const timeUpdateHandlerRef = (0, import_react7.useRef)(null);
1615
1616
  const setupEventListeners = (0, import_react7.useCallback)(() => {
1616
1617
  const video = videoRef.current;
1617
1618
  if (!video) return;
1618
- const { onPlay, onPause, onEnded, onLoadStart, onCanPlay } = handlers;
1619
+ const { onPlay, onPause, onEnded, onLoadStart, onCanPlay, onTimeUpdate } = handlers;
1619
1620
  if (onPlay) video.addEventListener("play", onPlay);
1620
1621
  if (onPause) video.addEventListener("pause", onPause);
1621
1622
  if (onEnded) video.addEventListener("ended", onEnded);
1622
1623
  if (onLoadStart) video.addEventListener("loadstart", onLoadStart);
1623
1624
  if (onCanPlay) video.addEventListener("canplay", onCanPlay);
1624
- }, [videoRef, handlers]);
1625
+ if (onTimeUpdate) {
1626
+ const handleTimeUpdate = () => {
1627
+ const player = playerRef.current;
1628
+ const currentTime = video.currentTime;
1629
+ const duration = video.duration;
1630
+ const isLive = player && typeof player.isLive === "function" ? player.isLive() : false;
1631
+ const timeData = {
1632
+ currentTime,
1633
+ duration,
1634
+ isLive
1635
+ };
1636
+ if (isLive && player && typeof player.seekRange === "function") {
1637
+ const seekRange = player.seekRange();
1638
+ if (seekRange && seekRange.end !== void 0) {
1639
+ timeData.liveEdge = seekRange.end;
1640
+ timeData.timeBehindLive = seekRange.end - currentTime;
1641
+ }
1642
+ } else if (duration && isFinite(duration) && duration > 0) {
1643
+ timeData.progress = currentTime / duration * 100;
1644
+ }
1645
+ onTimeUpdate(timeData);
1646
+ };
1647
+ timeUpdateHandlerRef.current = handleTimeUpdate;
1648
+ video.addEventListener("timeupdate", handleTimeUpdate);
1649
+ }
1650
+ }, [videoRef, playerRef, handlers]);
1625
1651
  const cleanupEventListeners = (0, import_react7.useCallback)(() => {
1626
1652
  const video = videoRef.current;
1627
1653
  if (!video) return;
@@ -1631,6 +1657,10 @@ var useEventHandlers = (videoRef, handlers) => {
1631
1657
  if (onEnded) video.removeEventListener("ended", onEnded);
1632
1658
  if (onLoadStart) video.removeEventListener("loadstart", onLoadStart);
1633
1659
  if (onCanPlay) video.removeEventListener("canplay", onCanPlay);
1660
+ if (timeUpdateHandlerRef.current) {
1661
+ video.removeEventListener("timeupdate", timeUpdateHandlerRef.current);
1662
+ timeUpdateHandlerRef.current = null;
1663
+ }
1634
1664
  }, [videoRef, handlers]);
1635
1665
  return {
1636
1666
  setupEventListeners,
@@ -1660,23 +1690,21 @@ var useLiveIndicator = (containerRef, playerRef, options = {}) => {
1660
1690
  return { isLive: false, isNearEdge: false };
1661
1691
  }
1662
1692
  try {
1663
- if (!player.getManifest || typeof player.getManifest !== "function") {
1693
+ if (typeof player.isLive !== "function") {
1664
1694
  return { isLive: false, isNearEdge: false };
1665
1695
  }
1666
- const manifest = player.getManifest();
1667
- if (!manifest) {
1668
- return { isLive: false, isNearEdge: false };
1669
- }
1670
- const timeline = manifest.presentationTimeline;
1671
- if (!timeline || typeof timeline.isLive !== "function") {
1672
- return { isLive: false, isNearEdge: false };
1673
- }
1674
- const isLiveStream = timeline.isLive();
1696
+ const isLiveStream = player.isLive();
1675
1697
  if (!isLiveStream) return { isLive: false, isNearEdge: false };
1676
1698
  const videoElement = player.getMediaElement?.();
1677
1699
  if (!videoElement) return { isLive: true, isNearEdge: false };
1678
- const liveEdge = timeline.getSeekRangeEnd?.() ?? timeline.getSegmentAvailabilityEnd?.();
1679
- if (liveEdge === void 0) return { isLive: true, isNearEdge: false };
1700
+ if (typeof player.seekRange !== "function") {
1701
+ return { isLive: true, isNearEdge: false };
1702
+ }
1703
+ const seekRange = player.seekRange();
1704
+ if (!seekRange || seekRange.end === void 0) {
1705
+ return { isLive: true, isNearEdge: false };
1706
+ }
1707
+ const liveEdge = seekRange.end;
1680
1708
  const currentTime = videoElement.currentTime;
1681
1709
  const timeBehindLive = liveEdge - currentTime;
1682
1710
  return {
@@ -1693,15 +1721,13 @@ var useLiveIndicator = (containerRef, playerRef, options = {}) => {
1693
1721
  const player = playerRef.current;
1694
1722
  if (!player) return;
1695
1723
  try {
1696
- const manifest = player.getManifest();
1697
- if (!manifest) return;
1698
- const timeline = manifest.presentationTimeline;
1699
- const liveEdge = timeline?.getSeekRangeEnd?.() ?? timeline?.getSegmentAvailabilityEnd?.();
1700
- if (liveEdge !== void 0) {
1701
- const videoElement = player.getMediaElement?.();
1702
- if (videoElement) {
1703
- videoElement.currentTime = liveEdge;
1704
- }
1724
+ if (typeof player.seekRange !== "function") return;
1725
+ const seekRange = player.seekRange();
1726
+ if (!seekRange || seekRange.end === void 0) return;
1727
+ const liveEdge = seekRange.end;
1728
+ const videoElement = player.getMediaElement?.();
1729
+ if (videoElement) {
1730
+ videoElement.currentTime = liveEdge;
1705
1731
  }
1706
1732
  } catch (error) {
1707
1733
  console.error("Error seeking to live edge:", error);
@@ -2235,12 +2261,13 @@ var Player = (0, import_react12.forwardRef)(
2235
2261
  skipForward,
2236
2262
  enabled: true
2237
2263
  });
2238
- const { setupEventListeners, cleanupEventListeners } = useEventHandlers(videoRef, {
2264
+ const { setupEventListeners, cleanupEventListeners } = useEventHandlers(videoRef, playerRef, {
2239
2265
  onPlay: events?.onPlay,
2240
2266
  onPause: events?.onPause,
2241
2267
  onEnded: events?.onEnded,
2242
2268
  onLoadStart: events?.onLoadStart,
2243
- onCanPlay: events?.onCanPlay
2269
+ onCanPlay: events?.onCanPlay,
2270
+ onTimeUpdate: events?.onTimeUpdate
2244
2271
  });
2245
2272
  const { uiRef, initializeUI, destroyUI } = useShakaUI(
2246
2273
  playerRef,