@streamplace/components 0.7.18 → 0.7.21

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 (122) hide show
  1. package/dist/assets/emoji-data.json +19371 -0
  2. package/dist/components/chat/chat-box.js +319 -0
  3. package/dist/components/chat/chat-message.js +87 -0
  4. package/dist/components/chat/chat.js +150 -0
  5. package/dist/components/chat/emoji-suggestions.js +35 -0
  6. package/dist/components/chat/mention-suggestions.js +42 -0
  7. package/dist/components/chat/mod-view.js +112 -0
  8. package/dist/components/chat/system-message.js +19 -0
  9. package/dist/components/dashboard/chat-panel.js +38 -0
  10. package/dist/components/dashboard/header.js +80 -0
  11. package/dist/components/dashboard/index.js +14 -0
  12. package/dist/components/dashboard/information-widget.js +234 -0
  13. package/dist/components/dashboard/mod-actions.js +71 -0
  14. package/dist/components/dashboard/problems.js +74 -0
  15. package/dist/components/icons/bluesky-icon.js +9 -0
  16. package/dist/components/keep-awake.js +7 -0
  17. package/dist/components/keep-awake.native.js +16 -0
  18. package/dist/components/mobile-player/fullscreen.js +76 -0
  19. package/dist/components/mobile-player/fullscreen.native.js +141 -0
  20. package/dist/components/mobile-player/player.js +94 -0
  21. package/dist/components/mobile-player/props.js +2 -0
  22. package/dist/components/mobile-player/shared.js +54 -0
  23. package/dist/components/mobile-player/ui/autoplay-button.js +68 -0
  24. package/dist/components/mobile-player/ui/countdown.js +83 -0
  25. package/dist/components/mobile-player/ui/index.js +12 -0
  26. package/dist/components/mobile-player/ui/input.js +42 -0
  27. package/dist/components/mobile-player/ui/metrics.js +44 -0
  28. package/dist/components/mobile-player/ui/report-modal.js +90 -0
  29. package/dist/components/mobile-player/ui/streamer-context-menu.js +7 -0
  30. package/dist/components/mobile-player/ui/streamer-loading-overlay.js +104 -0
  31. package/dist/components/mobile-player/ui/viewer-context-menu.js +51 -0
  32. package/dist/components/mobile-player/ui/viewer-loading-overlay.js +49 -0
  33. package/dist/components/mobile-player/ui/viewers.js +23 -0
  34. package/dist/components/mobile-player/use-webrtc.js +243 -0
  35. package/dist/components/mobile-player/video-async.native.js +276 -0
  36. package/dist/components/mobile-player/video-retry.js +29 -0
  37. package/dist/components/mobile-player/video.js +475 -0
  38. package/dist/components/mobile-player/video.native.js +56 -0
  39. package/dist/components/mobile-player/webrtc-diagnostics.js +110 -0
  40. package/dist/components/mobile-player/webrtc-primitives.js +27 -0
  41. package/dist/components/mobile-player/webrtc-primitives.native.js +8 -0
  42. package/dist/components/share/sharesheet.js +91 -0
  43. package/dist/components/ui/button.js +223 -0
  44. package/dist/components/ui/dialog.js +206 -0
  45. package/dist/components/ui/dropdown.js +172 -0
  46. package/dist/components/ui/icons.js +25 -0
  47. package/dist/components/ui/index.js +34 -0
  48. package/dist/components/ui/info-box.js +31 -0
  49. package/dist/components/ui/info-row.js +23 -0
  50. package/dist/components/ui/input.js +205 -0
  51. package/dist/components/ui/loader.js +10 -0
  52. package/dist/components/ui/primitives/button.js +125 -0
  53. package/dist/components/ui/primitives/input.js +206 -0
  54. package/dist/components/ui/primitives/modal.js +206 -0
  55. package/dist/components/ui/primitives/text.js +292 -0
  56. package/dist/components/ui/resizeable.js +121 -0
  57. package/dist/components/ui/slider.js +5 -0
  58. package/dist/components/ui/text.js +177 -0
  59. package/dist/components/ui/textarea.js +19 -0
  60. package/dist/components/ui/toast.js +175 -0
  61. package/dist/components/ui/view.js +252 -0
  62. package/dist/hooks/index.js +14 -0
  63. package/dist/hooks/useAvatars.js +35 -0
  64. package/dist/hooks/useCameraToggle.js +12 -0
  65. package/dist/hooks/useKeyboard.js +36 -0
  66. package/dist/hooks/useKeyboardSlide.js +14 -0
  67. package/dist/hooks/useLivestreamInfo.js +69 -0
  68. package/dist/hooks/useOuterAndInnerDimensions.js +30 -0
  69. package/dist/hooks/usePlayerDimensions.js +22 -0
  70. package/dist/hooks/usePointerDevice.js +71 -0
  71. package/dist/hooks/useSegmentDimensions.js +17 -0
  72. package/dist/hooks/useSegmentTiming.js +65 -0
  73. package/dist/index.js +34 -0
  74. package/dist/lib/browser.js +35 -0
  75. package/dist/lib/facet.js +92 -0
  76. package/dist/lib/system-messages.js +101 -0
  77. package/dist/lib/theme/atoms.js +646 -0
  78. package/dist/lib/theme/atoms.types.js +6 -0
  79. package/dist/lib/theme/index.js +35 -0
  80. package/dist/lib/theme/theme.js +256 -0
  81. package/dist/lib/theme/tokens.js +659 -0
  82. package/dist/lib/utils.js +105 -0
  83. package/dist/livestream-provider/index.js +30 -0
  84. package/dist/livestream-provider/websocket.js +45 -0
  85. package/dist/livestream-store/chat.js +308 -0
  86. package/dist/livestream-store/context.js +5 -0
  87. package/dist/livestream-store/index.js +7 -0
  88. package/dist/livestream-store/livestream-state.js +2 -0
  89. package/dist/livestream-store/livestream-store.js +58 -0
  90. package/dist/livestream-store/problems.js +76 -0
  91. package/dist/livestream-store/stream-key.js +88 -0
  92. package/dist/livestream-store/websocket-consumer.js +94 -0
  93. package/dist/player-store/context.js +5 -0
  94. package/dist/player-store/index.js +9 -0
  95. package/dist/player-store/player-provider.js +58 -0
  96. package/dist/player-store/player-state.js +25 -0
  97. package/dist/player-store/player-store.js +201 -0
  98. package/dist/player-store/single-player-provider.js +121 -0
  99. package/dist/streamplace-provider/context.js +5 -0
  100. package/dist/streamplace-provider/index.js +20 -0
  101. package/dist/streamplace-provider/poller.js +49 -0
  102. package/dist/streamplace-provider/xrpc.js +0 -0
  103. package/dist/streamplace-store/block.js +65 -0
  104. package/dist/streamplace-store/index.js +6 -0
  105. package/dist/streamplace-store/stream.js +247 -0
  106. package/dist/streamplace-store/streamplace-store.js +47 -0
  107. package/dist/streamplace-store/user.js +52 -0
  108. package/dist/streamplace-store/xrpc.js +15 -0
  109. package/dist/ui/index.js +79 -0
  110. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  111. package/package.json +5 -4
  112. package/src/components/chat/chat-box.tsx +3 -0
  113. package/src/components/chat/mod-view.tsx +39 -5
  114. package/src/components/mobile-player/fullscreen.tsx +2 -0
  115. package/src/components/mobile-player/ui/autoplay-button.tsx +86 -0
  116. package/src/components/mobile-player/ui/index.ts +1 -0
  117. package/src/components/mobile-player/video.tsx +11 -1
  118. package/src/livestream-store/chat.tsx +22 -0
  119. package/src/player-store/player-provider.tsx +2 -1
  120. package/src/player-store/player-state.tsx +6 -0
  121. package/src/player-store/player-store.tsx +4 -0
  122. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,276 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = VideoNative;
4
+ exports.NativeVideo = NativeVideo;
5
+ exports.NativeWHEP = NativeWHEP;
6
+ exports.NativeIngestPlayer = NativeIngestPlayer;
7
+ const tslib_1 = require("tslib");
8
+ const jsx_runtime_1 = require("react/jsx-runtime");
9
+ const expo_video_1 = require("expo-video");
10
+ const lucide_react_native_1 = require("lucide-react-native");
11
+ const react_1 = require("react");
12
+ const react_native_1 = require("react-native");
13
+ const react_native_webrtc_1 = require("react-native-webrtc");
14
+ const __1 = require("../..");
15
+ const atoms_1 = require("../../lib/theme/atoms");
16
+ const shared_1 = require("./shared");
17
+ const use_webrtc_1 = tslib_1.__importStar(require("./use-webrtc"));
18
+ const webrtc_primitives_native_1 = require("./webrtc-primitives.native");
19
+ // Add NativeIngestPlayer to the switch below!
20
+ function VideoNative(props) {
21
+ const protocol = (0, __1.usePlayerStore)((x) => x.protocol);
22
+ const ingest = (0, __1.usePlayerStore)((x) => x.ingestConnectionState) != null;
23
+ return ((0, jsx_runtime_1.jsx)(__1.View, { children: ingest ? ((0, jsx_runtime_1.jsx)(NativeIngestPlayer, { objectFit: props?.objectFit })) : protocol === __1.PlayerProtocol.WEBRTC ? ((0, jsx_runtime_1.jsx)(NativeWHEP, { objectFit: props?.objectFit, pictureInPictureEnabled: props?.pictureInPictureEnabled })) : ((0, jsx_runtime_1.jsx)(NativeVideo, { objectFit: props?.objectFit, pictureInPictureEnabled: props?.pictureInPictureEnabled })) }));
24
+ }
25
+ function NativeVideo(props) {
26
+ const videoRef = (0, react_1.useRef)(null);
27
+ const protocol = (0, __1.usePlayerStore)((x) => x.protocol);
28
+ const selectedRendition = (0, __1.usePlayerStore)((x) => x.selectedRendition);
29
+ const src = (0, __1.usePlayerStore)((x) => x.src);
30
+ const { url } = (0, shared_1.srcToUrl)({ src: src, selectedRendition }, protocol);
31
+ const setStatus = (0, __1.usePlayerStore)((x) => x.setStatus);
32
+ const muted = (0, __1.usePlayerStore)((x) => x.muted);
33
+ const volume = (0, __1.usePlayerStore)((x) => x.volume);
34
+ const setFullscreen = (0, __1.usePlayerStore)((x) => x.setFullscreen);
35
+ const fullscreen = (0, __1.usePlayerStore)((x) => x.fullscreen);
36
+ const playerEvent = (0, __1.usePlayerStore)((x) => x.playerEvent);
37
+ const spurl = (0, __1.useStreamplaceStore)((x) => x.url);
38
+ const setPlayerWidth = (0, __1.usePlayerStore)((x) => x.setPlayerWidth);
39
+ const setPlayerHeight = (0, __1.usePlayerStore)((x) => x.setPlayerHeight);
40
+ // State for live dimensions
41
+ const [dimensions, setDimensions] = (0, react_1.useState)({ width: 0, height: 0 });
42
+ const handleLayout = (0, react_1.useCallback)((event) => {
43
+ const { width, height } = event.nativeEvent.layout;
44
+ setDimensions({ width, height });
45
+ setPlayerWidth(width);
46
+ setPlayerHeight(height);
47
+ }, []);
48
+ (0, react_1.useEffect)(() => {
49
+ return () => {
50
+ setStatus(__1.PlayerStatus.START);
51
+ };
52
+ }, [setStatus]);
53
+ const player = (0, expo_video_1.useVideoPlayer)(url, (player) => {
54
+ player.addListener("playingChange", (newIsPlaying) => {
55
+ console.log("playingChange", newIsPlaying);
56
+ if (newIsPlaying) {
57
+ setStatus(__1.PlayerStatus.PLAYING);
58
+ }
59
+ else {
60
+ setStatus(__1.PlayerStatus.WAITING);
61
+ }
62
+ });
63
+ player.loop = true;
64
+ player.muted = muted;
65
+ player.play();
66
+ });
67
+ (0, react_1.useEffect)(() => {
68
+ player.muted = muted;
69
+ }, [muted, player]);
70
+ (0, react_1.useEffect)(() => {
71
+ player.volume = volume;
72
+ }, [volume, player]);
73
+ (0, react_1.useEffect)(() => {
74
+ const subs = [
75
+ "playToEnd",
76
+ "playbackRateChange",
77
+ "playingChange",
78
+ "sourceChange",
79
+ "statusChange",
80
+ "volumeChange",
81
+ ].map((evType) => {
82
+ return player.addListener(evType, (...args) => {
83
+ const now = new Date();
84
+ console.log("video native event", evType);
85
+ playerEvent(spurl, now.toISOString(), evType, { args: args });
86
+ });
87
+ });
88
+ subs.push(player.addListener("playingChange", (newIsPlaying) => {
89
+ console.log("playingChange", newIsPlaying);
90
+ if (newIsPlaying) {
91
+ setStatus(__1.PlayerStatus.PLAYING);
92
+ }
93
+ else {
94
+ setStatus(__1.PlayerStatus.WAITING);
95
+ }
96
+ }));
97
+ return () => {
98
+ for (const sub of subs) {
99
+ sub.remove();
100
+ }
101
+ };
102
+ }, [player, playerEvent, setStatus, spurl]);
103
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(expo_video_1.VideoView, { ref: videoRef, player: player, allowsFullscreen: true, nativeControls: fullscreen, onFullscreenEnter: () => {
104
+ setFullscreen(true);
105
+ }, onFullscreenExit: () => {
106
+ setFullscreen(false);
107
+ }, allowsPictureInPicture: props?.pictureInPictureEnabled !== false, onLayout: handleLayout }) }));
108
+ }
109
+ function NativeWHEP(props) {
110
+ const selectedRendition = (0, __1.usePlayerStore)((x) => x.selectedRendition);
111
+ const src = (0, __1.usePlayerStore)((x) => x.src);
112
+ const { url } = (0, shared_1.srcToUrl)({ src: src, selectedRendition }, __1.PlayerProtocol.WEBRTC);
113
+ const [stream, stuck] = (0, use_webrtc_1.default)(url);
114
+ const status = (0, __1.usePlayerStore)((x) => x.status);
115
+ const setPlayerWidth = (0, __1.usePlayerStore)((x) => x.setPlayerWidth);
116
+ const setPlayerHeight = (0, __1.usePlayerStore)((x) => x.setPlayerHeight);
117
+ // PiP support: wire up videoRef (no direct ref for RTCView)
118
+ const setVideoRef = (0, __1.usePlayerStore)((x) => x.setVideoRef);
119
+ // State for live dimensions
120
+ const [dimensions, setDimensions] = (0, react_1.useState)({ width: 0, height: 0 });
121
+ const handleLayout = (0, react_1.useCallback)((event) => {
122
+ const { width, height } = event.nativeEvent.layout;
123
+ setDimensions({ width, height });
124
+ setPlayerWidth(width);
125
+ setPlayerHeight(height);
126
+ }, []);
127
+ const setStatus = (0, __1.usePlayerStore)((x) => x.setStatus);
128
+ const muted = (0, __1.usePlayerStore)((x) => x.muted);
129
+ const volume = (0, __1.usePlayerStore)((x) => x.volume);
130
+ (0, react_1.useEffect)(() => {
131
+ if (stuck && status === __1.PlayerStatus.PLAYING) {
132
+ console.log("setting status to stalled", status);
133
+ setStatus(__1.PlayerStatus.STALLED);
134
+ }
135
+ if (!stuck && status === __1.PlayerStatus.STALLED) {
136
+ console.log("setting status to playing", status);
137
+ setStatus(__1.PlayerStatus.PLAYING);
138
+ }
139
+ }, [stuck, status]);
140
+ const mediaStream = stream;
141
+ // useEffect(() => {
142
+ // if (!mediaStream) {
143
+ // setStatus(PlayerStatus.WAITING);
144
+ // return;
145
+ // }
146
+ // setStatus(PlayerStatus.PLAYING);
147
+ // }, [mediaStream, setStatus]);
148
+ (0, react_1.useEffect)(() => {
149
+ if (!mediaStream) {
150
+ return;
151
+ }
152
+ mediaStream.getTracks().forEach((track) => {
153
+ if (track.kind === "audio") {
154
+ track._setVolume(muted ? 0 : volume);
155
+ }
156
+ });
157
+ }, [mediaStream, muted, volume]);
158
+ // Keep the playerStore videoRef in sync for PiP (if possible)
159
+ (0, react_1.useEffect)(() => {
160
+ if (typeof setVideoRef === "function") {
161
+ setVideoRef(null); // No direct ref for RTCView, but keep API consistent
162
+ }
163
+ }, [setVideoRef]);
164
+ if (!mediaStream) {
165
+ return (0, jsx_runtime_1.jsx)(__1.View, {});
166
+ }
167
+ return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(react_native_webrtc_1.RTCView, { mirror: false, objectFit: props?.objectFit || "contain", streamURL: mediaStream.toURL(), onLayout: handleLayout, pictureInPictureEnabled: props?.pictureInPictureEnabled !== false, autoStartPictureInPicture: true, pictureInPicturePreferredSize: {
168
+ width: 160,
169
+ height: 90,
170
+ }, style: {
171
+ minWidth: "100%",
172
+ minHeight: "100%",
173
+ flex: 1,
174
+ } }) }));
175
+ }
176
+ function NativeIngestPlayer(props) {
177
+ const ingestStarting = (0, __1.usePlayerStore)((x) => x.ingestStarting);
178
+ const ingestMediaSource = (0, __1.usePlayerStore)((x) => x.ingestMediaSource);
179
+ const ingestAutoStart = (0, __1.usePlayerStore)((x) => x.ingestAutoStart);
180
+ const setStatus = (0, __1.usePlayerStore)((x) => x.setStatus);
181
+ const setVideoRef = (0, __1.usePlayerStore)((x) => x.setVideoRef);
182
+ const [error, setError] = (0, react_1.useState)(null);
183
+ const ingestCamera = (0, __1.usePlayerStore)((x) => x.ingestCamera);
184
+ (0, react_1.useEffect)(() => {
185
+ setStatus(__1.PlayerStatus.PLAYING);
186
+ }, [setStatus]);
187
+ (0, react_1.useEffect)(() => {
188
+ if (typeof setVideoRef === "function") {
189
+ setVideoRef(null);
190
+ }
191
+ }, [setVideoRef]);
192
+ const url = (0, __1.useStreamplaceStore)((x) => x.url);
193
+ const [lms, setLocalMediaStream] = (0, react_1.useState)(null);
194
+ const [, setRemoteMediaStream] = (0, use_webrtc_1.useWebRTCIngest)({
195
+ endpoint: `${url}/api/ingest/webrtc`,
196
+ });
197
+ // Use lms directly as localMediaStream
198
+ const localMediaStream = lms;
199
+ (0, react_1.useEffect)(() => {
200
+ if (ingestMediaSource === __1.IngestMediaSource.DISPLAY) {
201
+ webrtc_primitives_native_1.mediaDevices
202
+ .getDisplayMedia()
203
+ .then((stream) => {
204
+ console.log("display media", stream);
205
+ setLocalMediaStream(stream);
206
+ })
207
+ .catch((e) => {
208
+ console.log("error getting display media", e);
209
+ console.error("error getting display media", e);
210
+ });
211
+ }
212
+ else {
213
+ webrtc_primitives_native_1.mediaDevices
214
+ .getUserMedia({
215
+ audio: {
216
+ // deviceId: "audio-1",
217
+ // echoCancellation: true,
218
+ // autoGainControl: true,
219
+ // noiseSuppression: true,
220
+ // latency: false,
221
+ // channelCount: false,
222
+ },
223
+ video: {
224
+ facingMode: ingestCamera,
225
+ width: { min: 200, ideal: 1080, max: 2160 },
226
+ height: { min: 200, ideal: 1920, max: 3840 },
227
+ },
228
+ })
229
+ .then((stream) => {
230
+ setLocalMediaStream(stream);
231
+ let errs = [];
232
+ if (stream.getAudioTracks().length === 0) {
233
+ console.warn("No audio tracks found in user media stream");
234
+ errs.push("microphone");
235
+ }
236
+ if (stream.getVideoTracks().length === 0) {
237
+ console.warn("No video tracks found in user media stream");
238
+ errs.push("camera");
239
+ }
240
+ if (errs.length > 0) {
241
+ setError(new Error(`We could not access your ${errs.join(" and ")}. To stream, you need to give us permission to access these.`));
242
+ }
243
+ else {
244
+ setError(null);
245
+ }
246
+ })
247
+ .catch((e) => {
248
+ console.error("error getting user media", e);
249
+ setError(new Error("We could not access your camera or microphone. To stream, you need to give us permission to access these."));
250
+ });
251
+ }
252
+ }, [ingestMediaSource, ingestCamera]);
253
+ (0, react_1.useEffect)(() => {
254
+ if (!ingestStarting && !ingestAutoStart) {
255
+ setRemoteMediaStream(null);
256
+ return;
257
+ }
258
+ if (!localMediaStream) {
259
+ return;
260
+ }
261
+ console.log("setting remote media stream", localMediaStream);
262
+ // @ts-expect-error: WebRTCMediaStream may not have all MediaStream properties, but is compatible for our use
263
+ setRemoteMediaStream(localMediaStream);
264
+ }, [localMediaStream, ingestStarting, ingestAutoStart, setRemoteMediaStream]);
265
+ if (!localMediaStream) {
266
+ return null;
267
+ }
268
+ if (error) {
269
+ return ((0, jsx_runtime_1.jsxs)(__1.View, { backgroundColor: atoms_1.colors.destructive[900], style: [atoms_1.p[4], atoms_1.m[4], atoms_1.gap.all[2], { borderRadius: atoms_1.borderRadius.md }], children: [(0, jsx_runtime_1.jsx)(__1.View, { children: (0, jsx_runtime_1.jsx)(__1.Text, { style: [atoms_1.fontWeight.semibold], size: "2xl", children: "Error encountered!" }) }), (0, jsx_runtime_1.jsx)(__1.Text, { children: error.message }), error.message.includes("To stream, you need to give us permission to access these.") && ((0, jsx_runtime_1.jsx)(__1.Button, { onPress: react_native_1.Linking.openSettings, style: [atoms_1.h[10]], variant: "secondary", children: (0, jsx_runtime_1.jsxs)(__1.View, { style: [atoms_1.layout.flex.row, atoms_1.gap.all[1]], children: [(0, jsx_runtime_1.jsx)(__1.Text, { children: "Open Settings" }), " ", (0, jsx_runtime_1.jsx)(lucide_react_native_1.ArrowRight, { color: "white", size: "18" })] }) }))] }));
270
+ }
271
+ return ((0, jsx_runtime_1.jsx)(react_native_webrtc_1.RTCView, { mirror: ingestCamera !== "environment", objectFit: props?.objectFit || "contain", streamURL: localMediaStream.toURL(), zOrder: 0, style: {
272
+ minWidth: "100%",
273
+ minHeight: "100%",
274
+ flex: 1,
275
+ } }));
276
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = VideoRetry;
4
+ const tslib_1 = require("tslib");
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = tslib_1.__importStar(require("react"));
7
+ const __1 = require("../..");
8
+ function VideoRetry(props) {
9
+ const retryTimeoutRef = (0, react_1.useRef)(null);
10
+ const [retries, setRetries] = (0, react_1.useState)(0);
11
+ const playing = (0, __1.usePlayerStore)((x) => x.status === __1.PlayerStatus.PLAYING);
12
+ (0, react_1.useEffect)(() => {
13
+ if (!playing) {
14
+ const jitter = 500 + Math.random() * 1500;
15
+ retryTimeoutRef.current = setTimeout(() => {
16
+ console.log("Retrying video playback...");
17
+ setRetries((prevRetries) => prevRetries + 1);
18
+ }, jitter);
19
+ }
20
+ return () => {
21
+ if (retryTimeoutRef.current) {
22
+ console.log("Clearing retry timeout");
23
+ clearTimeout(retryTimeoutRef.current);
24
+ retryTimeoutRef.current = null;
25
+ }
26
+ };
27
+ }, [!playing]);
28
+ return (0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: props.children }, retries);
29
+ }