@rxdrag/website-lib-core 0.0.109 → 0.0.111

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rxdrag/website-lib-core",
3
- "version": "0.0.109",
3
+ "version": "0.0.111",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.ts"
@@ -34,8 +34,8 @@
34
34
  "gsap": "^3.12.7",
35
35
  "hls.js": "^1.6.13",
36
36
  "lodash-es": "^4.17.21",
37
- "@rxdrag/rxcms-models": "0.3.96",
38
- "@rxdrag/entify-lib": "0.0.23"
37
+ "@rxdrag/entify-lib": "0.0.23",
38
+ "@rxdrag/rxcms-models": "0.3.96"
39
39
  },
40
40
  "peerDependencies": {
41
41
  "astro": "^4.0.0 || ^5.0.0",
@@ -19,6 +19,8 @@ export type VideoPlayerClassNames = {
19
19
  playButtonOuter?: string;
20
20
  playButtonInner?: string;
21
21
  playIcon?: string;
22
+ loadingOverlay?: string;
23
+ loadingContent?: string;
22
24
  overlay?: string;
23
25
  overlayTitle?: string;
24
26
  ctaButton?: string;
@@ -54,17 +56,22 @@ export const ReactVideoPlayer = forwardRef<
54
56
  const [isPlaying, setIsPlaying] = useState(false);
55
57
  const [isEnded, setIsEnded] = useState(false);
56
58
  const [isSourceReady, setIsSourceReady] = useState(false);
59
+ const sourceReadyRef = useRef(false);
60
+ const [isLoading, setIsLoading] = useState(false);
61
+ const isEndedRef = useRef(false);
62
+ const [hasStarted, setHasStarted] = useState(false);
57
63
 
58
64
  const ensureSourceReady = useCallback(() => {
59
65
  const video = videoRef.current;
60
66
  const url = media.file?.original;
61
67
  if (!video || !url) return false;
62
- if (isSourceReady) return true;
68
+ if (sourceReadyRef.current) return true;
63
69
 
64
70
  if (media.storageType === "cloudflare_stream") {
65
71
  if (!Hls.isSupported()) {
66
72
  if (video.canPlayType("application/vnd.apple.mpegurl")) {
67
73
  video.src = url;
74
+ sourceReadyRef.current = true;
68
75
  setIsSourceReady(true);
69
76
  return true;
70
77
  }
@@ -90,14 +97,16 @@ export const ReactVideoPlayer = forwardRef<
90
97
  hls.loadSource(url);
91
98
  hls.attachMedia(video);
92
99
  hlsRef.current = hls;
100
+ sourceReadyRef.current = true;
93
101
  setIsSourceReady(true);
94
102
  return true;
95
103
  }
96
104
 
97
105
  video.src = url;
106
+ sourceReadyRef.current = true;
98
107
  setIsSourceReady(true);
99
108
  return true;
100
- }, [isSourceReady, media.file?.original, media.storageType]);
109
+ }, [media.file?.original, media.storageType]);
101
110
 
102
111
  const handleContainerClick = useCallback(
103
112
  (e: React.MouseEvent) => {
@@ -128,7 +137,12 @@ export const ReactVideoPlayer = forwardRef<
128
137
  const ok = ensureSourceReady();
129
138
  if (!ok) return;
130
139
 
131
- v.play();
140
+ setIsLoading(true);
141
+
142
+ v.play().catch((error) => {
143
+ console.log("ReactVideoPlayer play() failed:", error);
144
+ setIsLoading(false);
145
+ });
132
146
  },
133
147
  [isPlaying, designMode, ensureSourceReady]
134
148
  );
@@ -137,6 +151,7 @@ export const ReactVideoPlayer = forwardRef<
137
151
  const video = videoRef.current;
138
152
  if (!video) return;
139
153
 
154
+ video.pause();
140
155
  if (hlsRef.current) {
141
156
  hlsRef.current.destroy();
142
157
  hlsRef.current = null;
@@ -144,20 +159,35 @@ export const ReactVideoPlayer = forwardRef<
144
159
  video.removeAttribute("src");
145
160
  video.load();
146
161
  setIsSourceReady(false);
162
+ sourceReadyRef.current = false;
147
163
 
148
164
  const onPlay = () => {
149
165
  setIsPlaying(true);
150
166
  setIsEnded(false);
167
+ isEndedRef.current = false;
168
+ setIsLoading(false);
169
+ setHasStarted(true);
151
170
  };
152
171
  const onPause = () => setIsPlaying(false);
153
172
  const onEnded = () => {
154
173
  setIsPlaying(false);
155
174
  setIsEnded(true);
175
+ isEndedRef.current = true;
176
+ setIsLoading(false);
177
+ };
178
+ const onWaiting = () => {
179
+ if (!isEndedRef.current) setIsLoading(true);
180
+ };
181
+ const onCanPlay = () => {
182
+ setIsLoading(false);
156
183
  };
157
184
 
158
185
  video.addEventListener("play", onPlay);
159
186
  video.addEventListener("pause", onPause);
160
187
  video.addEventListener("ended", onEnded);
188
+ video.addEventListener("waiting", onWaiting);
189
+ video.addEventListener("canplay", onCanPlay);
190
+ video.addEventListener("playing", onCanPlay);
161
191
 
162
192
  if (eagerLoad) {
163
193
  ensureSourceReady();
@@ -167,6 +197,9 @@ export const ReactVideoPlayer = forwardRef<
167
197
  video.removeEventListener("play", onPlay);
168
198
  video.removeEventListener("pause", onPause);
169
199
  video.removeEventListener("ended", onEnded);
200
+ video.removeEventListener("waiting", onWaiting);
201
+ video.removeEventListener("canplay", onCanPlay);
202
+ video.removeEventListener("playing", onCanPlay);
170
203
 
171
204
  if (hlsRef.current) {
172
205
  hlsRef.current.destroy();
@@ -194,7 +227,8 @@ export const ReactVideoPlayer = forwardRef<
194
227
  "w-full h-full rounded-lg object-cover",
195
228
  classNames?.video
196
229
  )}
197
- controls={!designMode}
230
+ playsInline
231
+ controls={!designMode && hasStarted}
198
232
  >
199
233
  {!media.storageType && media.file?.original && (eagerLoad || isSourceReady) ? (
200
234
  <source src={media.file.original} />
@@ -202,7 +236,7 @@ export const ReactVideoPlayer = forwardRef<
202
236
  Your browser does not support video playback.
203
237
  </video>
204
238
 
205
- {!isPlaying && !isEnded && (
239
+ {!isPlaying && !isEnded && !isLoading && (
206
240
  <button
207
241
  type="button"
208
242
  onClick={handlePlayClick}
@@ -243,6 +277,26 @@ export const ReactVideoPlayer = forwardRef<
243
277
  </button>
244
278
  )}
245
279
 
280
+ {!isPlaying && !isEnded && isLoading && (
281
+ <div
282
+ className={clsx(
283
+ "absolute inset-0 flex items-center justify-center w-full h-full rounded-lg z-10 bg-black/20",
284
+ classNames?.loadingOverlay
285
+ )}
286
+ onClick={(e) => e.stopPropagation()}
287
+ >
288
+ <div
289
+ className={clsx(
290
+ "flex items-center gap-3 rounded-full bg-black/50 px-4 py-2 text-white",
291
+ classNames?.loadingContent
292
+ )}
293
+ >
294
+ <div className="h-4 w-4 animate-spin rounded-full border-2 border-white/30 border-t-white" />
295
+ <span className="text-sm">Loading...</span>
296
+ </div>
297
+ </div>
298
+ )}
299
+
246
300
  <div
247
301
  className={clsx(
248
302
  "absolute inset-0 bg-black/50 flex-col gap-6 items-center justify-center text-center text-white hidden z-10 rounded-2xl",
@@ -277,9 +331,13 @@ export const ReactVideoPlayer = forwardRef<
277
331
  if (!v) return;
278
332
  const ok = ensureSourceReady();
279
333
  if (!ok) return;
334
+ setIsLoading(true);
280
335
  v.currentTime = 0;
281
336
  setIsEnded(false);
282
- v.play();
337
+ v.play().catch((error) => {
338
+ console.log("ReactVideoPlayer play() failed:", error);
339
+ setIsLoading(false);
340
+ });
283
341
  }}
284
342
  >
285
343
  Replay