analytica-frontend-lib 1.1.77 → 1.1.78

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.
@@ -23,7 +23,7 @@ __export(VideoPlayer_exports, {
23
23
  default: () => VideoPlayer_default
24
24
  });
25
25
  module.exports = __toCommonJS(VideoPlayer_exports);
26
- var import_react2 = require("react");
26
+ var import_react3 = require("react");
27
27
  var import_react_dom = require("react-dom");
28
28
  var import_phosphor_react = require("phosphor-react");
29
29
 
@@ -138,6 +138,86 @@ var Text = ({
138
138
  };
139
139
  var Text_default = Text;
140
140
 
141
+ // src/hooks/useMobile.ts
142
+ var import_react2 = require("react");
143
+ var MOBILE_WIDTH = 500;
144
+ var TABLET_WIDTH = 931;
145
+ var SMALL_MOBILE_WIDTH = 425;
146
+ var EXTRA_SMALL_MOBILE_WIDTH = 375;
147
+ var ULTRA_SMALL_MOBILE_WIDTH = 375;
148
+ var TINY_MOBILE_WIDTH = 320;
149
+ var DEFAULT_WIDTH = 1200;
150
+ var getWindowWidth = () => {
151
+ if (typeof window === "undefined") {
152
+ return DEFAULT_WIDTH;
153
+ }
154
+ return window.innerWidth;
155
+ };
156
+ var getDeviceType = () => {
157
+ const width = getWindowWidth();
158
+ return width < TABLET_WIDTH ? "responsive" : "desktop";
159
+ };
160
+ var useMobile = () => {
161
+ const [isMobile, setIsMobile] = (0, import_react2.useState)(false);
162
+ const [isTablet, setIsTablet] = (0, import_react2.useState)(false);
163
+ const [isSmallMobile, setIsSmallMobile] = (0, import_react2.useState)(false);
164
+ const [isExtraSmallMobile, setIsExtraSmallMobile] = (0, import_react2.useState)(false);
165
+ const [isUltraSmallMobile, setIsUltraSmallMobile] = (0, import_react2.useState)(false);
166
+ const [isTinyMobile, setIsTinyMobile] = (0, import_react2.useState)(false);
167
+ (0, import_react2.useEffect)(() => {
168
+ const checkScreenSize = () => {
169
+ const width = getWindowWidth();
170
+ setIsMobile(width < MOBILE_WIDTH);
171
+ setIsTablet(width < TABLET_WIDTH);
172
+ setIsSmallMobile(width < SMALL_MOBILE_WIDTH);
173
+ setIsExtraSmallMobile(width < EXTRA_SMALL_MOBILE_WIDTH);
174
+ setIsUltraSmallMobile(width < ULTRA_SMALL_MOBILE_WIDTH);
175
+ setIsTinyMobile(width < TINY_MOBILE_WIDTH);
176
+ };
177
+ checkScreenSize();
178
+ window.addEventListener("resize", checkScreenSize);
179
+ return () => window.removeEventListener("resize", checkScreenSize);
180
+ }, []);
181
+ const getFormContainerClasses = () => {
182
+ if (isMobile) {
183
+ return "w-full px-4";
184
+ }
185
+ if (isTablet) {
186
+ return "w-full px-6";
187
+ }
188
+ return "w-full max-w-[992px] mx-auto px-0";
189
+ };
190
+ const getMobileHeaderClasses = () => {
191
+ return "flex flex-col items-start gap-4 mb-6";
192
+ };
193
+ const getDesktopHeaderClasses = () => {
194
+ return "flex flex-row justify-between items-center gap-6 mb-8";
195
+ };
196
+ const getHeaderClasses = () => {
197
+ return isMobile ? getMobileHeaderClasses() : getDesktopHeaderClasses();
198
+ };
199
+ const getVideoContainerClasses = () => {
200
+ if (isTinyMobile) return "aspect-square";
201
+ if (isExtraSmallMobile) return "aspect-[4/3]";
202
+ if (isSmallMobile) return "aspect-[16/12]";
203
+ return "aspect-video";
204
+ };
205
+ return {
206
+ isMobile,
207
+ isTablet,
208
+ isSmallMobile,
209
+ isExtraSmallMobile,
210
+ isUltraSmallMobile,
211
+ isTinyMobile,
212
+ getFormContainerClasses,
213
+ getHeaderClasses,
214
+ getMobileHeaderClasses,
215
+ getDesktopHeaderClasses,
216
+ getVideoContainerClasses,
217
+ getDeviceType
218
+ };
219
+ };
220
+
141
221
  // src/components/VideoPlayer/VideoPlayer.tsx
142
222
  var import_jsx_runtime3 = require("react/jsx-runtime");
143
223
  var CONTROLS_HIDE_TIMEOUT = 3e3;
@@ -153,8 +233,9 @@ var ProgressBar = ({
153
233
  currentTime,
154
234
  duration,
155
235
  progressPercentage,
156
- onSeek
157
- }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "px-4 pb-2", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
236
+ onSeek,
237
+ className = "px-4 pb-2"
238
+ }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
158
239
  "input",
159
240
  {
160
241
  type: "range",
@@ -173,18 +254,20 @@ var VolumeControls = ({
173
254
  volume,
174
255
  isMuted,
175
256
  onVolumeChange,
176
- onToggleMute
257
+ onToggleMute,
258
+ iconSize = 24,
259
+ showSlider = true
177
260
  }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-2", children: [
178
261
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
179
262
  IconButton_default,
180
263
  {
181
- icon: isMuted ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.SpeakerSlash, { size: 24 }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.SpeakerHigh, { size: 24 }),
264
+ icon: isMuted ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.SpeakerSlash, { size: iconSize }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.SpeakerHigh, { size: iconSize }),
182
265
  onClick: onToggleMute,
183
266
  "aria-label": isMuted ? "Unmute" : "Mute",
184
267
  className: "!bg-transparent !text-white hover:!bg-white/20"
185
268
  }
186
269
  ),
187
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
270
+ showSlider && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
188
271
  "input",
189
272
  {
190
273
  type: "range",
@@ -205,22 +288,27 @@ var SpeedMenu = ({
205
288
  playbackRate,
206
289
  onToggleMenu,
207
290
  onSpeedChange,
208
- isFullscreen
291
+ isFullscreen,
292
+ iconSize = 24,
293
+ isTinyMobile = false
209
294
  }) => {
210
- const buttonRef = (0, import_react2.useRef)(null);
211
- const speedMenuContainerRef = (0, import_react2.useRef)(null);
212
- const speedMenuRef = (0, import_react2.useRef)(null);
295
+ const buttonRef = (0, import_react3.useRef)(null);
296
+ const speedMenuContainerRef = (0, import_react3.useRef)(null);
297
+ const speedMenuRef = (0, import_react3.useRef)(null);
213
298
  const getMenuPosition = () => {
214
299
  if (!buttonRef.current) return { top: 0, left: 0 };
215
300
  const rect = buttonRef.current.getBoundingClientRect();
301
+ const menuHeight = isTinyMobile ? 150 : 180;
302
+ const menuWidth = isTinyMobile ? 60 : 80;
303
+ const padding = isTinyMobile ? 4 : 8;
216
304
  return {
217
305
  // Fixed coords are viewport-based — no scroll offsets.
218
- top: Math.max(8, rect.top - 180),
219
- left: Math.max(8, rect.right - 80)
306
+ top: Math.max(padding, rect.top - menuHeight),
307
+ left: Math.max(padding, rect.right - menuWidth)
220
308
  };
221
309
  };
222
310
  const position = getMenuPosition();
223
- (0, import_react2.useEffect)(() => {
311
+ (0, import_react3.useEffect)(() => {
224
312
  const handleClickOutside = (event) => {
225
313
  const target = event.target;
226
314
  const isOutsideContainer = speedMenuContainerRef.current && !speedMenuContainerRef.current.contains(target);
@@ -269,7 +357,7 @@ var SpeedMenu = ({
269
357
  IconButton_default,
270
358
  {
271
359
  ref: buttonRef,
272
- icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.DotsThreeVertical, { size: 24 }),
360
+ icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.DotsThreeVertical, { size: iconSize }),
273
361
  onClick: onToggleMenu,
274
362
  "aria-label": "Playback speed",
275
363
  "aria-haspopup": "menu",
@@ -294,26 +382,27 @@ var VideoPlayer = ({
294
382
  autoSave = true,
295
383
  storageKey = "video-progress"
296
384
  }) => {
297
- const videoRef = (0, import_react2.useRef)(null);
298
- const [isPlaying, setIsPlaying] = (0, import_react2.useState)(false);
299
- const [currentTime, setCurrentTime] = (0, import_react2.useState)(0);
300
- const [duration, setDuration] = (0, import_react2.useState)(0);
301
- const [isMuted, setIsMuted] = (0, import_react2.useState)(false);
302
- const [volume, setVolume] = (0, import_react2.useState)(1);
303
- const [isFullscreen, setIsFullscreen] = (0, import_react2.useState)(false);
304
- const [showControls, setShowControls] = (0, import_react2.useState)(true);
305
- const [hasCompleted, setHasCompleted] = (0, import_react2.useState)(false);
306
- const [showCaptions, setShowCaptions] = (0, import_react2.useState)(false);
307
- (0, import_react2.useEffect)(() => {
385
+ const videoRef = (0, import_react3.useRef)(null);
386
+ const { isUltraSmallMobile, isTinyMobile } = useMobile();
387
+ const [isPlaying, setIsPlaying] = (0, import_react3.useState)(false);
388
+ const [currentTime, setCurrentTime] = (0, import_react3.useState)(0);
389
+ const [duration, setDuration] = (0, import_react3.useState)(0);
390
+ const [isMuted, setIsMuted] = (0, import_react3.useState)(false);
391
+ const [volume, setVolume] = (0, import_react3.useState)(1);
392
+ const [isFullscreen, setIsFullscreen] = (0, import_react3.useState)(false);
393
+ const [showControls, setShowControls] = (0, import_react3.useState)(true);
394
+ const [hasCompleted, setHasCompleted] = (0, import_react3.useState)(false);
395
+ const [showCaptions, setShowCaptions] = (0, import_react3.useState)(false);
396
+ (0, import_react3.useEffect)(() => {
308
397
  setHasCompleted(false);
309
398
  }, [src]);
310
- const [playbackRate, setPlaybackRate] = (0, import_react2.useState)(1);
311
- const [showSpeedMenu, setShowSpeedMenu] = (0, import_react2.useState)(false);
312
- const lastSaveTimeRef = (0, import_react2.useRef)(0);
313
- const trackRef = (0, import_react2.useRef)(null);
314
- const controlsTimeoutRef = (0, import_react2.useRef)(null);
315
- const lastMousePositionRef = (0, import_react2.useRef)({ x: 0, y: 0 });
316
- const isUserInteracting = (0, import_react2.useCallback)(() => {
399
+ const [playbackRate, setPlaybackRate] = (0, import_react3.useState)(1);
400
+ const [showSpeedMenu, setShowSpeedMenu] = (0, import_react3.useState)(false);
401
+ const lastSaveTimeRef = (0, import_react3.useRef)(0);
402
+ const trackRef = (0, import_react3.useRef)(null);
403
+ const controlsTimeoutRef = (0, import_react3.useRef)(null);
404
+ const lastMousePositionRef = (0, import_react3.useRef)({ x: 0, y: 0 });
405
+ const isUserInteracting = (0, import_react3.useCallback)(() => {
317
406
  if (showSpeedMenu) {
318
407
  return true;
319
408
  }
@@ -330,13 +419,13 @@ var VideoPlayer = ({
330
419
  }
331
420
  return false;
332
421
  }, [showSpeedMenu]);
333
- const clearControlsTimeout = (0, import_react2.useCallback)(() => {
422
+ const clearControlsTimeout = (0, import_react3.useCallback)(() => {
334
423
  if (controlsTimeoutRef.current) {
335
424
  clearTimeout(controlsTimeoutRef.current);
336
425
  controlsTimeoutRef.current = null;
337
426
  }
338
427
  }, []);
339
- const showControlsWithTimer = (0, import_react2.useCallback)(() => {
428
+ const showControlsWithTimer = (0, import_react3.useCallback)(() => {
340
429
  setShowControls(true);
341
430
  clearControlsTimeout();
342
431
  if (isFullscreen) {
@@ -351,7 +440,7 @@ var VideoPlayer = ({
351
440
  }, CONTROLS_HIDE_TIMEOUT);
352
441
  }
353
442
  }, [isFullscreen, isPlaying, clearControlsTimeout]);
354
- const handleMouseMove = (0, import_react2.useCallback)(
443
+ const handleMouseMove = (0, import_react3.useCallback)(
355
444
  (event) => {
356
445
  const currentX = event.clientX;
357
446
  const currentY = event.clientY;
@@ -364,10 +453,10 @@ var VideoPlayer = ({
364
453
  },
365
454
  [showControlsWithTimer]
366
455
  );
367
- const handleMouseEnter = (0, import_react2.useCallback)(() => {
456
+ const handleMouseEnter = (0, import_react3.useCallback)(() => {
368
457
  showControlsWithTimer();
369
458
  }, [showControlsWithTimer]);
370
- const handleMouseLeave = (0, import_react2.useCallback)(() => {
459
+ const handleMouseLeave = (0, import_react3.useCallback)(() => {
371
460
  const userInteracting = isUserInteracting();
372
461
  clearControlsTimeout();
373
462
  if (!isFullscreen && !userInteracting) {
@@ -376,13 +465,13 @@ var VideoPlayer = ({
376
465
  }, LEAVE_HIDE_TIMEOUT);
377
466
  }
378
467
  }, [isFullscreen, clearControlsTimeout, isUserInteracting]);
379
- (0, import_react2.useEffect)(() => {
468
+ (0, import_react3.useEffect)(() => {
380
469
  if (videoRef.current) {
381
470
  videoRef.current.volume = volume;
382
471
  videoRef.current.muted = isMuted;
383
472
  }
384
473
  }, [volume, isMuted]);
385
- (0, import_react2.useEffect)(() => {
474
+ (0, import_react3.useEffect)(() => {
386
475
  const video = videoRef.current;
387
476
  if (!video) return;
388
477
  const onPlay = () => setIsPlaying(true);
@@ -397,7 +486,13 @@ var VideoPlayer = ({
397
486
  video.removeEventListener("ended", onEnded);
398
487
  };
399
488
  }, []);
400
- (0, import_react2.useEffect)(() => {
489
+ (0, import_react3.useEffect)(() => {
490
+ const video = videoRef.current;
491
+ if (!video) return;
492
+ video.setAttribute("playsinline", "");
493
+ video.setAttribute("webkit-playsinline", "");
494
+ }, []);
495
+ (0, import_react3.useEffect)(() => {
401
496
  if (isPlaying) {
402
497
  showControlsWithTimer();
403
498
  } else {
@@ -409,7 +504,7 @@ var VideoPlayer = ({
409
504
  }
410
505
  }
411
506
  }, [isPlaying, isFullscreen, showControlsWithTimer, clearControlsTimeout]);
412
- (0, import_react2.useEffect)(() => {
507
+ (0, import_react3.useEffect)(() => {
413
508
  const handleFullscreenChange = () => {
414
509
  const isCurrentlyFullscreen = !!document.fullscreenElement;
415
510
  setIsFullscreen(isCurrentlyFullscreen);
@@ -422,7 +517,7 @@ var VideoPlayer = ({
422
517
  document.removeEventListener("fullscreenchange", handleFullscreenChange);
423
518
  };
424
519
  }, [showControlsWithTimer]);
425
- (0, import_react2.useEffect)(() => {
520
+ (0, import_react3.useEffect)(() => {
426
521
  const init = () => {
427
522
  if (!isFullscreen) {
428
523
  showControlsWithTimer();
@@ -444,7 +539,7 @@ var VideoPlayer = ({
444
539
  };
445
540
  }
446
541
  }, []);
447
- const getInitialTime = (0, import_react2.useCallback)(() => {
542
+ const getInitialTime = (0, import_react3.useCallback)(() => {
448
543
  if (!autoSave || !storageKey) {
449
544
  return Number.isFinite(initialTime) && initialTime >= 0 ? initialTime : void 0;
450
545
  }
@@ -455,14 +550,14 @@ var VideoPlayer = ({
455
550
  if (hasValidSaved) return saved;
456
551
  return void 0;
457
552
  }, [autoSave, storageKey, src, initialTime]);
458
- (0, import_react2.useEffect)(() => {
553
+ (0, import_react3.useEffect)(() => {
459
554
  const start = getInitialTime();
460
555
  if (start !== void 0 && videoRef.current) {
461
556
  videoRef.current.currentTime = start;
462
557
  setCurrentTime(start);
463
558
  }
464
559
  }, [getInitialTime]);
465
- const saveProgress = (0, import_react2.useCallback)(
560
+ const saveProgress = (0, import_react3.useCallback)(
466
561
  (time) => {
467
562
  if (!autoSave || !storageKey) return;
468
563
  const now = Date.now();
@@ -473,7 +568,7 @@ var VideoPlayer = ({
473
568
  },
474
569
  [autoSave, storageKey, src]
475
570
  );
476
- const togglePlayPause = (0, import_react2.useCallback)(async () => {
571
+ const togglePlayPause = (0, import_react3.useCallback)(async () => {
477
572
  const video = videoRef.current;
478
573
  if (!video) return;
479
574
  if (!video.paused) {
@@ -485,7 +580,7 @@ var VideoPlayer = ({
485
580
  } catch {
486
581
  }
487
582
  }, []);
488
- const handleVolumeChange = (0, import_react2.useCallback)(
583
+ const handleVolumeChange = (0, import_react3.useCallback)(
489
584
  (newVolume) => {
490
585
  const video = videoRef.current;
491
586
  if (!video) return;
@@ -504,7 +599,7 @@ var VideoPlayer = ({
504
599
  },
505
600
  [isMuted]
506
601
  );
507
- const toggleMute = (0, import_react2.useCallback)(() => {
602
+ const toggleMute = (0, import_react3.useCallback)(() => {
508
603
  const video = videoRef.current;
509
604
  if (!video) return;
510
605
  if (isMuted) {
@@ -518,13 +613,13 @@ var VideoPlayer = ({
518
613
  setIsMuted(true);
519
614
  }
520
615
  }, [isMuted, volume]);
521
- const handleSeek = (0, import_react2.useCallback)((newTime) => {
616
+ const handleSeek = (0, import_react3.useCallback)((newTime) => {
522
617
  const video = videoRef.current;
523
618
  if (video) {
524
619
  video.currentTime = newTime;
525
620
  }
526
621
  }, []);
527
- const toggleFullscreen = (0, import_react2.useCallback)(() => {
622
+ const toggleFullscreen = (0, import_react3.useCallback)(() => {
528
623
  const container = videoRef.current?.parentElement;
529
624
  if (!container) return;
530
625
  if (!isFullscreen && container.requestFullscreen) {
@@ -533,23 +628,23 @@ var VideoPlayer = ({
533
628
  document.exitFullscreen();
534
629
  }
535
630
  }, [isFullscreen]);
536
- const handleSpeedChange = (0, import_react2.useCallback)((speed) => {
631
+ const handleSpeedChange = (0, import_react3.useCallback)((speed) => {
537
632
  if (videoRef.current) {
538
633
  videoRef.current.playbackRate = speed;
539
634
  setPlaybackRate(speed);
540
635
  setShowSpeedMenu(false);
541
636
  }
542
637
  }, []);
543
- const toggleSpeedMenu = (0, import_react2.useCallback)(() => {
638
+ const toggleSpeedMenu = (0, import_react3.useCallback)(() => {
544
639
  setShowSpeedMenu(!showSpeedMenu);
545
640
  }, [showSpeedMenu]);
546
- const toggleCaptions = (0, import_react2.useCallback)(() => {
641
+ const toggleCaptions = (0, import_react3.useCallback)(() => {
547
642
  if (!trackRef.current?.track || !subtitles) return;
548
643
  const newShowCaptions = !showCaptions;
549
644
  setShowCaptions(newShowCaptions);
550
645
  trackRef.current.track.mode = newShowCaptions && subtitles ? "showing" : "hidden";
551
646
  }, [showCaptions, subtitles]);
552
- const checkVideoCompletion = (0, import_react2.useCallback)(
647
+ const checkVideoCompletion = (0, import_react3.useCallback)(
553
648
  (progressPercent) => {
554
649
  if (progressPercent >= 95 && !hasCompleted) {
555
650
  setHasCompleted(true);
@@ -558,7 +653,7 @@ var VideoPlayer = ({
558
653
  },
559
654
  [hasCompleted, onVideoComplete]
560
655
  );
561
- const handleTimeUpdate = (0, import_react2.useCallback)(() => {
656
+ const handleTimeUpdate = (0, import_react3.useCallback)(() => {
562
657
  const video = videoRef.current;
563
658
  if (!video) return;
564
659
  const current = video.currentTime;
@@ -571,17 +666,17 @@ var VideoPlayer = ({
571
666
  checkVideoCompletion(progressPercent);
572
667
  }
573
668
  }, [duration, saveProgress, onTimeUpdate, onProgress, checkVideoCompletion]);
574
- const handleLoadedMetadata = (0, import_react2.useCallback)(() => {
669
+ const handleLoadedMetadata = (0, import_react3.useCallback)(() => {
575
670
  if (videoRef.current) {
576
671
  setDuration(videoRef.current.duration);
577
672
  }
578
673
  }, []);
579
- (0, import_react2.useEffect)(() => {
674
+ (0, import_react3.useEffect)(() => {
580
675
  if (trackRef.current?.track) {
581
676
  trackRef.current.track.mode = showCaptions && subtitles ? "showing" : "hidden";
582
677
  }
583
678
  }, [subtitles, showCaptions]);
584
- (0, import_react2.useEffect)(() => {
679
+ (0, import_react3.useEffect)(() => {
585
680
  const handleVisibilityChange = () => {
586
681
  if (document.hidden && isPlaying && videoRef.current) {
587
682
  videoRef.current.pause();
@@ -603,13 +698,38 @@ var VideoPlayer = ({
603
698
  };
604
699
  }, [isPlaying, clearControlsTimeout]);
605
700
  const progressPercentage = duration > 0 ? currentTime / duration * 100 : 0;
606
- const getTopControlsOpacity = (0, import_react2.useCallback)(() => {
701
+ const getIconSize = (0, import_react3.useCallback)(() => {
702
+ if (isTinyMobile) return 18;
703
+ if (isUltraSmallMobile) return 20;
704
+ return 24;
705
+ }, [isTinyMobile, isUltraSmallMobile]);
706
+ const getControlsPadding = (0, import_react3.useCallback)(() => {
707
+ if (isTinyMobile) return "px-2 pb-2 pt-1";
708
+ if (isUltraSmallMobile) return "px-3 pb-3 pt-1";
709
+ return "px-4 pb-4";
710
+ }, [isTinyMobile, isUltraSmallMobile]);
711
+ const getControlsGap = (0, import_react3.useCallback)(() => {
712
+ if (isTinyMobile) return "gap-1";
713
+ if (isUltraSmallMobile) return "gap-2";
714
+ return "gap-4";
715
+ }, [isTinyMobile, isUltraSmallMobile]);
716
+ const getProgressBarPadding = (0, import_react3.useCallback)(() => {
717
+ if (isTinyMobile) return "px-2 pb-1";
718
+ if (isUltraSmallMobile) return "px-3 pb-1";
719
+ return "px-4 pb-2";
720
+ }, [isTinyMobile, isUltraSmallMobile]);
721
+ const getCenterPlayButtonPosition = (0, import_react3.useCallback)(() => {
722
+ if (isTinyMobile) return "items-center justify-center -translate-y-12";
723
+ if (isUltraSmallMobile) return "items-center justify-center -translate-y-8";
724
+ return "items-center justify-center";
725
+ }, [isTinyMobile, isUltraSmallMobile]);
726
+ const getTopControlsOpacity = (0, import_react3.useCallback)(() => {
607
727
  return showControls ? "opacity-100" : "opacity-0";
608
728
  }, [showControls]);
609
- const getBottomControlsOpacity = (0, import_react2.useCallback)(() => {
729
+ const getBottomControlsOpacity = (0, import_react3.useCallback)(() => {
610
730
  return showControls ? "opacity-100" : "opacity-0";
611
731
  }, [showControls]);
612
- const handleVideoKeyDown = (0, import_react2.useCallback)(
732
+ const handleVideoKeyDown = (0, import_react3.useCallback)(
613
733
  (e) => {
614
734
  if (e.key) {
615
735
  e.stopPropagation();
@@ -710,8 +830,9 @@ var VideoPlayer = ({
710
830
  ref: videoRef,
711
831
  src,
712
832
  poster,
713
- className: "w-full h-full object-contain",
833
+ className: "w-full h-full object-contain analytica-video",
714
834
  controlsList: "nodownload",
835
+ playsInline: true,
715
836
  onTimeUpdate: handleTimeUpdate,
716
837
  onLoadedMetadata: handleLoadedMetadata,
717
838
  onClick: togglePlayPause,
@@ -731,15 +852,24 @@ var VideoPlayer = ({
731
852
  )
732
853
  }
733
854
  ),
734
- !isPlaying && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "absolute inset-0 flex items-center justify-center bg-black/30 transition-opacity", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
735
- IconButton_default,
855
+ !isPlaying && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
856
+ "div",
736
857
  {
737
- icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.Play, { size: 32, weight: "regular", className: "ml-1" }),
738
- onClick: togglePlayPause,
739
- "aria-label": "Play video",
740
- className: "!bg-transparent !text-white !w-auto !h-auto hover:!bg-transparent hover:!text-gray-200"
858
+ className: cn(
859
+ "absolute inset-0 flex bg-black/30 transition-opacity",
860
+ getCenterPlayButtonPosition()
861
+ ),
862
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
863
+ IconButton_default,
864
+ {
865
+ icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.Play, { size: 32, weight: "regular", className: "ml-1" }),
866
+ onClick: togglePlayPause,
867
+ "aria-label": "Play video",
868
+ className: "!bg-transparent !text-white !w-auto !h-auto hover:!bg-transparent hover:!text-gray-200"
869
+ }
870
+ )
741
871
  }
742
- ) }),
872
+ ),
743
873
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
744
874
  "div",
745
875
  {
@@ -772,58 +902,72 @@ var VideoPlayer = ({
772
902
  currentTime,
773
903
  duration,
774
904
  progressPercentage,
775
- onSeek: handleSeek
905
+ onSeek: handleSeek,
906
+ className: getProgressBarPadding()
776
907
  }
777
908
  ),
778
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center justify-between px-4 pb-4", children: [
779
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-4", children: [
780
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
781
- IconButton_default,
782
- {
783
- icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.Pause, { size: 24 }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.Play, { size: 24 }),
784
- onClick: togglePlayPause,
785
- "aria-label": isPlaying ? "Pause" : "Play",
786
- className: "!bg-transparent !text-white hover:!bg-white/20"
787
- }
788
- ),
789
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
790
- VolumeControls,
791
- {
792
- volume,
793
- isMuted,
794
- onVolumeChange: handleVolumeChange,
795
- onToggleMute: toggleMute
796
- }
797
- ),
798
- subtitles && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
799
- IconButton_default,
800
- {
801
- icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.ClosedCaptioning, { size: 24 }),
802
- onClick: toggleCaptions,
803
- "aria-label": showCaptions ? "Hide captions" : "Show captions",
804
- className: cn(
805
- "!bg-transparent hover:!bg-white/20",
806
- showCaptions ? "!text-primary-400" : "!text-white"
807
- )
808
- }
909
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
910
+ "div",
911
+ {
912
+ className: cn(
913
+ "flex items-center justify-between",
914
+ getControlsPadding()
809
915
  ),
810
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text_default, { size: "sm", weight: "medium", color: "text-white", children: [
811
- formatTime(currentTime),
812
- " / ",
813
- formatTime(duration)
814
- ] })
815
- ] }),
816
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
817
- SpeedMenu,
818
- {
819
- showSpeedMenu,
820
- playbackRate,
821
- onToggleMenu: toggleSpeedMenu,
822
- onSpeedChange: handleSpeedChange,
823
- isFullscreen
824
- }
825
- ) })
826
- ] })
916
+ children: [
917
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: cn("flex items-center", getControlsGap()), children: [
918
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
919
+ IconButton_default,
920
+ {
921
+ icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.Pause, { size: getIconSize() }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.Play, { size: getIconSize() }),
922
+ onClick: togglePlayPause,
923
+ "aria-label": isPlaying ? "Pause" : "Play",
924
+ className: "!bg-transparent !text-white hover:!bg-white/20"
925
+ }
926
+ ),
927
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
928
+ VolumeControls,
929
+ {
930
+ volume,
931
+ isMuted,
932
+ onVolumeChange: handleVolumeChange,
933
+ onToggleMute: toggleMute,
934
+ iconSize: getIconSize(),
935
+ showSlider: !isUltraSmallMobile
936
+ }
937
+ ),
938
+ subtitles && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
939
+ IconButton_default,
940
+ {
941
+ icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_phosphor_react.ClosedCaptioning, { size: getIconSize() }),
942
+ onClick: toggleCaptions,
943
+ "aria-label": showCaptions ? "Hide captions" : "Show captions",
944
+ className: cn(
945
+ "!bg-transparent hover:!bg-white/20",
946
+ showCaptions ? "!text-primary-400" : "!text-white"
947
+ )
948
+ }
949
+ ),
950
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text_default, { size: "sm", weight: "medium", color: "text-white", children: [
951
+ formatTime(currentTime),
952
+ " / ",
953
+ formatTime(duration)
954
+ ] })
955
+ ] }),
956
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
957
+ SpeedMenu,
958
+ {
959
+ showSpeedMenu,
960
+ playbackRate,
961
+ onToggleMenu: toggleSpeedMenu,
962
+ onSpeedChange: handleSpeedChange,
963
+ iconSize: getIconSize(),
964
+ isTinyMobile,
965
+ isFullscreen
966
+ }
967
+ ) })
968
+ ]
969
+ }
970
+ )
827
971
  ]
828
972
  }
829
973
  )