@livepeer-frameworks/player-react 0.1.0 → 0.1.2
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 +7 -9
- package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js +359 -0
- package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
- package/dist/cjs/assets/logomark.svg.js +8 -0
- package/dist/cjs/assets/logomark.svg.js.map +1 -0
- package/dist/cjs/components/DevModePanel.js +826 -0
- package/dist/cjs/components/DevModePanel.js.map +1 -0
- package/dist/cjs/components/DvdLogo.js +200 -0
- package/dist/cjs/components/DvdLogo.js.map +1 -0
- package/dist/cjs/components/Icons.js +439 -0
- package/dist/cjs/components/Icons.js.map +1 -0
- package/dist/cjs/components/IdleScreen.js +587 -0
- package/dist/cjs/components/IdleScreen.js.map +1 -0
- package/dist/cjs/components/LoadingScreen.js +523 -0
- package/dist/cjs/components/LoadingScreen.js.map +1 -0
- package/dist/cjs/components/Player.js +420 -0
- package/dist/cjs/components/Player.js.map +1 -0
- package/dist/cjs/components/PlayerControls.js +798 -0
- package/dist/cjs/components/PlayerControls.js.map +1 -0
- package/dist/cjs/components/PlayerErrorBoundary.js +80 -0
- package/dist/cjs/components/PlayerErrorBoundary.js.map +1 -0
- package/dist/cjs/components/SeekBar.js +253 -0
- package/dist/cjs/components/SeekBar.js.map +1 -0
- package/dist/cjs/components/SkipIndicator.js +92 -0
- package/dist/cjs/components/SkipIndicator.js.map +1 -0
- package/dist/cjs/components/SpeedIndicator.js +43 -0
- package/dist/cjs/components/SpeedIndicator.js.map +1 -0
- package/dist/cjs/components/StatsPanel.js +202 -0
- package/dist/cjs/components/StatsPanel.js.map +1 -0
- package/dist/cjs/components/StreamStateOverlay.js +229 -0
- package/dist/cjs/components/StreamStateOverlay.js.map +1 -0
- package/dist/cjs/components/ThumbnailOverlay.js +86 -0
- package/dist/cjs/components/ThumbnailOverlay.js.map +1 -0
- package/dist/cjs/components/TitleOverlay.js +32 -0
- package/dist/cjs/components/TitleOverlay.js.map +1 -0
- package/dist/cjs/context/PlayerContext.js +46 -0
- package/dist/cjs/context/PlayerContext.js.map +1 -0
- package/dist/cjs/hooks/useMetaTrack.js +165 -0
- package/dist/cjs/hooks/useMetaTrack.js.map +1 -0
- package/dist/cjs/hooks/usePlaybackQuality.js +131 -0
- package/dist/cjs/hooks/usePlaybackQuality.js.map +1 -0
- package/dist/cjs/hooks/usePlayerController.js +518 -0
- package/dist/cjs/hooks/usePlayerController.js.map +1 -0
- package/dist/cjs/hooks/usePlayerSelection.js +90 -0
- package/dist/cjs/hooks/usePlayerSelection.js.map +1 -0
- package/dist/cjs/hooks/useStreamState.js +360 -0
- package/dist/cjs/hooks/useStreamState.js.map +1 -0
- package/dist/cjs/hooks/useTelemetry.js +120 -0
- package/dist/cjs/hooks/useTelemetry.js.map +1 -0
- package/dist/cjs/hooks/useViewerEndpoints.js +222 -0
- package/dist/cjs/hooks/useViewerEndpoints.js.map +1 -0
- package/dist/cjs/index.js +97 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/ui/badge.js +34 -0
- package/dist/cjs/ui/badge.js.map +1 -0
- package/dist/cjs/ui/button.js +74 -0
- package/dist/cjs/ui/button.js.map +1 -0
- package/dist/cjs/ui/context-menu.js +163 -0
- package/dist/cjs/ui/context-menu.js.map +1 -0
- package/dist/cjs/ui/slider.js +60 -0
- package/dist/cjs/ui/slider.js.map +1 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +329 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js.map +1 -0
- package/dist/esm/assets/logomark.svg.js +4 -0
- package/dist/esm/assets/logomark.svg.js.map +1 -0
- package/dist/esm/components/DevModePanel.js +822 -0
- package/dist/esm/components/DevModePanel.js.map +1 -0
- package/dist/esm/components/DvdLogo.js +196 -0
- package/dist/esm/components/DvdLogo.js.map +1 -0
- package/dist/esm/components/Icons.js +421 -0
- package/dist/esm/components/Icons.js.map +1 -0
- package/dist/esm/components/IdleScreen.js +582 -0
- package/dist/esm/components/IdleScreen.js.map +1 -0
- package/dist/esm/components/LoadingScreen.js +519 -0
- package/dist/esm/components/LoadingScreen.js.map +1 -0
- package/dist/esm/components/Player.js +416 -0
- package/dist/esm/components/Player.js.map +1 -0
- package/dist/esm/components/PlayerControls.js +794 -0
- package/dist/esm/components/PlayerControls.js.map +1 -0
- package/dist/esm/components/PlayerErrorBoundary.js +76 -0
- package/dist/esm/components/PlayerErrorBoundary.js.map +1 -0
- package/dist/esm/components/SeekBar.js +249 -0
- package/dist/esm/components/SeekBar.js.map +1 -0
- package/dist/esm/components/SkipIndicator.js +88 -0
- package/dist/esm/components/SkipIndicator.js.map +1 -0
- package/dist/esm/components/SpeedIndicator.js +39 -0
- package/dist/esm/components/SpeedIndicator.js.map +1 -0
- package/dist/esm/components/StatsPanel.js +198 -0
- package/dist/esm/components/StatsPanel.js.map +1 -0
- package/dist/esm/components/StreamStateOverlay.js +224 -0
- package/dist/esm/components/StreamStateOverlay.js.map +1 -0
- package/dist/esm/components/ThumbnailOverlay.js +82 -0
- package/dist/esm/components/ThumbnailOverlay.js.map +1 -0
- package/dist/esm/components/TitleOverlay.js +28 -0
- package/dist/esm/components/TitleOverlay.js.map +1 -0
- package/dist/esm/context/PlayerContext.js +41 -0
- package/dist/esm/context/PlayerContext.js.map +1 -0
- package/dist/esm/hooks/useMetaTrack.js +163 -0
- package/dist/esm/hooks/useMetaTrack.js.map +1 -0
- package/dist/esm/hooks/usePlaybackQuality.js +129 -0
- package/dist/esm/hooks/usePlaybackQuality.js.map +1 -0
- package/dist/esm/hooks/usePlayerController.js +516 -0
- package/dist/esm/hooks/usePlayerController.js.map +1 -0
- package/dist/esm/hooks/usePlayerSelection.js +88 -0
- package/dist/esm/hooks/usePlayerSelection.js.map +1 -0
- package/dist/esm/hooks/useStreamState.js +358 -0
- package/dist/esm/hooks/useStreamState.js.map +1 -0
- package/dist/esm/hooks/useTelemetry.js +118 -0
- package/dist/esm/hooks/useTelemetry.js.map +1 -0
- package/dist/esm/hooks/useViewerEndpoints.js +220 -0
- package/dist/esm/hooks/useViewerEndpoints.js.map +1 -0
- package/dist/esm/index.js +23 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/ui/badge.js +31 -0
- package/dist/esm/ui/badge.js.map +1 -0
- package/dist/esm/ui/button.js +52 -0
- package/dist/esm/ui/button.js.map +1 -0
- package/dist/esm/ui/context-menu.js +132 -0
- package/dist/esm/ui/context-menu.js.map +1 -0
- package/dist/esm/ui/slider.js +38 -0
- package/dist/esm/ui/slider.js.map +1 -0
- package/dist/types/components/DvdLogo.d.ts +1 -1
- package/dist/types/components/Icons.d.ts +1 -1
- package/dist/types/components/Player.d.ts +1 -1
- package/dist/types/components/PlayerErrorBoundary.d.ts +2 -1
- package/dist/types/components/StreamStateOverlay.d.ts +2 -2
- package/dist/types/components/SubtitleRenderer.d.ts +2 -2
- package/dist/types/context/PlayerContext.d.ts +2 -2
- package/dist/types/context/index.d.ts +2 -2
- package/dist/types/hooks/useMetaTrack.d.ts +3 -3
- package/dist/types/hooks/usePlaybackQuality.d.ts +2 -2
- package/dist/types/hooks/usePlayerController.d.ts +26 -3
- package/dist/types/hooks/usePlayerSelection.d.ts +1 -1
- package/dist/types/hooks/useStreamState.d.ts +1 -1
- package/dist/types/hooks/useTelemetry.d.ts +1 -1
- package/dist/types/hooks/useViewerEndpoints.d.ts +3 -3
- package/dist/types/index.d.ts +28 -28
- package/dist/types/types.d.ts +3 -3
- package/dist/types/ui/select.d.ts +1 -1
- package/package.json +22 -14
- package/src/components/DevModePanel.tsx +244 -143
- package/src/components/DvdLogo.tsx +1 -1
- package/src/components/Icons.tsx +105 -25
- package/src/components/IdleScreen.tsx +262 -128
- package/src/components/LoadingScreen.tsx +169 -151
- package/src/components/LogoOverlay.tsx +3 -6
- package/src/components/Player.tsx +126 -59
- package/src/components/PlayerControls.tsx +384 -272
- package/src/components/PlayerErrorBoundary.tsx +7 -13
- package/src/components/SeekBar.tsx +96 -88
- package/src/components/SkipIndicator.tsx +2 -12
- package/src/components/SpeedIndicator.tsx +2 -11
- package/src/components/StatsPanel.tsx +31 -22
- package/src/components/StreamStateOverlay.tsx +105 -49
- package/src/components/SubtitleRenderer.tsx +29 -29
- package/src/components/ThumbnailOverlay.tsx +5 -6
- package/src/components/TitleOverlay.tsx +2 -8
- package/src/context/PlayerContext.tsx +4 -8
- package/src/context/index.ts +3 -3
- package/src/hooks/useMetaTrack.ts +27 -27
- package/src/hooks/usePlaybackQuality.ts +3 -3
- package/src/hooks/usePlayerController.ts +246 -138
- package/src/hooks/usePlayerSelection.ts +6 -6
- package/src/hooks/useStreamState.ts +51 -56
- package/src/hooks/useTelemetry.ts +18 -3
- package/src/hooks/useViewerEndpoints.ts +34 -23
- package/src/index.tsx +36 -28
- package/src/types.ts +8 -8
- package/src/ui/badge.tsx +6 -5
- package/src/ui/button.tsx +9 -8
- package/src/ui/context-menu.tsx +42 -61
- package/src/ui/select.tsx +13 -7
- package/src/ui/slider.tsx +18 -29
- package/dist/types/components/players/DashJsPlayer.d.ts +0 -18
- package/dist/types/components/players/HlsJsPlayer.d.ts +0 -18
- package/dist/types/components/players/MewsWsPlayer/index.d.ts +0 -18
- package/dist/types/components/players/MistPlayer.d.ts +0 -20
- package/dist/types/components/players/MistWebRTCPlayer/index.d.ts +0 -20
- package/dist/types/components/players/NativePlayer.d.ts +0 -19
- package/dist/types/components/players/VideoJsPlayer.d.ts +0 -18
- package/src/components/players/DashJsPlayer.tsx +0 -56
- package/src/components/players/HlsJsPlayer.tsx +0 -56
- package/src/components/players/MewsWsPlayer/index.tsx +0 -56
- package/src/components/players/MistPlayer.tsx +0 -60
- package/src/components/players/MistWebRTCPlayer/index.tsx +0 -59
- package/src/components/players/NativePlayer.tsx +0 -58
- package/src/components/players/VideoJsPlayer.tsx +0 -56
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _rollupPluginBabelHelpers = require('../_virtual/_rollupPluginBabelHelpers.js');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
var React = require('react');
|
|
8
|
+
var playerCore = require('@livepeer-frameworks/player-core');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Skip indicator overlay that appears when double-tapping to skip.
|
|
12
|
+
* Shows the skip direction and amount (e.g., "-10s" or "+10s") with a ripple effect.
|
|
13
|
+
*/
|
|
14
|
+
var SkipIndicator = function SkipIndicator(_ref) {
|
|
15
|
+
var direction = _ref.direction,
|
|
16
|
+
_ref$seconds = _ref.seconds,
|
|
17
|
+
seconds = _ref$seconds === void 0 ? 10 : _ref$seconds,
|
|
18
|
+
className = _ref.className,
|
|
19
|
+
onHide = _ref.onHide;
|
|
20
|
+
var _useState = React.useState(false),
|
|
21
|
+
_useState2 = _rollupPluginBabelHelpers.slicedToArray(_useState, 2),
|
|
22
|
+
isAnimating = _useState2[0],
|
|
23
|
+
setIsAnimating = _useState2[1];
|
|
24
|
+
React.useEffect(function () {
|
|
25
|
+
if (direction) {
|
|
26
|
+
setIsAnimating(true);
|
|
27
|
+
var timer = setTimeout(function () {
|
|
28
|
+
setIsAnimating(false);
|
|
29
|
+
onHide === null || onHide === void 0 || onHide();
|
|
30
|
+
}, 600);
|
|
31
|
+
return function () {
|
|
32
|
+
return clearTimeout(timer);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}, [direction, onHide]);
|
|
36
|
+
if (!direction) return null;
|
|
37
|
+
var isBack = direction === "back";
|
|
38
|
+
return jsxRuntime.jsxs("div", {
|
|
39
|
+
className: playerCore.cn("fw-skip-indicator absolute inset-0 z-30 pointer-events-none", "flex items-center", isBack ? "justify-start pl-8" : "justify-end pr-8", className),
|
|
40
|
+
children: [jsxRuntime.jsx("div", {
|
|
41
|
+
className: playerCore.cn("absolute top-0 bottom-0 w-1/3", isBack ? "left-0" : "right-0", "bg-white/10", isAnimating && "animate-pulse")
|
|
42
|
+
}), jsxRuntime.jsxs("div", {
|
|
43
|
+
className: playerCore.cn("relative flex flex-col items-center gap-1 text-white", "transition-all duration-200", isAnimating ? "opacity-100 scale-100" : "opacity-0 scale-75"),
|
|
44
|
+
children: [jsxRuntime.jsx("div", {
|
|
45
|
+
className: "flex",
|
|
46
|
+
children: isBack ? jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
47
|
+
children: [jsxRuntime.jsx(RewindIcon, {
|
|
48
|
+
className: "w-8 h-8"
|
|
49
|
+
}), jsxRuntime.jsx(RewindIcon, {
|
|
50
|
+
className: "w-8 h-8 -ml-4"
|
|
51
|
+
})]
|
|
52
|
+
}) : jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
53
|
+
children: [jsxRuntime.jsx(FastForwardIcon, {
|
|
54
|
+
className: "w-8 h-8"
|
|
55
|
+
}), jsxRuntime.jsx(FastForwardIcon, {
|
|
56
|
+
className: "w-8 h-8 -ml-4"
|
|
57
|
+
})]
|
|
58
|
+
})
|
|
59
|
+
}), jsxRuntime.jsx("span", {
|
|
60
|
+
className: "text-sm font-semibold tabular-nums",
|
|
61
|
+
children: isBack ? "-".concat(seconds, "s") : "+".concat(seconds, "s")
|
|
62
|
+
})]
|
|
63
|
+
})]
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
var RewindIcon = function RewindIcon(_ref2) {
|
|
67
|
+
var className = _ref2.className;
|
|
68
|
+
return jsxRuntime.jsx("svg", {
|
|
69
|
+
viewBox: "0 0 24 24",
|
|
70
|
+
fill: "currentColor",
|
|
71
|
+
className: className,
|
|
72
|
+
"aria-hidden": "true",
|
|
73
|
+
children: jsxRuntime.jsx("path", {
|
|
74
|
+
d: "M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z"
|
|
75
|
+
})
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
var FastForwardIcon = function FastForwardIcon(_ref3) {
|
|
79
|
+
var className = _ref3.className;
|
|
80
|
+
return jsxRuntime.jsx("svg", {
|
|
81
|
+
viewBox: "0 0 24 24",
|
|
82
|
+
fill: "currentColor",
|
|
83
|
+
className: className,
|
|
84
|
+
"aria-hidden": "true",
|
|
85
|
+
children: jsxRuntime.jsx("path", {
|
|
86
|
+
d: "M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z"
|
|
87
|
+
})
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
exports.default = SkipIndicator;
|
|
92
|
+
//# sourceMappingURL=SkipIndicator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SkipIndicator.js","sources":["../../../../src/components/SkipIndicator.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\nexport type SkipDirection = \"back\" | \"forward\" | null;\n\ninterface SkipIndicatorProps {\n direction: SkipDirection;\n seconds?: number;\n className?: string;\n onHide?: () => void;\n}\n\n/**\n * Skip indicator overlay that appears when double-tapping to skip.\n * Shows the skip direction and amount (e.g., \"-10s\" or \"+10s\") with a ripple effect.\n */\nconst SkipIndicator: React.FC<SkipIndicatorProps> = ({\n direction,\n seconds = 10,\n className,\n onHide,\n}) => {\n const [isAnimating, setIsAnimating] = useState(false);\n\n useEffect(() => {\n if (direction) {\n setIsAnimating(true);\n const timer = setTimeout(() => {\n setIsAnimating(false);\n onHide?.();\n }, 600);\n return () => clearTimeout(timer);\n }\n }, [direction, onHide]);\n\n if (!direction) return null;\n\n const isBack = direction === \"back\";\n\n return (\n <div\n className={cn(\n \"fw-skip-indicator absolute inset-0 z-30 pointer-events-none\",\n \"flex items-center\",\n isBack ? \"justify-start pl-8\" : \"justify-end pr-8\",\n className\n )}\n >\n {/* Ripple background */}\n <div\n className={cn(\n \"absolute top-0 bottom-0 w-1/3\",\n isBack ? \"left-0\" : \"right-0\",\n \"bg-white/10\",\n isAnimating && \"animate-pulse\"\n )}\n />\n\n {/* Skip content */}\n <div\n className={cn(\n \"relative flex flex-col items-center gap-1 text-white\",\n \"transition-all duration-200\",\n isAnimating ? \"opacity-100 scale-100\" : \"opacity-0 scale-75\"\n )}\n >\n {/* Icon */}\n <div className=\"flex\">\n {isBack ? (\n <>\n <RewindIcon className=\"w-8 h-8\" />\n <RewindIcon className=\"w-8 h-8 -ml-4\" />\n </>\n ) : (\n <>\n <FastForwardIcon className=\"w-8 h-8\" />\n <FastForwardIcon className=\"w-8 h-8 -ml-4\" />\n </>\n )}\n </div>\n\n {/* Text */}\n <span className=\"text-sm font-semibold tabular-nums\">\n {isBack ? `-${seconds}s` : `+${seconds}s`}\n </span>\n </div>\n </div>\n );\n};\n\nconst RewindIcon: React.FC<{ className?: string }> = ({ className }) => (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} aria-hidden=\"true\">\n <path d=\"M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z\" />\n </svg>\n);\n\nconst FastForwardIcon: React.FC<{ className?: string }> = ({ className }) => (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} aria-hidden=\"true\">\n <path d=\"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\" />\n </svg>\n);\n\nexport default SkipIndicator;\n"],"names":["SkipIndicator","_ref","direction","_ref$seconds","seconds","className","onHide","_useState","useState","_useState2","_slicedToArray","isAnimating","setIsAnimating","useEffect","timer","setTimeout","clearTimeout","isBack","_jsxs","cn","_jsx","children","_Fragment","RewindIcon","FastForwardIcon","concat","_ref2","viewBox","fill","d","_ref3"],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
var playerCore = require('@livepeer-frameworks/player-core');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Speed indicator overlay that appears when holding for fast-forward.
|
|
10
|
+
* Shows the current playback speed (e.g., "2x") in a pill overlay.
|
|
11
|
+
*/
|
|
12
|
+
var SpeedIndicator = function SpeedIndicator(_ref) {
|
|
13
|
+
var isVisible = _ref.isVisible,
|
|
14
|
+
speed = _ref.speed,
|
|
15
|
+
className = _ref.className;
|
|
16
|
+
return jsxRuntime.jsx("div", {
|
|
17
|
+
className: playerCore.cn("fw-speed-indicator absolute top-3 right-3 z-30 pointer-events-none", "transition-opacity duration-150", isVisible ? "opacity-100" : "opacity-0", className),
|
|
18
|
+
children: jsxRuntime.jsxs("div", {
|
|
19
|
+
className: playerCore.cn("bg-black/60 text-white px-2.5 py-1 rounded-md", "text-xs font-semibold tabular-nums", "flex items-center gap-2", "border border-white/15", "transform transition-transform duration-150", isVisible ? "scale-100" : "scale-90"),
|
|
20
|
+
children: [jsxRuntime.jsx(FastForwardIcon, {
|
|
21
|
+
className: "w-4 h-4"
|
|
22
|
+
}), jsxRuntime.jsxs("span", {
|
|
23
|
+
children: [speed, "x"]
|
|
24
|
+
})]
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
// Simple fast-forward icon
|
|
29
|
+
var FastForwardIcon = function FastForwardIcon(_ref2) {
|
|
30
|
+
var className = _ref2.className;
|
|
31
|
+
return jsxRuntime.jsx("svg", {
|
|
32
|
+
viewBox: "0 0 24 24",
|
|
33
|
+
fill: "currentColor",
|
|
34
|
+
className: className,
|
|
35
|
+
"aria-hidden": "true",
|
|
36
|
+
children: jsxRuntime.jsx("path", {
|
|
37
|
+
d: "M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z"
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
exports.default = SpeedIndicator;
|
|
43
|
+
//# sourceMappingURL=SpeedIndicator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SpeedIndicator.js","sources":["../../../../src/components/SpeedIndicator.tsx"],"sourcesContent":["import React from \"react\";\nimport { cn } from \"@livepeer-frameworks/player-core\";\n\ninterface SpeedIndicatorProps {\n isVisible: boolean;\n speed: number;\n className?: string;\n}\n\n/**\n * Speed indicator overlay that appears when holding for fast-forward.\n * Shows the current playback speed (e.g., \"2x\") in a pill overlay.\n */\nconst SpeedIndicator: React.FC<SpeedIndicatorProps> = ({ isVisible, speed, className }) => {\n return (\n <div\n className={cn(\n \"fw-speed-indicator absolute top-3 right-3 z-30 pointer-events-none\",\n \"transition-opacity duration-150\",\n isVisible ? \"opacity-100\" : \"opacity-0\",\n className\n )}\n >\n <div\n className={cn(\n \"bg-black/60 text-white px-2.5 py-1 rounded-md\",\n \"text-xs font-semibold tabular-nums\",\n \"flex items-center gap-2\",\n \"border border-white/15\",\n \"transform transition-transform duration-150\",\n isVisible ? \"scale-100\" : \"scale-90\"\n )}\n >\n <FastForwardIcon className=\"w-4 h-4\" />\n <span>{speed}x</span>\n </div>\n </div>\n );\n};\n\n// Simple fast-forward icon\nconst FastForwardIcon: React.FC<{ className?: string }> = ({ className }) => (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} aria-hidden=\"true\">\n <path d=\"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z\" />\n </svg>\n);\n\nexport default SpeedIndicator;\n"],"names":["SpeedIndicator","_ref","isVisible","speed","className","_jsx","cn","children","_jsxs","FastForwardIcon","_ref2","viewBox","fill","d"],"mappings":";;;;;;;AASA;;;AAGG;AACH,IAAMA,cAAc,GAAkC,SAAhDA,cAAcA,CAAAC,IAAA,EAAsE;AAAA,EAAA,IAAjCC,SAAS,GAAAD,IAAA,CAATC,SAAS;IAAEC,KAAK,GAAAF,IAAA,CAALE,KAAK;IAAEC,SAAS,GAAAH,IAAA,CAATG,SAAS;EAClF,OACEC,cAAA,CAAA,KAAA,EAAA;AACED,IAAAA,SAAS,EAAEE,aAAE,CACX,oEAAoE,EACpE,iCAAiC,EACjCJ,SAAS,GAAG,aAAa,GAAG,WAAW,EACvCE,SAAS,CACV;AAAAG,IAAAA,QAAA,EAEDC,eAAA,CAAA,KAAA,EAAA;AACEJ,MAAAA,SAAS,EAAEE,aAAE,CACX,+CAA+C,EAC/C,oCAAoC,EACpC,yBAAyB,EACzB,wBAAwB,EACxB,6CAA6C,EAC7CJ,SAAS,GAAG,WAAW,GAAG,UAAU,CACrC;AAAAK,MAAAA,QAAA,EAAA,CAEDF,cAAA,CAACI,eAAe,EAAA;AAACL,QAAAA,SAAS,EAAC;AAAS,OAAA,CAAG,EACvCI,eAAA,CAAA,MAAA,EAAA;AAAAD,QAAAA,QAAA,EAAA,CAAOJ,KAAK,EAAA,GAAA;AAAA,OAAA,CAAS;KAAA;AACjB,GAAA,CACF;AAEV;AAEA;AACA,IAAMM,eAAe,GAAqC,SAApDA,eAAeA,CAAAC,KAAA,EAAA;AAAA,EAAA,IAAwCN,SAAS,GAAAM,KAAA,CAATN,SAAS;EAAA,OACpEC,cAAA,CAAA,KAAA,EAAA;AAAKM,IAAAA,OAAO,EAAC,WAAW;AAACC,IAAAA,IAAI,EAAC,cAAc;AAACR,IAAAA,SAAS,EAAEA,SAAS;mBAAc,MAAM;AAAAG,IAAAA,QAAA,EACnFF,cAAA,CAAA,MAAA,EAAA;AAAMQ,MAAAA,CAAC,EAAC;KAAyC;AAAG,GAAA,CAChD;AAAA,CACP;;;;"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
var playerCore = require('@livepeer-frameworks/player-core');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* "Stats for nerds" panel showing detailed playback information.
|
|
10
|
+
* Toggleable overlay with technical details about the stream.
|
|
11
|
+
*/
|
|
12
|
+
var StatsPanel = function StatsPanel(_ref) {
|
|
13
|
+
var _video$playbackRate$t, _video$playbackRate, _quality$score$toFixe, _quality$score, _quality$frameDropRat, _quality$frameDropRat2, _quality$stallCount, _metadata$viewers, _ref2, _streamState$status, _metadata$mist, _mistInfo$type, _mistInfo$meta2;
|
|
14
|
+
var isOpen = _ref.isOpen,
|
|
15
|
+
onClose = _ref.onClose,
|
|
16
|
+
metadata = _ref.metadata,
|
|
17
|
+
streamState = _ref.streamState,
|
|
18
|
+
quality = _ref.quality,
|
|
19
|
+
videoElement = _ref.videoElement,
|
|
20
|
+
protocol = _ref.protocol,
|
|
21
|
+
nodeId = _ref.nodeId,
|
|
22
|
+
geoDistance = _ref.geoDistance;
|
|
23
|
+
if (!isOpen) return null;
|
|
24
|
+
// Video element stats
|
|
25
|
+
var video = videoElement;
|
|
26
|
+
var currentRes = video ? "".concat(video.videoWidth, "x").concat(video.videoHeight) : "—";
|
|
27
|
+
var buffered = video && video.buffered.length > 0 ? (video.buffered.end(video.buffered.length - 1) - video.currentTime).toFixed(1) : "—";
|
|
28
|
+
var playbackRate = (_video$playbackRate$t = video === null || video === void 0 || (_video$playbackRate = video.playbackRate) === null || _video$playbackRate === void 0 ? void 0 : _video$playbackRate.toFixed(2)) !== null && _video$playbackRate$t !== void 0 ? _video$playbackRate$t : "1.00";
|
|
29
|
+
// Quality monitor stats
|
|
30
|
+
var qualityScore = (_quality$score$toFixe = quality === null || quality === void 0 || (_quality$score = quality.score) === null || _quality$score === void 0 ? void 0 : _quality$score.toFixed(0)) !== null && _quality$score$toFixe !== void 0 ? _quality$score$toFixe : "—";
|
|
31
|
+
var bitrateKbps = quality !== null && quality !== void 0 && quality.bitrate ? "".concat((quality.bitrate / 1000).toFixed(0), " kbps") : "—";
|
|
32
|
+
var frameDropRate = (_quality$frameDropRat = quality === null || quality === void 0 || (_quality$frameDropRat2 = quality.frameDropRate) === null || _quality$frameDropRat2 === void 0 ? void 0 : _quality$frameDropRat2.toFixed(1)) !== null && _quality$frameDropRat !== void 0 ? _quality$frameDropRat : "—";
|
|
33
|
+
var stallCount = (_quality$stallCount = quality === null || quality === void 0 ? void 0 : quality.stallCount) !== null && _quality$stallCount !== void 0 ? _quality$stallCount : 0;
|
|
34
|
+
var latency = quality !== null && quality !== void 0 && quality.latency ? "".concat(Math.round(quality.latency), " ms") : "—";
|
|
35
|
+
// Stream state stats
|
|
36
|
+
var viewers = (_metadata$viewers = metadata === null || metadata === void 0 ? void 0 : metadata.viewers) !== null && _metadata$viewers !== void 0 ? _metadata$viewers : "—";
|
|
37
|
+
var streamStatus = (_ref2 = (_streamState$status = streamState === null || streamState === void 0 ? void 0 : streamState.status) !== null && _streamState$status !== void 0 ? _streamState$status : metadata === null || metadata === void 0 ? void 0 : metadata.status) !== null && _ref2 !== void 0 ? _ref2 : "—";
|
|
38
|
+
var mistInfo = (_metadata$mist = metadata === null || metadata === void 0 ? void 0 : metadata.mist) !== null && _metadata$mist !== void 0 ? _metadata$mist : streamState === null || streamState === void 0 ? void 0 : streamState.streamInfo;
|
|
39
|
+
var deriveTracksFromMist = function deriveTracksFromMist() {
|
|
40
|
+
var _mistInfo$meta;
|
|
41
|
+
var mistTracks = mistInfo === null || mistInfo === void 0 || (_mistInfo$meta = mistInfo.meta) === null || _mistInfo$meta === void 0 ? void 0 : _mistInfo$meta.tracks;
|
|
42
|
+
if (!mistTracks) return undefined;
|
|
43
|
+
return Object.values(mistTracks).map(function (t) {
|
|
44
|
+
return {
|
|
45
|
+
type: t.type,
|
|
46
|
+
codec: t.codec,
|
|
47
|
+
width: t.width,
|
|
48
|
+
height: t.height,
|
|
49
|
+
bitrate: typeof t.bps === "number" ? Math.round(t.bps) : undefined,
|
|
50
|
+
fps: typeof t.fpks === "number" ? t.fpks / 1000 : undefined,
|
|
51
|
+
channels: t.channels,
|
|
52
|
+
sampleRate: t.rate
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
// Format track info from metadata
|
|
57
|
+
var formatTracks = function formatTracks() {
|
|
58
|
+
var _metadata$tracks;
|
|
59
|
+
var tracks = (_metadata$tracks = metadata === null || metadata === void 0 ? void 0 : metadata.tracks) !== null && _metadata$tracks !== void 0 ? _metadata$tracks : deriveTracksFromMist();
|
|
60
|
+
if (!(tracks !== null && tracks !== void 0 && tracks.length)) return "—";
|
|
61
|
+
return tracks.map(function (t) {
|
|
62
|
+
var _t$codec2;
|
|
63
|
+
if (t.type === "video") {
|
|
64
|
+
var _t$codec;
|
|
65
|
+
var resolution = t.width && t.height ? "".concat(t.width, "x").concat(t.height) : "?";
|
|
66
|
+
var bitrate = t.bitrate ? "".concat(Math.round(t.bitrate / 1000), "kbps") : "?";
|
|
67
|
+
return "".concat((_t$codec = t.codec) !== null && _t$codec !== void 0 ? _t$codec : "?", " ").concat(resolution, "@").concat(bitrate);
|
|
68
|
+
}
|
|
69
|
+
var channels = t.channels ? "".concat(t.channels, "ch") : "?";
|
|
70
|
+
return "".concat((_t$codec2 = t.codec) !== null && _t$codec2 !== void 0 ? _t$codec2 : "?", " ").concat(channels);
|
|
71
|
+
}).join(", ");
|
|
72
|
+
};
|
|
73
|
+
var mistType = (_mistInfo$type = mistInfo === null || mistInfo === void 0 ? void 0 : mistInfo.type) !== null && _mistInfo$type !== void 0 ? _mistInfo$type : "—";
|
|
74
|
+
var mistBufferWindow = mistInfo === null || mistInfo === void 0 || (_mistInfo$meta2 = mistInfo.meta) === null || _mistInfo$meta2 === void 0 ? void 0 : _mistInfo$meta2.buffer_window;
|
|
75
|
+
var mistLastMs = mistInfo === null || mistInfo === void 0 ? void 0 : mistInfo.lastms;
|
|
76
|
+
var mistUnixOffset = mistInfo === null || mistInfo === void 0 ? void 0 : mistInfo.unixoffset;
|
|
77
|
+
var stats = [{
|
|
78
|
+
label: "Resolution",
|
|
79
|
+
value: currentRes
|
|
80
|
+
}, {
|
|
81
|
+
label: "Buffer",
|
|
82
|
+
value: "".concat(buffered, "s")
|
|
83
|
+
}, {
|
|
84
|
+
label: "Latency",
|
|
85
|
+
value: latency
|
|
86
|
+
}, {
|
|
87
|
+
label: "Bitrate",
|
|
88
|
+
value: bitrateKbps
|
|
89
|
+
}, {
|
|
90
|
+
label: "Quality Score",
|
|
91
|
+
value: "".concat(qualityScore, "/100")
|
|
92
|
+
}, {
|
|
93
|
+
label: "Frame Drop Rate",
|
|
94
|
+
value: "".concat(frameDropRate, "%")
|
|
95
|
+
}, {
|
|
96
|
+
label: "Stalls",
|
|
97
|
+
value: String(stallCount)
|
|
98
|
+
}, {
|
|
99
|
+
label: "Playback Rate",
|
|
100
|
+
value: "".concat(playbackRate, "x")
|
|
101
|
+
}, {
|
|
102
|
+
label: "Protocol",
|
|
103
|
+
value: protocol !== null && protocol !== void 0 ? protocol : "—"
|
|
104
|
+
}, {
|
|
105
|
+
label: "Node",
|
|
106
|
+
value: nodeId !== null && nodeId !== void 0 ? nodeId : "—"
|
|
107
|
+
}, {
|
|
108
|
+
label: "Geo Distance",
|
|
109
|
+
value: geoDistance ? "".concat(geoDistance.toFixed(0), " km") : "—"
|
|
110
|
+
}, {
|
|
111
|
+
label: "Viewers",
|
|
112
|
+
value: String(viewers)
|
|
113
|
+
}, {
|
|
114
|
+
label: "Status",
|
|
115
|
+
value: streamStatus
|
|
116
|
+
}, {
|
|
117
|
+
label: "Tracks",
|
|
118
|
+
value: formatTracks()
|
|
119
|
+
}, {
|
|
120
|
+
label: "Mist Type",
|
|
121
|
+
value: mistType
|
|
122
|
+
}, {
|
|
123
|
+
label: "Mist Buffer Window",
|
|
124
|
+
value: mistBufferWindow != null ? String(mistBufferWindow) : "—"
|
|
125
|
+
}, {
|
|
126
|
+
label: "Mist Lastms",
|
|
127
|
+
value: mistLastMs != null ? String(mistLastMs) : "—"
|
|
128
|
+
}, {
|
|
129
|
+
label: "Mist Unixoffset",
|
|
130
|
+
value: mistUnixOffset != null ? String(mistUnixOffset) : "—"
|
|
131
|
+
}];
|
|
132
|
+
// Add metadata fields if available
|
|
133
|
+
if (metadata !== null && metadata !== void 0 && metadata.title) {
|
|
134
|
+
stats.unshift({
|
|
135
|
+
label: "Title",
|
|
136
|
+
value: metadata.title
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
if (metadata !== null && metadata !== void 0 && metadata.durationSeconds) {
|
|
140
|
+
var mins = Math.floor(metadata.durationSeconds / 60);
|
|
141
|
+
var secs = metadata.durationSeconds % 60;
|
|
142
|
+
stats.push({
|
|
143
|
+
label: "Duration",
|
|
144
|
+
value: "".concat(mins, ":").concat(String(secs).padStart(2, "0"))
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (metadata !== null && metadata !== void 0 && metadata.recordingSizeBytes) {
|
|
148
|
+
var mb = (metadata.recordingSizeBytes / (1024 * 1024)).toFixed(1);
|
|
149
|
+
stats.push({
|
|
150
|
+
label: "Size",
|
|
151
|
+
value: "".concat(mb, " MB")
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
return jsxRuntime.jsxs("div", {
|
|
155
|
+
className: playerCore.cn("fw-stats-panel absolute top-2 right-2 z-30", "bg-black border border-white/10 rounded", "text-white text-xs font-mono", "max-w-[320px] max-h-[80%] overflow-auto", "shadow-lg"),
|
|
156
|
+
style: {
|
|
157
|
+
backgroundColor: "#000000"
|
|
158
|
+
},
|
|
159
|
+
children: [jsxRuntime.jsxs("div", {
|
|
160
|
+
className: "flex items-center justify-between px-3 py-2 border-b border-white/10",
|
|
161
|
+
children: [jsxRuntime.jsx("span", {
|
|
162
|
+
className: "text-white/70 text-[10px] uppercase tracking-wider",
|
|
163
|
+
children: "Stats Overlay"
|
|
164
|
+
}), jsxRuntime.jsx("button", {
|
|
165
|
+
type: "button",
|
|
166
|
+
onClick: onClose,
|
|
167
|
+
className: "text-white/50 hover:text-white transition-colors p-1 -mr-1",
|
|
168
|
+
"aria-label": "Close stats panel",
|
|
169
|
+
children: jsxRuntime.jsx("svg", {
|
|
170
|
+
width: "12",
|
|
171
|
+
height: "12",
|
|
172
|
+
viewBox: "0 0 12 12",
|
|
173
|
+
fill: "none",
|
|
174
|
+
stroke: "currentColor",
|
|
175
|
+
strokeWidth: "1.5",
|
|
176
|
+
children: jsxRuntime.jsx("path", {
|
|
177
|
+
d: "M2 2l8 8M10 2l-8 8"
|
|
178
|
+
})
|
|
179
|
+
})
|
|
180
|
+
})]
|
|
181
|
+
}), jsxRuntime.jsx("div", {
|
|
182
|
+
className: "px-3 py-2 space-y-1",
|
|
183
|
+
children: stats.map(function (_ref3) {
|
|
184
|
+
var label = _ref3.label,
|
|
185
|
+
value = _ref3.value;
|
|
186
|
+
return jsxRuntime.jsxs("div", {
|
|
187
|
+
className: "flex justify-between gap-4",
|
|
188
|
+
children: [jsxRuntime.jsx("span", {
|
|
189
|
+
className: "text-white/50 shrink-0",
|
|
190
|
+
children: label
|
|
191
|
+
}), jsxRuntime.jsx("span", {
|
|
192
|
+
className: "text-white/90 truncate text-right",
|
|
193
|
+
children: value
|
|
194
|
+
})]
|
|
195
|
+
}, label);
|
|
196
|
+
})
|
|
197
|
+
})]
|
|
198
|
+
});
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
exports.default = StatsPanel;
|
|
202
|
+
//# sourceMappingURL=StatsPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StatsPanel.js","sources":["../../../../src/components/StatsPanel.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n cn,\n type ContentMetadata,\n type PlaybackQuality,\n type StreamState,\n} from \"@livepeer-frameworks/player-core\";\n\ninterface StatsPanelProps {\n isOpen: boolean;\n onClose: () => void;\n metadata?: ContentMetadata | null;\n streamState?: StreamState | null;\n quality?: PlaybackQuality | null;\n videoElement?: HTMLVideoElement | null;\n protocol?: string;\n nodeId?: string;\n geoDistance?: number;\n}\n\n/**\n * \"Stats for nerds\" panel showing detailed playback information.\n * Toggleable overlay with technical details about the stream.\n */\nconst StatsPanel: React.FC<StatsPanelProps> = ({\n isOpen,\n onClose,\n metadata,\n streamState,\n quality,\n videoElement,\n protocol,\n nodeId,\n geoDistance,\n}) => {\n if (!isOpen) return null;\n\n // Video element stats\n const video = videoElement;\n const currentRes = video ? `${video.videoWidth}x${video.videoHeight}` : \"—\";\n const buffered =\n video && video.buffered.length > 0\n ? (video.buffered.end(video.buffered.length - 1) - video.currentTime).toFixed(1)\n : \"—\";\n const playbackRate = video?.playbackRate?.toFixed(2) ?? \"1.00\";\n\n // Quality monitor stats\n const qualityScore = quality?.score?.toFixed(0) ?? \"—\";\n const bitrateKbps = quality?.bitrate ? `${(quality.bitrate / 1000).toFixed(0)} kbps` : \"—\";\n const frameDropRate = quality?.frameDropRate?.toFixed(1) ?? \"—\";\n const stallCount = quality?.stallCount ?? 0;\n const latency = quality?.latency ? `${Math.round(quality.latency)} ms` : \"—\";\n\n // Stream state stats\n const viewers = metadata?.viewers ?? \"—\";\n const streamStatus = streamState?.status ?? metadata?.status ?? \"—\";\n\n const mistInfo = metadata?.mist ?? streamState?.streamInfo;\n\n const deriveTracksFromMist = () => {\n const mistTracks = mistInfo?.meta?.tracks;\n if (!mistTracks) return undefined;\n return Object.values(mistTracks).map((t) => ({\n type: t.type,\n codec: t.codec,\n width: t.width,\n height: t.height,\n bitrate: typeof t.bps === \"number\" ? Math.round(t.bps) : undefined,\n fps: typeof t.fpks === \"number\" ? t.fpks / 1000 : undefined,\n channels: t.channels,\n sampleRate: t.rate,\n }));\n };\n\n // Format track info from metadata\n const formatTracks = () => {\n const tracks = metadata?.tracks ?? deriveTracksFromMist();\n if (!tracks?.length) return \"—\";\n return tracks\n .map((t) => {\n if (t.type === \"video\") {\n const resolution = t.width && t.height ? `${t.width}x${t.height}` : \"?\";\n const bitrate = t.bitrate ? `${Math.round(t.bitrate / 1000)}kbps` : \"?\";\n return `${t.codec ?? \"?\"} ${resolution}@${bitrate}`;\n }\n const channels = t.channels ? `${t.channels}ch` : \"?\";\n return `${t.codec ?? \"?\"} ${channels}`;\n })\n .join(\", \");\n };\n\n const mistType = mistInfo?.type ?? \"—\";\n const mistBufferWindow = mistInfo?.meta?.buffer_window;\n const mistLastMs = mistInfo?.lastms;\n const mistUnixOffset = mistInfo?.unixoffset;\n\n const stats = [\n { label: \"Resolution\", value: currentRes },\n { label: \"Buffer\", value: `${buffered}s` },\n { label: \"Latency\", value: latency },\n { label: \"Bitrate\", value: bitrateKbps },\n { label: \"Quality Score\", value: `${qualityScore}/100` },\n { label: \"Frame Drop Rate\", value: `${frameDropRate}%` },\n { label: \"Stalls\", value: String(stallCount) },\n { label: \"Playback Rate\", value: `${playbackRate}x` },\n { label: \"Protocol\", value: protocol ?? \"—\" },\n { label: \"Node\", value: nodeId ?? \"—\" },\n { label: \"Geo Distance\", value: geoDistance ? `${geoDistance.toFixed(0)} km` : \"—\" },\n { label: \"Viewers\", value: String(viewers) },\n { label: \"Status\", value: streamStatus },\n { label: \"Tracks\", value: formatTracks() },\n { label: \"Mist Type\", value: mistType },\n {\n label: \"Mist Buffer Window\",\n value: mistBufferWindow != null ? String(mistBufferWindow) : \"—\",\n },\n { label: \"Mist Lastms\", value: mistLastMs != null ? String(mistLastMs) : \"—\" },\n { label: \"Mist Unixoffset\", value: mistUnixOffset != null ? String(mistUnixOffset) : \"—\" },\n ];\n\n // Add metadata fields if available\n if (metadata?.title) {\n stats.unshift({ label: \"Title\", value: metadata.title });\n }\n if (metadata?.durationSeconds) {\n const mins = Math.floor(metadata.durationSeconds / 60);\n const secs = metadata.durationSeconds % 60;\n stats.push({ label: \"Duration\", value: `${mins}:${String(secs).padStart(2, \"0\")}` });\n }\n if (metadata?.recordingSizeBytes) {\n const mb = (metadata.recordingSizeBytes / (1024 * 1024)).toFixed(1);\n stats.push({ label: \"Size\", value: `${mb} MB` });\n }\n\n return (\n <div\n className={cn(\n \"fw-stats-panel absolute top-2 right-2 z-30\",\n \"bg-black border border-white/10 rounded\",\n \"text-white text-xs font-mono\",\n \"max-w-[320px] max-h-[80%] overflow-auto\",\n \"shadow-lg\"\n )}\n style={{ backgroundColor: \"#000000\" }} // Inline fallback for opaque background\n >\n {/* Header */}\n <div className=\"flex items-center justify-between px-3 py-2 border-b border-white/10\">\n <span className=\"text-white/70 text-[10px] uppercase tracking-wider\">Stats Overlay</span>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"text-white/50 hover:text-white transition-colors p-1 -mr-1\"\n aria-label=\"Close stats panel\"\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n >\n <path d=\"M2 2l8 8M10 2l-8 8\" />\n </svg>\n </button>\n </div>\n\n {/* Stats grid */}\n <div className=\"px-3 py-2 space-y-1\">\n {stats.map(({ label, value }) => (\n <div key={label} className=\"flex justify-between gap-4\">\n <span className=\"text-white/50 shrink-0\">{label}</span>\n <span className=\"text-white/90 truncate text-right\">{value}</span>\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport default StatsPanel;\n"],"names":["StatsPanel","_ref","_video$playbackRate$t","_video$playbackRate","_quality$score$toFixe","_quality$score","_quality$frameDropRat","_quality$frameDropRat2","_quality$stallCount","_metadata$viewers","_ref2","_streamState$status","_metadata$mist","_mistInfo$type","_mistInfo$meta2","isOpen","onClose","metadata","streamState","quality","videoElement","protocol","nodeId","geoDistance","video","currentRes","concat","videoWidth","videoHeight","buffered","length","end","currentTime","toFixed","playbackRate","qualityScore","score","bitrateKbps","bitrate","frameDropRate","stallCount","latency","Math","round","viewers","streamStatus","status","mistInfo","mist","streamInfo","deriveTracksFromMist","_mistInfo$meta","mistTracks","meta","tracks","undefined","Object","values","map","t","type","codec","width","height","bps","fps","fpks","channels","sampleRate","rate","formatTracks","_metadata$tracks","_t$codec2","_t$codec","resolution","join","mistType","mistBufferWindow","buffer_window","mistLastMs","lastms","mistUnixOffset","unixoffset","stats","label","value","String","title","unshift","durationSeconds","mins","floor","secs","push","padStart","recordingSizeBytes","mb","_jsxs","className","cn","style","backgroundColor","children","_jsx","onClick","viewBox","fill","stroke","strokeWidth","d","_ref3"],"mappings":"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"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get status icon based on stream state
|
|
9
|
+
*/
|
|
10
|
+
function StatusIcon(_ref) {
|
|
11
|
+
var status = _ref.status;
|
|
12
|
+
var iconClass = "w-5 h-5";
|
|
13
|
+
switch (status) {
|
|
14
|
+
case "ONLINE":
|
|
15
|
+
return jsxRuntime.jsx("svg", {
|
|
16
|
+
className: "".concat(iconClass, " fw-status-online"),
|
|
17
|
+
fill: "none",
|
|
18
|
+
viewBox: "0 0 24 24",
|
|
19
|
+
stroke: "currentColor",
|
|
20
|
+
children: jsxRuntime.jsx("path", {
|
|
21
|
+
strokeLinecap: "round",
|
|
22
|
+
strokeLinejoin: "round",
|
|
23
|
+
strokeWidth: 2,
|
|
24
|
+
d: "M5 13l4 4L19 7"
|
|
25
|
+
})
|
|
26
|
+
});
|
|
27
|
+
case "OFFLINE":
|
|
28
|
+
return jsxRuntime.jsx("svg", {
|
|
29
|
+
className: "".concat(iconClass, " fw-status-offline"),
|
|
30
|
+
fill: "none",
|
|
31
|
+
viewBox: "0 0 24 24",
|
|
32
|
+
stroke: "currentColor",
|
|
33
|
+
children: jsxRuntime.jsx("path", {
|
|
34
|
+
strokeLinecap: "round",
|
|
35
|
+
strokeLinejoin: "round",
|
|
36
|
+
strokeWidth: 2,
|
|
37
|
+
d: "M18.364 5.636a9 9 0 010 12.728m0 0l-2.829-2.829m2.829 2.829L21 21M15.536 8.464a5 5 0 010 7.072m0 0l-2.829-2.829m-4.243 2.829a4.978 4.978 0 01-1.414-2.83m-1.414 5.658a9 9 0 01-2.167-9.238m7.824 2.167a1 1 0 111.414 1.414m-1.414-1.414L3 3m8.293 8.293l1.414 1.414"
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
case "INITIALIZING":
|
|
41
|
+
case "BOOTING":
|
|
42
|
+
case "WAITING_FOR_DATA":
|
|
43
|
+
return jsxRuntime.jsxs("svg", {
|
|
44
|
+
className: "".concat(iconClass, " fw-status-warning animate-spin"),
|
|
45
|
+
fill: "none",
|
|
46
|
+
viewBox: "0 0 24 24",
|
|
47
|
+
children: [jsxRuntime.jsx("circle", {
|
|
48
|
+
className: "opacity-25",
|
|
49
|
+
cx: "12",
|
|
50
|
+
cy: "12",
|
|
51
|
+
r: "10",
|
|
52
|
+
stroke: "currentColor",
|
|
53
|
+
strokeWidth: "4"
|
|
54
|
+
}), jsxRuntime.jsx("path", {
|
|
55
|
+
className: "opacity-75",
|
|
56
|
+
fill: "currentColor",
|
|
57
|
+
d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
58
|
+
})]
|
|
59
|
+
});
|
|
60
|
+
case "SHUTTING_DOWN":
|
|
61
|
+
return jsxRuntime.jsx("svg", {
|
|
62
|
+
className: "".concat(iconClass, " fw-status-warning"),
|
|
63
|
+
fill: "none",
|
|
64
|
+
viewBox: "0 0 24 24",
|
|
65
|
+
stroke: "currentColor",
|
|
66
|
+
children: jsxRuntime.jsx("path", {
|
|
67
|
+
strokeLinecap: "round",
|
|
68
|
+
strokeLinejoin: "round",
|
|
69
|
+
strokeWidth: 2,
|
|
70
|
+
d: "M13 10V3L4 14h7v7l9-11h-7z"
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
case "ERROR":
|
|
74
|
+
case "INVALID":
|
|
75
|
+
default:
|
|
76
|
+
return jsxRuntime.jsx("svg", {
|
|
77
|
+
className: "".concat(iconClass, " fw-status-offline"),
|
|
78
|
+
fill: "none",
|
|
79
|
+
viewBox: "0 0 24 24",
|
|
80
|
+
stroke: "currentColor",
|
|
81
|
+
children: jsxRuntime.jsx("path", {
|
|
82
|
+
strokeLinecap: "round",
|
|
83
|
+
strokeLinejoin: "round",
|
|
84
|
+
strokeWidth: 2,
|
|
85
|
+
d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
86
|
+
})
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get status label for header
|
|
92
|
+
*/
|
|
93
|
+
function getStatusLabel(status) {
|
|
94
|
+
switch (status) {
|
|
95
|
+
case "ONLINE":
|
|
96
|
+
return "ONLINE";
|
|
97
|
+
case "OFFLINE":
|
|
98
|
+
return "OFFLINE";
|
|
99
|
+
case "INITIALIZING":
|
|
100
|
+
return "INITIALIZING";
|
|
101
|
+
case "BOOTING":
|
|
102
|
+
return "STARTING";
|
|
103
|
+
case "WAITING_FOR_DATA":
|
|
104
|
+
return "WAITING";
|
|
105
|
+
case "SHUTTING_DOWN":
|
|
106
|
+
return "ENDING";
|
|
107
|
+
case "ERROR":
|
|
108
|
+
return "ERROR";
|
|
109
|
+
case "INVALID":
|
|
110
|
+
return "INVALID";
|
|
111
|
+
default:
|
|
112
|
+
return "STATUS";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* StreamStateOverlay - Shows stream status when not playable
|
|
117
|
+
*
|
|
118
|
+
* Slab-based design with header/body/actions zones.
|
|
119
|
+
* Uses Tokyo Night color palette and seam-based layout.
|
|
120
|
+
*/
|
|
121
|
+
var StreamStateOverlay = function StreamStateOverlay(_ref2) {
|
|
122
|
+
var status = _ref2.status,
|
|
123
|
+
message = _ref2.message,
|
|
124
|
+
percentage = _ref2.percentage,
|
|
125
|
+
onRetry = _ref2.onRetry,
|
|
126
|
+
_ref2$visible = _ref2.visible,
|
|
127
|
+
visible = _ref2$visible === void 0 ? true : _ref2$visible,
|
|
128
|
+
_ref2$className = _ref2.className,
|
|
129
|
+
className = _ref2$className === void 0 ? "" : _ref2$className;
|
|
130
|
+
if (!visible || status === "ONLINE") {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
var showRetry = status === "ERROR" || status === "INVALID" || status === "OFFLINE";
|
|
134
|
+
var showProgress = status === "INITIALIZING" && percentage !== undefined;
|
|
135
|
+
return jsxRuntime.jsx("div", {
|
|
136
|
+
className: "absolute inset-0 z-20 flex items-center justify-center ".concat(className),
|
|
137
|
+
style: {
|
|
138
|
+
backgroundColor: "hsl(var(--tn-bg-dark) / 0.8)",
|
|
139
|
+
backdropFilter: "blur(4px)"
|
|
140
|
+
},
|
|
141
|
+
role: "status",
|
|
142
|
+
"aria-live": "polite",
|
|
143
|
+
children: jsxRuntime.jsxs("div", {
|
|
144
|
+
className: "fw-slab w-[280px] max-w-[90%]",
|
|
145
|
+
style: {
|
|
146
|
+
backgroundColor: "hsl(var(--tn-bg) / 0.95)"
|
|
147
|
+
},
|
|
148
|
+
children: [jsxRuntime.jsxs("div", {
|
|
149
|
+
className: "fw-slab-header flex items-center gap-2",
|
|
150
|
+
children: [jsxRuntime.jsx(StatusIcon, {
|
|
151
|
+
status: status
|
|
152
|
+
}), jsxRuntime.jsx("span", {
|
|
153
|
+
children: getStatusLabel(status)
|
|
154
|
+
})]
|
|
155
|
+
}), jsxRuntime.jsxs("div", {
|
|
156
|
+
className: "fw-slab-body",
|
|
157
|
+
children: [jsxRuntime.jsx("p", {
|
|
158
|
+
className: "text-sm",
|
|
159
|
+
style: {
|
|
160
|
+
color: "hsl(var(--tn-fg))"
|
|
161
|
+
},
|
|
162
|
+
children: message
|
|
163
|
+
}), showProgress && jsxRuntime.jsxs("div", {
|
|
164
|
+
className: "mt-3",
|
|
165
|
+
children: [jsxRuntime.jsx("div", {
|
|
166
|
+
className: "h-1.5 w-full overflow-hidden",
|
|
167
|
+
style: {
|
|
168
|
+
backgroundColor: "hsl(var(--tn-bg-visual))"
|
|
169
|
+
},
|
|
170
|
+
children: jsxRuntime.jsx("div", {
|
|
171
|
+
className: "h-full transition-all duration-300",
|
|
172
|
+
style: {
|
|
173
|
+
width: "".concat(Math.min(100, percentage), "%"),
|
|
174
|
+
backgroundColor: "hsl(var(--tn-yellow))"
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
}), jsxRuntime.jsxs("p", {
|
|
178
|
+
className: "mt-1.5 text-xs font-mono",
|
|
179
|
+
style: {
|
|
180
|
+
color: "hsl(var(--tn-fg-dark))"
|
|
181
|
+
},
|
|
182
|
+
children: [Math.round(percentage), "%"]
|
|
183
|
+
})]
|
|
184
|
+
}), status === "OFFLINE" && jsxRuntime.jsx("p", {
|
|
185
|
+
className: "mt-2 text-xs",
|
|
186
|
+
style: {
|
|
187
|
+
color: "hsl(var(--tn-fg-dark))"
|
|
188
|
+
},
|
|
189
|
+
children: "The stream will start when the broadcaster goes live"
|
|
190
|
+
}), (status === "BOOTING" || status === "WAITING_FOR_DATA") && jsxRuntime.jsx("p", {
|
|
191
|
+
className: "mt-2 text-xs",
|
|
192
|
+
style: {
|
|
193
|
+
color: "hsl(var(--tn-fg-dark))"
|
|
194
|
+
},
|
|
195
|
+
children: "Please wait while the stream prepares..."
|
|
196
|
+
}), !showRetry && jsxRuntime.jsxs("div", {
|
|
197
|
+
className: "mt-3 flex items-center gap-2 text-xs",
|
|
198
|
+
style: {
|
|
199
|
+
color: "hsl(var(--tn-fg-dark))"
|
|
200
|
+
},
|
|
201
|
+
children: [jsxRuntime.jsx("span", {
|
|
202
|
+
className: "h-1.5 w-1.5 animate-pulse",
|
|
203
|
+
style: {
|
|
204
|
+
backgroundColor: "hsl(var(--tn-cyan))"
|
|
205
|
+
}
|
|
206
|
+
}), jsxRuntime.jsx("span", {
|
|
207
|
+
children: "Checking stream status..."
|
|
208
|
+
})]
|
|
209
|
+
})]
|
|
210
|
+
}), showRetry && onRetry && jsxRuntime.jsx("div", {
|
|
211
|
+
className: "fw-slab-actions",
|
|
212
|
+
children: jsxRuntime.jsx("button", {
|
|
213
|
+
type: "button",
|
|
214
|
+
onClick: onRetry,
|
|
215
|
+
className: "fw-btn-flush py-2.5 text-xs font-medium uppercase tracking-wide",
|
|
216
|
+
style: {
|
|
217
|
+
color: "hsl(var(--tn-blue))"
|
|
218
|
+
},
|
|
219
|
+
"aria-label": "Retry connection",
|
|
220
|
+
children: "Retry Connection"
|
|
221
|
+
})
|
|
222
|
+
})]
|
|
223
|
+
})
|
|
224
|
+
});
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
exports.StreamStateOverlay = StreamStateOverlay;
|
|
228
|
+
exports.default = StreamStateOverlay;
|
|
229
|
+
//# sourceMappingURL=StreamStateOverlay.js.map
|