@zuude-ui/video 0.1.35 → 0.1.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,102 +1,69 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import React, { ComponentPropsWithoutRef, ReactNode, RefObject } from 'react';
2
+ import React from 'react';
3
+ import { V as VideoRef, a as VideoAutoplay } from './types-DejCaLAg.js';
4
+ export { C as CustomVideoRef } from './types-DejCaLAg.js';
3
5
 
4
- type VideoAutoplay = boolean | "force";
5
- type VideoRef = RefObject<(Omit<HTMLVideoElement, "autoplay"> & {
6
- autoplay?: VideoAutoplay;
7
- }) | null>;
8
- type VideoChildren = ReactNode | ((props: {
9
- isPlaying: boolean;
10
- togglePlay: () => void;
11
- isMuted: boolean;
12
- toggleMute: () => void;
13
- speed: number;
14
- onChangeSpeed: (speed: number) => void;
15
- duration: number | null;
16
- isFullscreen: boolean;
17
- toggleFullscreen: () => void;
18
- isPictureInPicture: boolean;
19
- togglePictureInPicture: () => void;
20
- showHidingElement: boolean;
21
- }) => ReactNode);
22
- type VideoConfig = {
23
- startAt?: number;
24
- range?: [number, number];
25
- autoplayOnVisible?: boolean | number;
26
- muteFallback?: (toggleMute: () => void) => ReactNode;
27
- clickToPlay?: boolean;
28
- };
29
- interface VideoProps extends Omit<ComponentPropsWithoutRef<"video">, "children" | "autoPlay" | "controls"> {
30
- children?: VideoChildren;
31
- autoPlay?: VideoAutoplay;
32
- ratio?: string;
33
- config?: VideoConfig;
34
- controls?: boolean;
6
+ interface VideoConfig {
7
+ config?: Partial<{
8
+ clickToPlay: boolean;
9
+ }>;
35
10
  }
36
- interface VideoContextType {
11
+ interface VideoContextType extends VideoConfig {
37
12
  videoRef: VideoRef;
38
- duration: number | null;
39
- isFullscreen?: boolean;
40
- setIsFullscreen?: (isFullscreen: boolean) => void;
41
- isPictureInPicture?: boolean;
42
- setIsPictureInPicture?: (isPictureInPicture: boolean) => void;
43
- showHidingElement?: boolean;
44
- setShowHidingElement?: (showHidingElement: boolean) => void;
13
+ setVideoRef: (video: VideoRef) => void;
14
+ error: string | null;
15
+ setError: (error: string | null) => void;
16
+ isFocused: boolean;
17
+ setIsFocused: (isFocused: boolean) => void;
45
18
  }
46
-
47
- interface HidingElementProps extends React.ComponentPropsWithoutRef<"div"> {
19
+ type VideoProviderProps = Omit<React.ComponentProps<"div">, "onError"> & VideoConfig & {
48
20
  children: React.ReactNode;
49
- className?: string;
50
- }
51
-
52
- /**
53
- * Using compound components pattern
54
- */
55
- declare const Video: React.ForwardRefExoticComponent<VideoProps & {
56
- pause?: boolean;
57
- } & React.RefAttributes<HTMLVideoElement>> & {
58
- PlayPauseOnVideo: () => react_jsx_runtime.JSX.Element;
59
- HidingElement: React.ComponentType<HidingElementProps>;
21
+ onError?: (error: string | null) => void;
60
22
  };
61
-
23
+ declare const VideoProvider: React.MemoExoticComponent<({ children, config, onError, ...props }: VideoProviderProps) => react_jsx_runtime.JSX.Element>;
62
24
  declare const useVideo: () => VideoContextType;
63
25
 
64
- declare const useVolume: () => {
65
- volume: number;
66
- onChangeVolume: (volume: number) => void;
67
- };
68
-
69
- declare const useTimeline: () => {
70
- currentTime: number;
71
- duration: number | null;
72
- buffered: number;
73
- setCurrentTime: React.Dispatch<React.SetStateAction<number>>;
74
- };
75
-
76
- declare const useGetDuration: (ref: VideoRef) => {
77
- duration: number | null;
78
- isLoading: boolean;
79
- };
80
-
81
- declare const usePlayPause: (ref: VideoRef, enabled: boolean) => {
82
- togglePlay: () => void;
83
- isPlaying: boolean;
84
- };
85
-
86
- declare const useMuteUnmute: (ref: VideoRef, enabled: boolean) => {
87
- toggleMute: () => void;
88
- isMuted: boolean;
89
- };
90
-
91
- declare const useStartAt: (ref: VideoRef, startAt?: VideoConfig["startAt"]) => void;
92
-
93
- declare const useFullscreen: () => {
94
- isFullscreen: boolean;
95
- toggleFullscreen: () => void;
96
- };
97
-
98
- declare const useAutoplayByForce: (ref: VideoRef | null, enabled: boolean, setError?: (error: string | null) => void) => void;
26
+ interface Props$1 extends Omit<React.ComponentProps<"video">, "autoPlay" | "preload"> {
27
+ src: string;
28
+ autoPlay?: VideoAutoplay;
29
+ controls?: boolean;
30
+ preload?: "none" | "metadata" | "auto";
31
+ muteFallback?: (onMute: () => void) => React.ReactNode;
32
+ autoPlayOnVisible?: boolean | number;
33
+ }
34
+ declare const Video: React.ForwardRefExoticComponent<Omit<Props$1, "ref"> & React.RefAttributes<HTMLVideoElement>>;
99
35
 
100
- declare function formatTime(time: number, type?: "h:mm:ss" | "mm:ss"): string;
36
+ interface ControlsProps extends React.ComponentProps<"div"> {
37
+ children: React.ReactNode;
38
+ asChild?: boolean;
39
+ }
40
+ declare const Controls: React.MemoExoticComponent<({ children, asChild, ...props }: ControlsProps) => react_jsx_runtime.JSX.Element>;
41
+ interface Props extends React.ComponentProps<"button"> {
42
+ children: React.ReactNode;
43
+ asChild?: boolean;
44
+ }
45
+ declare const Play: React.MemoExoticComponent<({ children, asChild, ...props }: Props) => react_jsx_runtime.JSX.Element>;
46
+ declare const Pause: React.MemoExoticComponent<({ children, asChild, ...props }: Props) => react_jsx_runtime.JSX.Element>;
47
+ declare const Mute: React.MemoExoticComponent<({ children, asChild, ...props }: Props) => react_jsx_runtime.JSX.Element>;
48
+ declare const Unmute: React.MemoExoticComponent<({ children, asChild, ...props }: Props) => react_jsx_runtime.JSX.Element>;
49
+ interface SpeedProps extends Props {
50
+ value: number;
51
+ onClick?: () => void;
52
+ }
53
+ declare const Speed: React.MemoExoticComponent<({ children, asChild, value, onClick, ...props }: SpeedProps) => react_jsx_runtime.JSX.Element>;
54
+ declare const SeekForward: React.MemoExoticComponent<({ children, asChild, ...props }: Props) => react_jsx_runtime.JSX.Element>;
55
+ declare const SeekBackward: React.MemoExoticComponent<({ children, asChild, ...props }: Props) => react_jsx_runtime.JSX.Element>;
56
+ declare const Fullscreen: React.MemoExoticComponent<({ children, asChild, ...props }: Props) => react_jsx_runtime.JSX.Element>;
57
+ declare const ExitFullscreen: React.MemoExoticComponent<({ children, asChild, ...props }: Props) => react_jsx_runtime.JSX.Element>;
58
+ declare const PictureInPicture: React.MemoExoticComponent<({ children, asChild, ...props }: Props) => react_jsx_runtime.JSX.Element>;
59
+ declare const Download: React.MemoExoticComponent<({ children, asChild, ...props }: Props) => react_jsx_runtime.JSX.Element>;
60
+ interface LoadingProps extends React.ComponentProps<"div"> {
61
+ children: React.ReactNode;
62
+ asChild?: boolean;
63
+ }
64
+ declare const Loading: React.MemoExoticComponent<({ children, asChild, ...props }: LoadingProps) => react_jsx_runtime.JSX.Element>;
65
+ interface ShadowProps extends React.ComponentProps<"div"> {
66
+ }
67
+ declare const Shadow: ({ ...props }: ShadowProps) => react_jsx_runtime.JSX.Element | null;
101
68
 
102
- export { Video, type VideoContextType, type VideoProps, formatTime, useAutoplayByForce, useFullscreen, useGetDuration, useMuteUnmute, usePlayPause, useStartAt, useTimeline, useVideo, useVolume };
69
+ export { Controls, Download, ExitFullscreen, Fullscreen, Loading, Mute, Pause, PictureInPicture, Play, SeekBackward, SeekForward, Shadow, Speed, Unmute, Video, VideoAutoplay, VideoProvider, VideoRef, useVideo };
package/dist/index.js CHANGED
@@ -1,3 +1,2 @@
1
- "use client";import{a as C}from"./chunk-WLYC6MHJ.js";function R(e,{insertAt:n}={}){if(!e||typeof document=="undefined")return;let r=document.head||document.getElementsByTagName("head")[0],t=document.createElement("style");t.type="text/css",n==="top"&&r.firstChild?r.insertBefore(t,r.firstChild):r.appendChild(t),t.styleSheet?t.styleSheet.cssText=e:t.appendChild(document.createTextNode(e))}R(`.reset-styles{box-sizing:border-box;padding:0;margin:0}[data-zuude-video-wrapper]{position:relative}[data-zuude-video-wrapper] [data-zuude-video]{width:100%;height:100%;object-fit:cover}
2
- `);import E from"react";import g from"react";import{jsx as Q}from"react/jsx-runtime";var O=g.createContext(void 0),l=()=>{let e=g.useContext(O);if(!e)throw new Error("useVideo must be used within a VideoProvider");return e},z=({children:e,videoRef:n,duration:r,showHidingElement:t,setShowHidingElement:u})=>{let[s,o]=g.useState(!1);return Q(O.Provider,{value:{videoRef:n,duration:r,isFullscreen:s,setIsFullscreen:o,showHidingElement:t,setShowHidingElement:u},children:e})};import X from"react";var T=(e,n)=>{X.useEffect(()=>{if(!(e!=null&&e.current)||!n)return;let r=e==null?void 0:e.current;r&&n&&(r.currentTime=n)},[n,e==null?void 0:e.current])};import Y from"react";var A=(e,n,r)=>{Y.useEffect(()=>{if(!r||!(e!=null&&e.current))return;let t=new IntersectionObserver(u=>{u.forEach(s=>{var o;e!=null&&e.current&&(s.isIntersecting?e.current.play().catch(a=>{e.current&&(e.current.pause(),e.current.muted=!0,e.current.play(),console.error(a))}):(o=e.current)==null||o.pause())})},{threshold:n!=null?n:.5});return t.observe(e==null?void 0:e.current),()=>{t.disconnect()}},[r,e==null?void 0:e.current])};import L from"react";var V=(e,n)=>{let[r,t]=L.useState(!1),u=L.useCallback(()=>{console.log(e==null?void 0:e.current),e!=null&&e.current&&(e.current.paused?e.current.play():e.current.pause())},[e==null?void 0:e.current]);return L.useEffect(()=>{if(!n||!(e!=null&&e.current))return;let s=()=>{t(!0)},o=()=>{t(!1)};if(t(!(e!=null&&e.current.paused)),e!=null&&e.current)return e.current.addEventListener("play",s),e.current.addEventListener("pause",o),()=>{var a,d;(a=e.current)==null||a.removeEventListener("play",s),(d=e.current)==null||d.removeEventListener("pause",o)}},[e==null?void 0:e.current,n]),{togglePlay:u,isPlaying:r}};import{jsx as Z}from"react/jsx-runtime";var N=()=>{let{videoRef:e}=l(),{togglePlay:n}=V(e,!0);return Z("div",{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",display:"flex",justifyContent:"center",alignItems:"center"},onClick:n})};import te from"react";import F from"react";var M=(e,n)=>{let[r,t]=F.useState(!1),u=F.useCallback(()=>{e!=null&&e.current&&(e.current.muted=!e.current.muted)},[e==null?void 0:e.current]);return F.useEffect(()=>{if(!n||!(e!=null&&e.current))return;t(e.current.muted);let s=()=>{e.current&&t(e.current.muted)};return e.current.addEventListener("volumechange",s),()=>{var o;(o=e.current)==null||o.removeEventListener("volumechange",s)}},[e==null?void 0:e.current,n]),{toggleMute:u,isMuted:r}};import _ from"react";var w=()=>{let{videoRef:e,isFullscreen:n,setIsFullscreen:r}=l();_.useEffect(()=>{let u=()=>{r==null||r(!!document.fullscreenElement)};return document.addEventListener("fullscreenchange",u),()=>document.removeEventListener("fullscreenchange",u)},[]);let t=()=>{var a;let u=/^((?!chrome|android).)*safari/i.test(navigator.userAgent),s=e==null?void 0:e.current;if(s&&u){if(s.webkitEnterFullscreen){s.webkitEnterFullscreen();return}else if(s.requestFullscreen){s.requestFullscreen();return}}let o=(a=e==null?void 0:e.current)==null?void 0:a.closest("[data-zuude-video-wrapper]");o&&(n?document.exitFullscreen():o.requestFullscreen())};return{isFullscreen:n!=null?n:!1,toggleFullscreen:t}};import ee from"react";var q=()=>{let{videoRef:e,isPictureInPicture:n,setIsPictureInPicture:r}=l();ee.useEffect(()=>{let u=()=>{r==null||r(!!document.pictureInPictureElement)};return document.addEventListener("pictureinpicturechange",u),()=>document.removeEventListener("pictureinpicturechange",u)},[]);let t=async()=>{let u=e==null?void 0:e.current;if(u)try{document.pictureInPictureElement?await document.exitPictureInPicture():await u.requestPictureInPicture()}catch(s){if(/^((?!chrome|android).)*safari/i.test(navigator.userAgent))u.webkitEnterFullscreen?u.webkitEnterFullscreen():u.requestFullscreen&&u.requestFullscreen();else{let a=u.closest("[data-zuude-video-wrapper]");a&&(document.fullscreenElement?await document.exitFullscreen():await a.requestFullscreen())}}};return{isPictureInPicture:n!=null?n:!1,togglePictureInPicture:t}};import S from"react";var $=(e,n)=>{let[r,t]=S.useState(1),u=s=>{t(s)};return S.useEffect(()=>{e!=null&&e.current&&t(e.current.playbackRate)},[e==null?void 0:e.current]),S.useEffect(()=>{!n||!(e!=null&&e.current)||(e.current.playbackRate=r)},[r,n,e==null?void 0:e.current]),{speed:r,onChangeSpeed:u}};var B=te.forwardRef(({children:e},n)=>{let{duration:r,showHidingElement:t}=l(),{togglePlay:u,isPlaying:s}=V(n,typeof e=="function"),{speed:o,onChangeSpeed:a}=$(n,typeof e=="function"),{toggleMute:d,isMuted:m}=M(n,typeof e=="function"),{isFullscreen:v,toggleFullscreen:b}=w(),{isPictureInPicture:x,togglePictureInPicture:i}=q();return typeof e!="function"?null:e({isPlaying:s,togglePlay:u,isMuted:m,toggleMute:d,speed:o,onChangeSpeed:a,isFullscreen:v,toggleFullscreen:b,isPictureInPicture:x,togglePictureInPicture:i,duration:r,showHidingElement:t!=null?t:!1})});import re from"react";import{jsx as ne}from"react/jsx-runtime";var D=re.forwardRef(({children:e,className:n,...r})=>{let{videoRef:t}=l(),{isPlaying:u}=V(t,!0),{showHidingElement:s,setShowHidingElement:o}=l();return ne("div",{"data-zuude-hiding-element":!0,"data-show":!u||s,className:n,onMouseEnter:()=>{o==null||o(!0)},onMouseLeave:()=>{o==null||o(!1)},...r,children:e})});import{jsx as I,jsxs as ue}from"react/jsx-runtime";var U=E.forwardRef(({children:e,autoPlay:n,className:r,config:t,ratio:u,controls:s,pause:o,...a},d)=>{let[m,v]=E.useState(null),[b,x]=E.useState(null),i=d||E.useRef(null),[j,h]=E.useState(!1),y=E.useRef(null),G=()=>{var c;(c=i.current)!=null&&c.paused||(h(!0),y.current&&clearTimeout(y.current))},W=()=>{var c;(c=i.current)!=null&&c.paused||(h(!1),y.current&&clearTimeout(y.current))},J=()=>{var c;(c=i.current)!=null&&c.paused||(h(!0),y.current&&clearTimeout(y.current),y.current=setTimeout(()=>{h(!1)},3e3))};return E.useEffect(()=>{var c,p;o!==void 0&&(o?(c=i.current)==null||c.pause():(p=i.current)==null||p.play())},[o,i.current]),C(i,n==="force"&&a.muted===void 0&&!(t!=null&&t.autoplayOnVisible),x),T(i,t==null?void 0:t.startAt),A(i,typeof(t==null?void 0:t.autoplayOnVisible)=="number"?t.autoplayOnVisible:void 0,t==null?void 0:t.autoplayOnVisible),I(z,{videoRef:i,duration:m,showHidingElement:j,setShowHidingElement:h,children:ue("div",{"data-zuude-video-wrapper":!0,className:r,style:{aspectRatio:u},children:[I("video",{"data-zuude-video":!0,ref:i,autoPlay:t!=null&&t.autoplayOnVisible?!1:n==="force"?!0:n,playsInline:!0,onMouseEnter:G,onMouseLeave:W,onMouseMove:J,onClick:()=>{var c,p,P;t!=null&&t.clickToPlay&&((c=i.current)!=null&&c.paused?(p=i.current)==null||p.play():(P=i.current)==null||P.pause())},onLoadedMetadata:c=>{console.log("loaded metadata"),v(c.target.duration)},onTimeUpdate:c=>{var p;if(t!=null&&t.range){let[P,K]=t.range;if(!(i!=null&&i.current))return;((p=i==null?void 0:i.current)==null?void 0:p.currentTime)<P&&(i.current.currentTime=P),i.current.currentTime>K&&(i.current.currentTime=P)}},className:r,style:{aspectRatio:u},...a}),typeof e=="function"?I(B,{ref:i,children:e}):e,b==="NotAllowedError"&&typeof(t==null?void 0:t.muteFallback)=="function"&&t.muteFallback(()=>{i.current&&(i.current.muted=!i.current.muted),x(null)})]})})});U.displayName="Video";var oe=Object.assign(U,{PlayPauseOnVideo:N,HidingElement:D});import H from"react";var se=()=>{let[e,n]=H.useState(100),{videoRef:r}=l(),t=u=>{n(u)};return H.useEffect(()=>{r!=null&&r.current&&n(r.current.volume*100)},[r==null?void 0:r.current]),H.useEffect(()=>{r!=null&&r.current&&(r.current.volume=e/100)},[e,r==null?void 0:r.current]),{volume:e,onChangeVolume:t}};import f from"react";var ie=()=>{let[e,n]=f.useState(!1),[r,t]=f.useState(0),[u,s]=f.useState(0),{videoRef:o,duration:a}=l();return f.useEffect(()=>{if(o!=null&&o.current&&e){let d=setInterval(()=>{var m,v;t(((m=o.current)==null?void 0:m.currentTime)||0),(v=o.current)!=null&&v.buffered.length&&s(o.current.buffered.end(o.current.buffered.length-1))},10);return()=>clearInterval(d)}},[o==null?void 0:o.current,e]),f.useEffect(()=>{if(o!=null&&o.current)return o.current.addEventListener("play",()=>n(!0)),o.current.addEventListener("pause",()=>n(!1)),()=>{var d,m;(d=o.current)==null||d.removeEventListener("play",()=>n(!0)),(m=o.current)==null||m.removeEventListener("pause",()=>n(!1))}},[]),{currentTime:r,duration:a,buffered:u,setCurrentTime:t}};import k from"react";var ae=e=>{let[n,r]=k.useState(!1),[t,u]=k.useState(null);return k.useEffect(()=>{if(e!=null&&e.current)return r(!0),e.current.addEventListener("loadedmetadata",()=>{var s,o;u((o=(s=e.current)==null?void 0:s.duration)!=null?o:null),r(!1)}),e.current.addEventListener("error",()=>{r(!1)}),()=>{var s,o;(s=e.current)==null||s.removeEventListener("loadedmetadata",()=>{}),(o=e.current)==null||o.removeEventListener("error",()=>{})}},[e==null?void 0:e.current]),{duration:t,isLoading:n}};function ce(e,n="mm:ss"){let r=Math.floor(e/60),t=Math.floor(e%60);return n==="h:mm:ss"?`${Math.floor(r/60)}:${r}:${t<10?"0":""}${t}`:`${r}:${t<10?"0":""}${t}`}export{oe as Video,ce as formatTime,C as useAutoplayByForce,w as useFullscreen,ae as useGetDuration,M as useMuteUnmute,V as usePlayPause,T as useStartAt,ie as useTimeline,l as useVideo,se as useVolume};
1
+ "use client";import{a as H,b,c as V,d as C,e as T,f as k,g as w,h as O,j,p as N}from"./chunk-OYLOY3EO.js";import G,{createContext as J,useContext as Q,useEffect as M,useRef as X,useState as S}from"react";import{jsx as D}from"react/jsx-runtime";var z=J(null),Y=G.memo(({children:o,config:n,onError:t,...e})=>{let[s,r]=S({current:null}),[a,L]=S(null),[i,E]=S(!1),f=X(null);return M(()=>{t==null||t(a)},[a]),M(()=>{let l=f.current;if(l){let p=l.querySelectorAll("[data-zuude-hide-elements]"),c=l.querySelector("[data-zuude-video]");if(p){let v=null,x=3e3,h=!1,g=()=>{v&&(clearTimeout(v),v=null),v=setTimeout(()=>{h&&c&&!c.paused&&p.forEach(y=>{y.setAttribute("data-hidden","true")}),v=null},x)},R=()=>{h=!0,p.forEach(y=>{y.removeAttribute("data-hidden")}),g()},F=()=>{h=!1,v&&(clearTimeout(v),v=null),c&&!c.paused&&p.forEach(y=>{y.setAttribute("data-hidden","true")})},A=()=>{h&&(p.forEach(y=>{y.hasAttribute("data-hidden")&&y.removeAttribute("data-hidden")}),g())},I=()=>{h||p.forEach(y=>{y.setAttribute("data-hidden","true")})};return l.addEventListener("mouseenter",R),l.addEventListener("mouseleave",F),l.addEventListener("mousemove",A),c.addEventListener("pause",R),c.addEventListener("play",I),()=>{v&&clearTimeout(v),l.removeEventListener("mouseenter",R),l.removeEventListener("mouseleave",F),l.removeEventListener("mousemove",A),c.removeEventListener("pause",R),c.removeEventListener("play",I)}}}},[]),M(()=>{if(i){let l=p=>{var c;(c=f.current)!=null&&c.contains(p.target)||E(!1)};return document.addEventListener("click",l),()=>{document.removeEventListener("click",l)}}},[i]),D(z.Provider,{value:{videoRef:s,setVideoRef:r,config:{clickToPlay:!0,...n},error:a,setError:L,isFocused:i,setIsFocused:E},children:D("div",{ref:f,"data-zuude-video-wrapper":!0,onClick:()=>E(!0),...e,children:o})})}),d=()=>{let o=Q(z);if(!o)throw new Error("useVideo must be used within a VideoProvider");return o};import{forwardRef as Z,useEffect as _,useRef as $}from"react";var B=()=>{let{videoRef:o}=d(),{seekForward:n,seekBackward:t}=V(o),{togglePlay:e}=C(o),{toggleMute:s}=T(o),{toggleFullscreen:r}=k(o),{togglePictureInPicture:a}=w(o);return b("ArrowRight",()=>{n()}),b("ArrowLeft",()=>{t()}),b(" ",()=>{e()}),b("m",()=>{s()}),b("f",()=>{r()}),b("p",()=>{a()}),null};import{Fragment as ee,jsx as K,jsxs as te}from"react/jsx-runtime";var U=Z(({src:o,autoPlay:n,muteFallback:t,controls:e,preload:s="metadata",autoPlayOnVisible:r,...a},L)=>{let{videoRef:i,setVideoRef:E,config:f,setError:l,error:p,isFocused:c}=d(),v=$(null);_(()=>{let h=v.current,g=L;g?E(g):h&&E({current:h})},[o]),H(i,n==="force"&&a.muted===void 0,l),O(i,typeof r=="number"?r:r?void 0:.5,!!r);let x=()=>{var h,g,R;(h=i==null?void 0:i.current)!=null&&h.paused?(g=i.current)==null||g.play():(R=i==null?void 0:i.current)==null||R.pause()};return te(ee,{children:[K("video",{ref:L||v,"data-zuude-video":!0,src:o,onClick:f!=null&&f.clickToPlay?x:void 0,autoPlay:n==="force"?!0:n,preload:s,...a}),e&&c&&K(B,{}),p==="NotAllowedError"&&typeof t=="function"&&t(()=>{i!=null&&i.current&&(i.current.muted=!i.current.muted),l(null)})]})});U.displayName="Video";import m,{useRef as oe}from"react";import{Slot as P}from"@radix-ui/react-slot";import W from"react";var q=o=>{let[n,t]=W.useState(!1);return W.useEffect(()=>{if(!(o!=null&&o.current))return;let e=o.current,s=()=>{t(!0)},r=()=>{},a=()=>{},L=()=>{t(!1)},i=()=>{t(!1)},E=()=>{t(!0)},f=()=>{t(!1)},l=()=>{t(!1)},p=()=>{t(!1)},c=()=>{};return e.addEventListener("loadstart",s),e.addEventListener("loadedmetadata",r),e.addEventListener("loadeddata",a),e.addEventListener("canplay",L),e.addEventListener("canplaythrough",i),e.addEventListener("waiting",E),e.addEventListener("playing",f),e.addEventListener("error",l),e.addEventListener("abort",p),e.addEventListener("suspend",c),e.readyState>=2&&t(!1),()=>{e.removeEventListener("loadstart",s),e.removeEventListener("loadedmetadata",r),e.removeEventListener("loadeddata",a),e.removeEventListener("canplay",L),e.removeEventListener("canplaythrough",i),e.removeEventListener("waiting",E),e.removeEventListener("playing",f),e.removeEventListener("error",l),e.removeEventListener("abort",p),e.removeEventListener("suspend",c)}},[o]),{isLoading:n}};import{jsx as u}from"react/jsx-runtime";var je=m.memo(({children:o,asChild:n,...t})=>u("div",{"data-zuude-hide-elements":!0,...t,children:o})),Ne=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"button",{videoRef:s}=d(),{play:r}=C(s);return u(e,{...t,onClick:r,children:o})}),De=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"button",{videoRef:s}=d(),{pause:r}=C(s);return u(e,{...t,onClick:r,children:o})}),ze=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"button",{videoRef:s}=d(),{mute:r}=T(s);return u(e,{...t,onClick:r,children:o})}),Be=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"button",{videoRef:s}=d(),{unmute:r}=T(s);return u(e,{...t,onClick:r,children:o})}),Ke=m.memo(({children:o,asChild:n,value:t,onClick:e,...s})=>{let r=n?P:"button",{videoRef:a}=d(),{speed:L,onChangeSpeed:i}=j(a);return u(r,{...s,value:t,onClick:()=>{i(t),e==null||e()},children:o})}),Ue=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"button",{videoRef:s}=d(),{seekForward:r}=V(s,10);return u(e,{...t,onClick:r,children:o})}),We=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"button",{videoRef:s}=d(),{seekBackward:r}=V(s,10);return u(e,{...t,onClick:r,children:o})}),qe=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"button",{videoRef:s}=d(),{toggleFullscreen:r}=k(s);return u(e,{...t,onClick:r,children:o})}),Ge=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"button",{videoRef:s}=d(),{toggleFullscreen:r}=k(s);return u(e,{...t,onClick:r,children:o})}),Je=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"button",{videoRef:s}=d(),{togglePictureInPicture:r}=w(s);return u(e,{...t,onClick:r,children:o})}),Qe=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"button",{videoRef:s}=d(),{downloadDirect:r}=N(s);return u(e,{...t,onClick:()=>r(),children:o})}),Xe=m.memo(({children:o,asChild:n,...t})=>{let e=n?P:"div",{videoRef:s}=d(),{isLoading:r}=q(s);return u(e,{...t,style:{...t.style,pointerEvents:"none"},"data-loading":r,children:o})}),Ye=({...o})=>{let{videoRef:n}=d(),t=oe(null);return m.useEffect(()=>{let e=n==null?void 0:n.current;if(t.current&&e){let s=0,r=!1,a=null,L=()=>{a&&clearInterval(a),a=setInterval(()=>{console.log("currentTime",e.currentTime),s=e.currentTime,t.current&&(t.current.currentTime=s)},100)},i=()=>{a&&(clearInterval(a),a=null)},E=()=>{r=!0,L()},f=()=>{r=!1,i()};return e.addEventListener("play",E),e.addEventListener("pause",f),()=>{i(),e.removeEventListener("play",E),e.removeEventListener("pause",f)}}},[n==null?void 0:n.current]),n!=null&&n.current?u("div",{...o,style:{...o.style,position:"absolute",top:0,left:0,width:"100%",height:"100%",pointerEvents:"none"},children:u("video",{ref:t,src:n.current.src,muted:!0,playsInline:!0,style:{width:"100%",height:"100%",objectFit:"cover"}})}):null};export{je as Controls,Qe as Download,Ge as ExitFullscreen,qe as Fullscreen,Xe as Loading,ze as Mute,De as Pause,Je as PictureInPicture,Ne as Play,We as SeekBackward,Ue as SeekForward,Ye as Shadow,Ke as Speed,Be as Unmute,U as Video,Y as VideoProvider,d as useVideo};
3
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["#style-inject:#style-inject","../src/styles.css","../src/video.tsx","../src/context.tsx","../src/hooks/use-start-at.tsx","../src/hooks/use-autoplay-on-visible.tsx","../src/hooks/use-play-pause.tsx","../src/components/play-pause-on-video.tsx","../src/function-children.tsx","../src/hooks/use-mute-unmute.tsx","../src/hooks/use-fullscreen.tsx","../src/hooks/use-picture-in-picture.tsx","../src/hooks/use-speed.tsx","../src/components/hiding-element.tsx","../src/hooks/use-volume.tsx","../src/hooks/use-timeline.tsx","../src/hooks/use-get-duration.tsx","../src/utils.ts"],"sourcesContent":["\n export default function styleInject(css, { insertAt } = {}) {\n if (!css || typeof document === 'undefined') return\n \n const head = document.head || document.getElementsByTagName('head')[0]\n const style = document.createElement('style')\n style.type = 'text/css'\n \n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild)\n } else {\n head.appendChild(style)\n }\n } else {\n head.appendChild(style)\n }\n \n if (style.styleSheet) {\n style.styleSheet.cssText = css\n } else {\n style.appendChild(document.createTextNode(css))\n }\n }\n ","import styleInject from '#style-inject';styleInject(\".reset-styles{box-sizing:border-box;padding:0;margin:0}[data-zuude-video-wrapper]{position:relative}[data-zuude-video-wrapper] [data-zuude-video]{width:100%;height:100%;object-fit:cover}\\n\")","import React from \"react\";\n\n// 📦 Types\nimport type { VideoProps, VideoRef } from \"./types\";\n\n// 🔍 Context\nimport { VideoProvider } from \"./context\";\n\n// 🔗 Hooks\nimport { useAutoplayByForce } from \"./hooks/use-autoplay-by-force\";\nimport { useStartAt } from \"./hooks/use-start-at\";\nimport { useAutoplayOnVisible } from \"./hooks/use-autoplay-on-visible\";\n\n// 🔧 Components\nimport { PlayPauseOnVideo } from \"./components/play-pause-on-video\";\nimport { FunctionChildren } from \"./function-children\";\nimport { HidingElement, HidingElementProps } from \"./components/hiding-element\";\n\n/**\n * Main Video component structure\n * @param {VideoProps} props - Video component props\n */\n\nconst VideoComponent = React.forwardRef<\n HTMLVideoElement,\n VideoProps & { pause?: boolean }\n>(\n (\n { children, autoPlay, className, config, ratio, controls, pause, ...props },\n ref\n ) => {\n const [duration, setDuration] = React.useState<number | null>(null);\n const [error, setError] = React.useState<string | null>(null);\n\n const videoRef = (ref as VideoRef) || React.useRef<VideoRef>(null);\n\n const [showHidingElement, setShowHidingElement] = React.useState(false);\n const timeoutRef = React.useRef<ReturnType<typeof setTimeout>>(null);\n const handleMouseEnter = () => {\n if (videoRef.current?.paused) return;\n\n setShowHidingElement(true);\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n const handleMouseLeave = () => {\n if (videoRef.current?.paused) return;\n\n setShowHidingElement(false);\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n };\n const handleMouseMove = () => {\n if (videoRef.current?.paused) return;\n\n setShowHidingElement(true);\n if (timeoutRef.current) {\n clearTimeout(timeoutRef.current);\n }\n timeoutRef.current = setTimeout(() => {\n setShowHidingElement(false);\n }, 3000);\n };\n\n React.useEffect(() => {\n if (pause !== undefined) {\n if (pause) {\n videoRef.current?.pause();\n } else {\n videoRef.current?.play();\n }\n }\n }, [pause, videoRef.current]);\n\n useAutoplayByForce(\n videoRef,\n autoPlay === \"force\" &&\n props.muted === undefined &&\n !config?.autoplayOnVisible,\n setError\n );\n useStartAt(videoRef, config?.startAt);\n useAutoplayOnVisible(\n videoRef,\n typeof config?.autoplayOnVisible === \"number\"\n ? config.autoplayOnVisible\n : undefined,\n config?.autoplayOnVisible\n );\n\n return (\n <VideoProvider\n videoRef={videoRef}\n duration={duration}\n showHidingElement={showHidingElement}\n setShowHidingElement={setShowHidingElement}\n >\n <div\n data-zuude-video-wrapper\n className={className}\n style={{ aspectRatio: ratio }}\n >\n <video\n data-zuude-video\n // @ts-ignore\n ref={videoRef}\n autoPlay={\n config?.autoplayOnVisible\n ? false\n : autoPlay === \"force\"\n ? true\n : autoPlay\n }\n playsInline\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onMouseMove={handleMouseMove}\n onClick={() => {\n if (config?.clickToPlay) {\n if (videoRef.current?.paused) {\n videoRef.current?.play();\n } else {\n videoRef.current?.pause();\n }\n }\n }}\n onLoadedMetadata={(e) => {\n console.log(\"loaded metadata\");\n setDuration((e.target as HTMLVideoElement).duration);\n }}\n onTimeUpdate={(e) => {\n /**\n * If the current time is less than the start time, set the current time to the start time\n * If the current time is greater than the end time, set the current time to the start time\n */\n if (config?.range) {\n const [start, end] = config.range;\n\n if (!videoRef?.current) return;\n\n if (videoRef?.current?.currentTime < start) {\n videoRef.current.currentTime = start;\n }\n\n if (videoRef.current.currentTime > end) {\n videoRef.current.currentTime = start;\n }\n }\n }}\n className={className}\n style={{ aspectRatio: ratio }}\n {...props}\n />\n {typeof children === \"function\" ? (\n <FunctionChildren ref={videoRef} children={children} />\n ) : (\n children\n )}\n {error === \"NotAllowedError\" &&\n typeof config?.muteFallback === \"function\" &&\n config.muteFallback(() => {\n if (videoRef.current) {\n videoRef.current.muted = !videoRef.current.muted;\n }\n setError(null);\n })}\n </div>\n </VideoProvider>\n );\n }\n);\n\nVideoComponent.displayName = \"Video\";\n\n/**\n * Using compound components pattern\n */\nexport const Video = Object.assign(VideoComponent, {\n PlayPauseOnVideo,\n HidingElement: HidingElement as React.ComponentType<HidingElementProps>,\n});\n","import React from \"react\";\nimport type { VideoContextType } from \"./types.js\";\n\nconst VideoContext = React.createContext<VideoContextType | undefined>(\n undefined\n);\n\nconst useVideo = () => {\n const context = React.useContext(VideoContext);\n if (!context) {\n throw new Error(\"useVideo must be used within a VideoProvider\");\n }\n return context;\n};\n\ninterface VideoProviderProps extends VideoContextType {\n children: React.ReactNode;\n}\n\nconst VideoProvider = ({\n children,\n videoRef,\n duration,\n showHidingElement,\n setShowHidingElement,\n}: VideoProviderProps) => {\n const [fullscreen, setFullscreen] = React.useState(false);\n\n return (\n <VideoContext.Provider\n value={{\n videoRef,\n duration,\n isFullscreen: fullscreen,\n setIsFullscreen: setFullscreen,\n showHidingElement,\n setShowHidingElement,\n }}\n >\n {children}\n </VideoContext.Provider>\n );\n};\n\nexport { useVideo, VideoProvider };\n","import React from \"react\";\nimport type { VideoConfig, VideoRef } from \"../types\";\n\nexport const useStartAt = (ref: VideoRef, startAt?: VideoConfig[\"startAt\"]) => {\n React.useEffect(() => {\n if (!ref?.current || !startAt) return;\n\n const video = ref?.current;\n if (video && startAt) {\n video.currentTime = startAt;\n }\n }, [startAt, ref?.current]);\n};\n","import React from \"react\";\nimport type { VideoRef } from \"../types\";\n\nexport const useAutoplayOnVisible = (\n ref: VideoRef,\n threshold: number | undefined,\n enabled: boolean | number | null | undefined\n) => {\n React.useEffect(() => {\n if (!enabled || !ref?.current) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n entries.forEach((entry) => {\n if (!ref?.current) return;\n\n if (entry.isIntersecting) {\n ref.current.play().catch((error) => {\n if (!ref.current) return;\n\n ref.current.pause();\n ref.current.muted = true;\n ref.current.play();\n console.error(error);\n });\n } else {\n ref.current?.pause();\n }\n });\n },\n { threshold: threshold ?? 0.5 }\n );\n\n observer.observe(ref?.current);\n\n return () => {\n observer.disconnect();\n };\n }, [enabled, ref?.current]);\n};\n","import React from \"react\";\nimport type { VideoRef } from \"../types\";\n\nexport const usePlayPause = (ref: VideoRef, enabled: boolean) => {\n const [isPlaying, setIsPlaying] = React.useState(false);\n\n const togglePlay = React.useCallback(() => {\n console.log(ref?.current);\n if (ref?.current) {\n ref.current.paused ? ref.current.play() : ref.current.pause();\n }\n }, [ref?.current]);\n\n React.useEffect(() => {\n if (!enabled || !ref?.current) return;\n\n const handlePlay = () => {\n setIsPlaying(true);\n };\n const handlePause = () => {\n setIsPlaying(false);\n };\n\n setIsPlaying(!ref?.current.paused);\n\n if (ref?.current) {\n ref.current.addEventListener(\"play\", handlePlay);\n ref.current.addEventListener(\"pause\", handlePause);\n\n return () => {\n ref.current?.removeEventListener(\"play\", handlePlay);\n ref.current?.removeEventListener(\"pause\", handlePause);\n };\n }\n }, [ref?.current, enabled]);\n\n return { togglePlay, isPlaying };\n};\n","import { useVideo } from \"../context\";\nimport { usePlayPause } from \"../hooks/use-play-pause\";\n\nexport const PlayPauseOnVideo = () => {\n const { videoRef } = useVideo();\n\n const { togglePlay } = usePlayPause(videoRef, true);\n\n return (\n <div\n style={{\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n display: \"flex\",\n justifyContent: \"center\",\n alignItems: \"center\",\n }}\n onClick={togglePlay}\n ></div>\n );\n};\n","import React from \"react\";\n\nimport type { VideoChildren, VideoRef } from \"./types\";\nimport { usePlayPause } from \"./hooks/use-play-pause\";\nimport { useMuteUnmute } from \"./hooks/use-mute-unmute\";\nimport { useVideo } from \"./context\";\nimport { useFullscreen } from \"./hooks/use-fullscreen\";\nimport { usePictureInPicture } from \"./hooks/use-picture-in-picture\";\nimport { useSpeed } from \"./hooks/use-speed\";\n\nexport const FunctionChildren = React.forwardRef<\n any,\n {\n children: VideoChildren;\n }\n>(({ children }, ref) => {\n const { duration, showHidingElement } = useVideo();\n\n /**\n * Only use these hooks if the children is a function\n */\n const { togglePlay, isPlaying } = usePlayPause(\n ref as VideoRef,\n typeof children === \"function\"\n );\n const { speed, onChangeSpeed } = useSpeed(\n ref as VideoRef,\n typeof children === \"function\"\n );\n const { toggleMute, isMuted } = useMuteUnmute(\n ref as VideoRef,\n typeof children === \"function\"\n );\n const { isFullscreen, toggleFullscreen } = useFullscreen();\n const { isPictureInPicture, togglePictureInPicture } = usePictureInPicture();\n\n if (typeof children !== \"function\") return null;\n\n return children({\n isPlaying,\n togglePlay,\n isMuted,\n toggleMute,\n speed,\n onChangeSpeed,\n isFullscreen,\n toggleFullscreen,\n isPictureInPicture,\n togglePictureInPicture,\n duration,\n showHidingElement: showHidingElement ?? false,\n });\n});\n","import React from \"react\";\nimport type { VideoRef } from \"../types\";\n\nexport const useMuteUnmute = (ref: VideoRef, enabled: boolean) => {\n const [isMuted, setIsMuted] = React.useState(false);\n\n const toggleMute = React.useCallback(() => {\n if (ref?.current) {\n ref.current.muted = !ref.current.muted;\n }\n }, [ref?.current]);\n\n React.useEffect(() => {\n if (!enabled || !ref?.current) return;\n\n // Set the initial state\n setIsMuted(ref.current.muted);\n\n const handleVolumeChange = () => {\n if (ref.current) {\n setIsMuted(ref.current.muted);\n }\n };\n\n ref.current.addEventListener(\"volumechange\", handleVolumeChange);\n\n return () => {\n ref.current?.removeEventListener(\"volumechange\", handleVolumeChange);\n };\n }, [ref?.current, enabled]);\n\n return { toggleMute, isMuted };\n};\n","import React from \"react\";\nimport { useVideo } from \"../context\";\n\nexport const useFullscreen = () => {\n const { videoRef, isFullscreen, setIsFullscreen } = useVideo();\n\n React.useEffect(() => {\n const handleFullscreenChange = () => {\n setIsFullscreen?.(!!document.fullscreenElement);\n };\n\n document.addEventListener(\"fullscreenchange\", handleFullscreenChange);\n return () =>\n document.removeEventListener(\"fullscreenchange\", handleFullscreenChange);\n }, []);\n\n const toggleFullscreen = () => {\n const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);\n const video = videoRef?.current;\n\n if (video && isSafari) {\n if ((video as any).webkitEnterFullscreen) {\n (video as any).webkitEnterFullscreen();\n return;\n } else if (video.requestFullscreen) {\n video.requestFullscreen();\n return;\n }\n }\n\n const videoContainer = videoRef?.current?.closest(\n \"[data-zuude-video-wrapper]\"\n ) as HTMLElement;\n\n if (videoContainer) {\n if (!isFullscreen) {\n videoContainer.requestFullscreen();\n } else {\n document.exitFullscreen();\n }\n }\n };\n\n return { isFullscreen: isFullscreen ?? false, toggleFullscreen };\n};\n","import React from \"react\";\nimport { useVideo } from \"../context\";\n\nexport const usePictureInPicture = () => {\n const { videoRef, isPictureInPicture, setIsPictureInPicture } = useVideo();\n\n React.useEffect(() => {\n const handlePictureInPictureChange = () => {\n setIsPictureInPicture?.(!!document.pictureInPictureElement);\n };\n\n document.addEventListener(\n \"pictureinpicturechange\",\n handlePictureInPictureChange\n );\n return () =>\n document.removeEventListener(\n \"pictureinpicturechange\",\n handlePictureInPictureChange\n );\n }, []);\n\n const togglePictureInPicture = async () => {\n const video = videoRef?.current;\n if (!video) return;\n\n try {\n if (document.pictureInPictureElement) {\n await document.exitPictureInPicture();\n } else {\n await video.requestPictureInPicture();\n }\n } catch (error) {\n // Fallback for browsers that don't support PiP\n const isSafari = /^((?!chrome|android).)*safari/i.test(\n navigator.userAgent\n );\n\n if (isSafari) {\n if ((video as any).webkitEnterFullscreen) {\n (video as any).webkitEnterFullscreen();\n } else if (video.requestFullscreen) {\n video.requestFullscreen();\n }\n } else {\n const videoContainer = video.closest(\n \"[data-zuude-video-wrapper]\"\n ) as HTMLElement;\n if (videoContainer) {\n if (!document.fullscreenElement) {\n await videoContainer.requestFullscreen();\n } else {\n await document.exitFullscreen();\n }\n }\n }\n }\n };\n\n return {\n isPictureInPicture: isPictureInPicture ?? false,\n togglePictureInPicture,\n };\n};\n","import React from \"react\";\nimport type { VideoRef } from \"../types\";\n\nexport const useSpeed = (ref: VideoRef, enabled: boolean) => {\n const [speed, setSpeed] = React.useState(1);\n\n const onChangeSpeed = (speed: number) => {\n setSpeed(speed);\n };\n\n // Get the speed from the video element\n React.useEffect(() => {\n if (!ref?.current) return;\n setSpeed(ref.current.playbackRate);\n }, [ref?.current]);\n\n React.useEffect(() => {\n if (!enabled || !ref?.current) return;\n\n ref.current.playbackRate = speed;\n }, [speed, enabled, ref?.current]);\n\n return { speed, onChangeSpeed };\n};\n","import React from \"react\";\nimport { useVideo } from \"../context\";\nimport { usePlayPause } from \"../hooks/use-play-pause\";\n\nexport interface HidingElementProps\n extends React.ComponentPropsWithoutRef<\"div\"> {\n children: React.ReactNode;\n className?: string;\n}\n\nexport const HidingElement = React.forwardRef<\n HTMLDivElement,\n HidingElementProps\n>(({ children, className, ...props }: HidingElementProps) => {\n const { videoRef } = useVideo();\n const { isPlaying } = usePlayPause(videoRef, true);\n const { showHidingElement, setShowHidingElement } = useVideo();\n\n return (\n <div\n data-zuude-hiding-element\n data-show={!isPlaying || showHidingElement}\n className={className}\n onMouseEnter={() => {\n setShowHidingElement?.(true);\n }}\n onMouseLeave={() => {\n setShowHidingElement?.(false);\n }}\n {...props}\n >\n {children}\n </div>\n );\n});\n","import React from \"react\";\nimport { useVideo } from \"../context\";\n\nexport const useVolume = () => {\n const [volume, setVolume] = React.useState(100);\n const { videoRef } = useVideo();\n\n const onChangeVolume = (volume: number) => {\n setVolume(volume);\n };\n\n // Get the volume from the video element\n React.useEffect(() => {\n if (!videoRef?.current) return;\n setVolume(videoRef.current.volume * 100);\n }, [videoRef?.current]);\n\n React.useEffect(() => {\n if (!videoRef?.current) return;\n\n videoRef.current.volume = volume / 100;\n }, [volume, videoRef?.current]);\n\n return { volume, onChangeVolume };\n};\n","import React from \"react\";\nimport { useVideo } from \"../context\";\n\nexport const useTimeline = () => {\n const [isPlaying, setIsPlaying] = React.useState(false);\n const [currentTime, setCurrentTime] = React.useState(0);\n const [buffered, setBuffered] = React.useState(0);\n\n const { videoRef, duration } = useVideo();\n\n React.useEffect(() => {\n if (videoRef?.current && isPlaying) {\n const intervalId = setInterval(() => {\n setCurrentTime(videoRef.current?.currentTime || 0);\n\n if (videoRef.current?.buffered.length) {\n setBuffered(\n videoRef.current.buffered.end(videoRef.current.buffered.length - 1)\n );\n }\n }, 10);\n\n return () => clearInterval(intervalId);\n }\n }, [videoRef?.current, isPlaying]);\n\n React.useEffect(() => {\n if (!videoRef?.current) return;\n\n videoRef.current.addEventListener(\"play\", () => setIsPlaying(true));\n videoRef.current.addEventListener(\"pause\", () => setIsPlaying(false));\n\n return () => {\n videoRef.current?.removeEventListener(\"play\", () => setIsPlaying(true));\n videoRef.current?.removeEventListener(\"pause\", () => setIsPlaying(false));\n };\n }, []);\n\n return {\n currentTime,\n duration,\n buffered,\n setCurrentTime,\n };\n};\n","import React from \"react\";\nimport { VideoRef } from \"../types.js\";\n\nexport const useGetDuration = (ref: VideoRef) => {\n const [isLoading, setIsLoading] = React.useState(false);\n const [duration, setDuration] = React.useState<number | null>(null);\n\n React.useEffect(() => {\n if (!ref?.current) return;\n setIsLoading(true);\n\n ref.current.addEventListener(\"loadedmetadata\", () => {\n setDuration(ref.current?.duration ?? null);\n setIsLoading(false);\n });\n\n ref.current.addEventListener(\"error\", () => {\n setIsLoading(false);\n });\n\n return () => {\n ref.current?.removeEventListener(\"loadedmetadata\", () => {});\n ref.current?.removeEventListener(\"error\", () => {});\n };\n }, [ref?.current]);\n\n return { duration, isLoading };\n};\n","function formatTime(time: number, type: \"h:mm:ss\" | \"mm:ss\" = \"mm:ss\"): string {\n const minutes = Math.floor(time / 60);\n const seconds = Math.floor(time % 60);\n if (type === \"h:mm:ss\") {\n const hours = Math.floor(minutes / 60);\n return `${hours}:${minutes}:${seconds < 10 ? \"0\" : \"\"}${seconds}`;\n }\n return `${minutes}:${seconds < 10 ? \"0\" : \"\"}${seconds}`;\n}\n\nexport { formatTime };\n"],"mappings":"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","names":["styleInject","css","insertAt","head","style","styleInject","React","React","jsx","VideoContext","useVideo","context","VideoProvider","children","videoRef","duration","showHidingElement","setShowHidingElement","fullscreen","setFullscreen","React","useStartAt","ref","startAt","video","React","useAutoplayOnVisible","ref","threshold","enabled","observer","entries","entry","_a","error","React","usePlayPause","ref","enabled","isPlaying","setIsPlaying","togglePlay","handlePlay","handlePause","_a","_b","jsx","PlayPauseOnVideo","videoRef","useVideo","togglePlay","usePlayPause","React","React","useMuteUnmute","ref","enabled","isMuted","setIsMuted","toggleMute","handleVolumeChange","_a","React","useFullscreen","videoRef","isFullscreen","setIsFullscreen","useVideo","React","handleFullscreenChange","toggleFullscreen","_a","isSafari","video","videoContainer","React","usePictureInPicture","videoRef","isPictureInPicture","setIsPictureInPicture","useVideo","React","handlePictureInPictureChange","togglePictureInPicture","video","error","videoContainer","React","useSpeed","ref","enabled","speed","setSpeed","onChangeSpeed","FunctionChildren","React","children","ref","duration","showHidingElement","useVideo","togglePlay","isPlaying","usePlayPause","speed","onChangeSpeed","useSpeed","toggleMute","isMuted","useMuteUnmute","isFullscreen","toggleFullscreen","useFullscreen","isPictureInPicture","togglePictureInPicture","usePictureInPicture","React","jsx","HidingElement","React","children","className","props","videoRef","useVideo","isPlaying","usePlayPause","showHidingElement","setShowHidingElement","jsx","jsxs","VideoComponent","React","children","autoPlay","className","config","ratio","controls","pause","props","ref","duration","setDuration","error","setError","videoRef","showHidingElement","setShowHidingElement","timeoutRef","handleMouseEnter","_a","handleMouseLeave","handleMouseMove","_b","useAutoplayByForce","useStartAt","useAutoplayOnVisible","VideoProvider","_c","e","start","end","FunctionChildren","Video","PlayPauseOnVideo","HidingElement","React","useVolume","volume","setVolume","React","videoRef","useVideo","onChangeVolume","React","useTimeline","isPlaying","setIsPlaying","React","currentTime","setCurrentTime","buffered","setBuffered","videoRef","duration","useVideo","intervalId","_a","_b","React","useGetDuration","ref","isLoading","setIsLoading","duration","setDuration","_a","_b","formatTime","time","type","minutes","seconds"]}
1
+ {"version":3,"sources":["../src/wrapper.tsx","../src/video.tsx","../src/keyboard.tsx","../src/components.tsx","../src/hooks/use-loading.tsx"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport type { VideoRef } from \"./types\";\n\ninterface VideoConfig {\n config?: Partial<{\n clickToPlay: boolean;\n }>;\n}\n\ninterface VideoContextType extends VideoConfig {\n videoRef: VideoRef;\n setVideoRef: (video: VideoRef) => void;\n error: string | null;\n setError: (error: string | null) => void;\n isFocused: boolean;\n setIsFocused: (isFocused: boolean) => void;\n}\n\nexport const VideoContext = createContext<VideoContextType | null>(null);\n\ntype VideoProviderProps = Omit<React.ComponentProps<\"div\">, \"onError\"> &\n VideoConfig & {\n children: React.ReactNode;\n onError?: (error: string | null) => void;\n };\n\nexport const VideoProvider = React.memo(\n ({ children, config, onError, ...props }: VideoProviderProps) => {\n const [videoRef, setVideoRef] = useState<VideoRef>({ current: null });\n const [error, setError] = useState<string | null>(null);\n const [isFocused, setIsFocused] = useState(false);\n\n const videoWrapperRef = useRef<HTMLDivElement>(null);\n\n // Sending error to user if it exists\n useEffect(() => {\n onError?.(error);\n }, [error]);\n\n useEffect(() => {\n const videoWrapper = videoWrapperRef.current;\n if (videoWrapper) {\n const controls = videoWrapper.querySelectorAll(\n \"[data-zuude-hide-elements]\"\n );\n const video = videoWrapper.querySelector(\n \"[data-zuude-video]\"\n ) as HTMLVideoElement;\n\n if (controls) {\n let hideTimeout: ReturnType<typeof setTimeout> | null = null;\n const hideDelay = 3000; // 3 seconds delay\n let isMouseOver = false;\n\n const resetTimer = () => {\n // Clear any pending hide timeout\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n\n // Start new timer to hide controls after delay\n hideTimeout = setTimeout(() => {\n if (isMouseOver) {\n // Check if video is paused - don't hide controls if paused\n if (video && !video.paused) {\n controls.forEach((control) => {\n control.setAttribute(\"data-hidden\", \"true\");\n });\n }\n }\n hideTimeout = null;\n }, hideDelay);\n };\n\n const showControls = () => {\n isMouseOver = true;\n controls.forEach((control) => {\n control.removeAttribute(\"data-hidden\");\n });\n resetTimer();\n };\n\n const hideControls = () => {\n isMouseOver = false;\n // Clear any pending hide timeout\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n hideTimeout = null;\n }\n // Hide controls immediately when mouse leaves\n if (video && !video.paused) {\n controls.forEach((control) => {\n control.setAttribute(\"data-hidden\", \"true\");\n });\n }\n };\n\n const handleMouseMove = () => {\n if (isMouseOver) {\n // If controls are hidden, show them\n controls.forEach((control) => {\n if (control.hasAttribute(\"data-hidden\")) {\n control.removeAttribute(\"data-hidden\");\n }\n });\n resetTimer();\n }\n };\n\n const handlePlay = () => {\n // Hide controls when video starts playing (autoplay)\n if (!isMouseOver) {\n controls.forEach((control) => {\n control.setAttribute(\"data-hidden\", \"true\");\n });\n }\n };\n\n videoWrapper.addEventListener(\"mouseenter\", showControls);\n videoWrapper.addEventListener(\"mouseleave\", hideControls);\n videoWrapper.addEventListener(\"mousemove\", handleMouseMove);\n video.addEventListener(\"pause\", showControls);\n video.addEventListener(\"play\", handlePlay);\n\n // Cleanup function\n return () => {\n if (hideTimeout) {\n clearTimeout(hideTimeout);\n }\n videoWrapper.removeEventListener(\"mouseenter\", showControls);\n videoWrapper.removeEventListener(\"mouseleave\", hideControls);\n videoWrapper.removeEventListener(\"mousemove\", handleMouseMove);\n video.removeEventListener(\"pause\", showControls);\n video.removeEventListener(\"play\", handlePlay);\n };\n }\n }\n }, []);\n\n useEffect(() => {\n if (isFocused) {\n const handleClick = (event: MouseEvent) => {\n if (!videoWrapperRef.current?.contains(event.target as Node)) {\n setIsFocused(false);\n }\n };\n document.addEventListener(\"click\", handleClick);\n\n return () => {\n document.removeEventListener(\"click\", handleClick);\n };\n }\n }, [isFocused]);\n\n return (\n <VideoContext.Provider\n value={{\n videoRef,\n setVideoRef,\n config: { clickToPlay: true, ...config },\n error,\n setError,\n isFocused,\n setIsFocused,\n }}\n >\n <div\n ref={videoWrapperRef}\n data-zuude-video-wrapper\n onClick={() => setIsFocused(true)}\n {...props}\n >\n {children}\n </div>\n </VideoContext.Provider>\n );\n }\n);\n\nexport const useVideo = () => {\n const context = useContext(VideoContext);\n if (!context) {\n throw new Error(\"useVideo must be used within a VideoProvider\");\n }\n return context;\n};\n","import React, { forwardRef, RefObject, useEffect, useRef } from \"react\";\nimport { useVideo } from \"./wrapper\";\nimport { VideoAutoplay } from \"./types\";\nimport { useAutoplayByForce } from \"./hooks/use-autoplay-by-force\";\nimport { Keyboards } from \"./keyboard\";\nimport { useAutoplayOnVisible } from \"./hooks\";\n\ninterface Props\n extends Omit<React.ComponentProps<\"video\">, \"autoPlay\" | \"preload\"> {\n src: string;\n autoPlay?: VideoAutoplay;\n controls?: boolean;\n preload?: \"none\" | \"metadata\" | \"auto\";\n muteFallback?: (onMute: () => void) => React.ReactNode;\n autoPlayOnVisible?: boolean | number;\n}\n\nexport const Video = forwardRef<HTMLVideoElement, Props>(\n (\n {\n src,\n autoPlay,\n muteFallback,\n controls,\n preload = \"metadata\",\n autoPlayOnVisible,\n ...props\n },\n ref\n ) => {\n const { videoRef, setVideoRef, config, setError, error, isFocused } =\n useVideo();\n\n const refVideo = useRef<HTMLVideoElement>(null);\n\n useEffect(() => {\n const video = refVideo.current;\n const thirdPartyRef = ref;\n\n if (thirdPartyRef) {\n setVideoRef(thirdPartyRef as RefObject<HTMLVideoElement>);\n } else {\n if (video) {\n setVideoRef({ current: video });\n }\n }\n }, [src]);\n\n useAutoplayByForce(\n videoRef,\n autoPlay === \"force\" && props.muted === undefined,\n setError\n );\n\n useAutoplayOnVisible(\n videoRef,\n typeof autoPlayOnVisible === \"number\"\n ? autoPlayOnVisible\n : !autoPlayOnVisible\n ? 0.5\n : undefined,\n !!autoPlayOnVisible\n );\n\n const onPlay = () => {\n if (videoRef?.current?.paused) {\n videoRef.current?.play();\n } else {\n videoRef?.current?.pause();\n }\n };\n\n return (\n <>\n <video\n ref={ref || refVideo}\n data-zuude-video\n src={src}\n onClick={config?.clickToPlay ? onPlay : undefined}\n autoPlay={autoPlay === \"force\" ? true : autoPlay}\n preload={preload}\n {...props}\n />\n\n {controls && isFocused && <Keyboards />}\n\n {error === \"NotAllowedError\" &&\n typeof muteFallback === \"function\" &&\n muteFallback(() => {\n if (videoRef?.current) {\n videoRef.current.muted = !videoRef.current.muted;\n }\n setError(null);\n })}\n </>\n );\n }\n);\n\nVideo.displayName = \"Video\";\n","import { useVideo } from \"./wrapper\";\nimport { useHotKeys } from \"./hooks/use-hot-keys\";\nimport { useSeek } from \"./hooks/use-seek\";\nimport { usePlayPause } from \"./hooks/use-play-pause\";\nimport { useMuteUnmute } from \"./hooks/use-mute-unmute\";\nimport { useFullscreen } from \"./hooks/use-fullscreen\";\nimport { usePictureInPicture } from \"./hooks/use-picture-in-picture\";\n\nexport const Keyboards = () => {\n const { videoRef } = useVideo();\n\n const { seekForward, seekBackward } = useSeek(videoRef);\n const { togglePlay } = usePlayPause(videoRef);\n const { toggleMute } = useMuteUnmute(videoRef);\n const { toggleFullscreen } = useFullscreen(videoRef);\n const { togglePictureInPicture } = usePictureInPicture(videoRef);\n\n useHotKeys(\"ArrowRight\", () => {\n seekForward();\n });\n useHotKeys(\"ArrowLeft\", () => {\n seekBackward();\n });\n useHotKeys(\" \", () => {\n togglePlay();\n });\n useHotKeys(\"m\", () => {\n toggleMute();\n });\n useHotKeys(\"f\", () => {\n toggleFullscreen();\n });\n useHotKeys(\"p\", () => {\n togglePictureInPicture();\n });\n\n return null;\n};\n","import React, { RefObject, useRef } from \"react\";\n\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { useVideo } from \"./wrapper\";\nimport { useFullscreen } from \"./hooks/use-fullscreen\";\nimport { useSeek } from \"./hooks/use-seek\";\nimport { useMuteUnmute } from \"./hooks/use-mute-unmute\";\nimport { usePlayPause } from \"./hooks/use-play-pause\";\nimport { useCurrentTime } from \"./hooks/use-current-time\";\nimport { usePictureInPicture } from \"./hooks/use-picture-in-picture\";\nimport { useDownload } from \"./hooks/use-download\";\nimport { useSpeed } from \"./hooks\";\nimport { useLoading } from \"./hooks/use-loading\";\n\ninterface ControlsProps extends React.ComponentProps<\"div\"> {\n children: React.ReactNode;\n asChild?: boolean;\n}\n\nconst Controls = React.memo(\n ({ children, asChild, ...props }: ControlsProps) => {\n return (\n <div data-zuude-hide-elements {...props}>\n {children}\n </div>\n );\n }\n);\n\ninterface Props extends React.ComponentProps<\"button\"> {\n children: React.ReactNode;\n asChild?: boolean;\n}\n\nconst Play = React.memo(({ children, asChild, ...props }: Props) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { play } = usePlayPause(videoRef as RefObject<HTMLVideoElement>);\n\n return (\n <Element {...props} onClick={play}>\n {children}\n </Element>\n );\n});\n\nconst Pause = React.memo(({ children, asChild, ...props }: Props) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { pause } = usePlayPause(videoRef as RefObject<HTMLVideoElement>);\n\n return (\n <Element {...props} onClick={pause}>\n {children}\n </Element>\n );\n});\n\nconst Mute = React.memo(({ children, asChild, ...props }: Props) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { mute } = useMuteUnmute(videoRef as RefObject<HTMLVideoElement>);\n\n return (\n <Element {...props} onClick={mute}>\n {children}\n </Element>\n );\n});\n\nconst Unmute = React.memo(({ children, asChild, ...props }: Props) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { unmute } = useMuteUnmute(videoRef as RefObject<HTMLVideoElement>);\n\n return (\n <Element {...props} onClick={unmute}>\n {children}\n </Element>\n );\n});\n\ninterface SpeedProps extends Props {\n value: number;\n onClick?: () => void;\n}\n\nconst Speed = React.memo(\n ({ children, asChild, value, onClick, ...props }: SpeedProps) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { speed, onChangeSpeed } = useSpeed(\n videoRef as RefObject<HTMLVideoElement>\n );\n\n return (\n <Element\n {...props}\n value={value}\n onClick={() => {\n onChangeSpeed(value);\n onClick?.();\n }}\n >\n {children}\n </Element>\n );\n }\n);\n\nconst SeekForward = React.memo(({ children, asChild, ...props }: Props) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { seekForward } = useSeek(videoRef as RefObject<HTMLVideoElement>, 10);\n\n return (\n <Element {...props} onClick={seekForward}>\n {children}\n </Element>\n );\n});\n\nconst SeekBackward = React.memo(({ children, asChild, ...props }: Props) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { seekBackward } = useSeek(videoRef as RefObject<HTMLVideoElement>, 10);\n\n return (\n <Element {...props} onClick={seekBackward}>\n {children}\n </Element>\n );\n});\n\nconst Fullscreen = React.memo(({ children, asChild, ...props }: Props) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { toggleFullscreen } = useFullscreen(videoRef);\n\n return (\n <Element {...props} onClick={toggleFullscreen}>\n {children}\n </Element>\n );\n});\n\nconst ExitFullscreen = React.memo(({ children, asChild, ...props }: Props) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { toggleFullscreen } = useFullscreen(videoRef);\n\n return (\n <Element {...props} onClick={toggleFullscreen}>\n {children}\n </Element>\n );\n});\n\nconst PictureInPicture = React.memo(\n ({ children, asChild, ...props }: Props) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { togglePictureInPicture } = usePictureInPicture(videoRef);\n\n return (\n <Element {...props} onClick={togglePictureInPicture}>\n {children}\n </Element>\n );\n }\n);\n\nconst Download = React.memo(({ children, asChild, ...props }: Props) => {\n const Element = asChild ? Slot : \"button\";\n const { videoRef } = useVideo();\n\n const { downloadDirect } = useDownload(videoRef);\n\n return (\n <Element {...props} onClick={() => downloadDirect()}>\n {children}\n </Element>\n );\n});\n\ninterface LoadingProps extends React.ComponentProps<\"div\"> {\n children: React.ReactNode;\n asChild?: boolean;\n}\n\nconst Loading = React.memo(({ children, asChild, ...props }: LoadingProps) => {\n const Element = asChild ? Slot : \"div\";\n const { videoRef } = useVideo();\n\n const { isLoading } = useLoading(videoRef);\n\n return (\n <Element\n {...props}\n style={{ ...props.style, pointerEvents: \"none\" }}\n data-loading={isLoading}\n >\n {children}\n </Element>\n );\n});\n\ninterface ShadowProps extends React.ComponentProps<\"div\"> {}\n\nconst Shadow = ({ ...props }: ShadowProps) => {\n const { videoRef } = useVideo();\n\n const shadowVideoRef = useRef<HTMLVideoElement>(null);\n\n React.useEffect(() => {\n const video = videoRef?.current;\n if (shadowVideoRef.current && video) {\n let currentTime = 0;\n let isPlaying = false;\n let interval: ReturnType<typeof setInterval> | null = null;\n\n const startInterval = () => {\n if (interval) clearInterval(interval);\n interval = setInterval(() => {\n console.log(\"currentTime\", video.currentTime);\n currentTime = video.currentTime;\n if (shadowVideoRef.current) {\n shadowVideoRef.current.currentTime = currentTime;\n }\n }, 100);\n };\n\n const stopInterval = () => {\n if (interval) {\n clearInterval(interval);\n interval = null;\n }\n };\n\n const handlePlay = () => {\n isPlaying = true;\n startInterval();\n };\n\n const handlePause = () => {\n isPlaying = false;\n stopInterval();\n };\n\n video.addEventListener(\"play\", handlePlay);\n video.addEventListener(\"pause\", handlePause);\n\n return () => {\n stopInterval();\n video.removeEventListener(\"play\", handlePlay);\n video.removeEventListener(\"pause\", handlePause);\n };\n }\n }, [videoRef?.current]);\n\n if (!videoRef?.current) return null;\n\n return (\n <div\n {...props}\n style={{\n ...props.style,\n position: \"absolute\",\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n }}\n >\n <video\n ref={shadowVideoRef}\n src={videoRef.current.src}\n muted\n playsInline\n style={{\n width: \"100%\",\n height: \"100%\",\n objectFit: \"cover\",\n }}\n />\n </div>\n );\n};\n\nexport {\n Controls,\n Play,\n Pause,\n Mute,\n Unmute,\n Speed,\n SeekForward,\n SeekBackward,\n Fullscreen,\n ExitFullscreen,\n PictureInPicture,\n Download,\n Loading,\n Shadow,\n};\n","import React from \"react\";\nimport type { VideoRef } from \"../types\";\n\nexport const useLoading = (videoRef: VideoRef) => {\n const [isLoading, setIsLoading] = React.useState(false);\n\n React.useEffect(() => {\n if (!videoRef?.current) return;\n\n const video = videoRef.current;\n\n const handleLoadStart = () => {\n setIsLoading(true);\n };\n\n const handleLoadedMetadata = () => {\n // Metadata loaded but video might not be ready to play yet\n // Keep loading true until canplay\n };\n\n const handleLoadedData = () => {\n // First frame loaded, but might still be buffering\n // Keep loading true until canplay\n };\n\n const handleCanPlay = () => {\n setIsLoading(false);\n };\n\n const handleCanPlayThrough = () => {\n setIsLoading(false);\n };\n\n const handleWaiting = () => {\n // Video is waiting for data (buffering)\n setIsLoading(true);\n };\n\n const handlePlaying = () => {\n // Video is playing, so it's not loading anymore\n setIsLoading(false);\n };\n\n const handleError = () => {\n setIsLoading(false);\n };\n\n const handleAbort = () => {\n setIsLoading(false);\n };\n\n const handleSuspend = () => {\n // Loading suspended (e.g., user paused)\n // Don't change loading state here\n };\n\n // Add event listeners\n video.addEventListener(\"loadstart\", handleLoadStart);\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.addEventListener(\"loadeddata\", handleLoadedData);\n video.addEventListener(\"canplay\", handleCanPlay);\n video.addEventListener(\"canplaythrough\", handleCanPlayThrough);\n video.addEventListener(\"waiting\", handleWaiting);\n video.addEventListener(\"playing\", handlePlaying);\n video.addEventListener(\"error\", handleError);\n video.addEventListener(\"abort\", handleAbort);\n video.addEventListener(\"suspend\", handleSuspend);\n\n // Check initial state\n if (video.readyState >= 2) {\n setIsLoading(false);\n }\n\n return () => {\n // Remove event listeners\n video.removeEventListener(\"loadstart\", handleLoadStart);\n video.removeEventListener(\"loadedmetadata\", handleLoadedMetadata);\n video.removeEventListener(\"loadeddata\", handleLoadedData);\n video.removeEventListener(\"canplay\", handleCanPlay);\n video.removeEventListener(\"canplaythrough\", handleCanPlayThrough);\n video.removeEventListener(\"waiting\", handleWaiting);\n video.removeEventListener(\"playing\", handlePlaying);\n video.removeEventListener(\"error\", handleError);\n video.removeEventListener(\"abort\", handleAbort);\n video.removeEventListener(\"suspend\", handleSuspend);\n };\n }, [videoRef]);\n\n return { isLoading };\n};\n"],"mappings":"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","names":["React","createContext","useContext","useEffect","useRef","useState","jsx","VideoContext","VideoProvider","children","config","onError","props","videoRef","setVideoRef","error","setError","isFocused","setIsFocused","videoWrapperRef","videoWrapper","controls","video","hideTimeout","hideDelay","isMouseOver","resetTimer","control","showControls","hideControls","handleMouseMove","handlePlay","handleClick","event","_a","useVideo","context","forwardRef","useEffect","useRef","Keyboards","videoRef","useVideo","seekForward","seekBackward","useSeek","togglePlay","usePlayPause","toggleMute","useMuteUnmute","toggleFullscreen","useFullscreen","togglePictureInPicture","usePictureInPicture","useHotKeys","Fragment","jsx","jsxs","Video","forwardRef","src","autoPlay","muteFallback","controls","preload","autoPlayOnVisible","props","ref","videoRef","setVideoRef","config","setError","error","isFocused","useVideo","refVideo","useRef","useEffect","video","thirdPartyRef","useAutoplayByForce","useAutoplayOnVisible","onPlay","_a","_b","_c","Keyboards","React","useRef","Slot","React","useLoading","videoRef","isLoading","setIsLoading","video","handleLoadStart","handleLoadedMetadata","handleLoadedData","handleCanPlay","handleCanPlayThrough","handleWaiting","handlePlaying","handleError","handleAbort","handleSuspend","jsx","Controls","React","children","asChild","props","Play","Element","Slot","videoRef","useVideo","play","usePlayPause","Pause","pause","Mute","mute","useMuteUnmute","Unmute","unmute","Speed","value","onClick","speed","onChangeSpeed","useSpeed","SeekForward","seekForward","useSeek","SeekBackward","seekBackward","Fullscreen","toggleFullscreen","useFullscreen","ExitFullscreen","PictureInPicture","togglePictureInPicture","usePictureInPicture","Download","downloadDirect","useDownload","Loading","isLoading","useLoading","Shadow","shadowVideoRef","useRef","video","currentTime","isPlaying","interval","startInterval","stopInterval","handlePlay","handlePause"]}
@@ -0,0 +1,9 @@
1
+ import { RefObject } from 'react';
2
+
3
+ type VideoAutoplay = boolean | "force";
4
+ type CustomVideoRef = RefObject<(Omit<HTMLVideoElement, "autoplay"> & {
5
+ autoplay?: VideoAutoplay;
6
+ }) | null>;
7
+ type VideoRef = RefObject<HTMLVideoElement | null> | null;
8
+
9
+ export type { CustomVideoRef as C, VideoRef as V, VideoAutoplay as a };
@@ -0,0 +1,9 @@
1
+ import { RefObject } from 'react';
2
+
3
+ type VideoAutoplay = boolean | "force";
4
+ type CustomVideoRef = RefObject<(Omit<HTMLVideoElement, "autoplay"> & {
5
+ autoplay?: VideoAutoplay;
6
+ }) | null>;
7
+ type VideoRef = RefObject<HTMLVideoElement | null> | null;
8
+
9
+ export type { CustomVideoRef as C, VideoRef as V, VideoAutoplay as a };
@@ -0,0 +1,9 @@
1
+ import { RefObject } from 'react';
2
+
3
+ type VideoAutoplay = boolean | "force";
4
+ type CustomVideoRef = RefObject<(Omit<HTMLVideoElement, "autoplay"> & {
5
+ autoplay?: VideoAutoplay;
6
+ }) | null>;
7
+ type VideoRef = RefObject<HTMLVideoElement | null> | null;
8
+
9
+ export type { CustomVideoRef as C, VideoAutoplay as V, VideoRef as a };
@@ -0,0 +1,9 @@
1
+ import { RefObject } from 'react';
2
+
3
+ type VideoAutoplay = boolean | "force";
4
+ type CustomVideoRef = RefObject<(Omit<HTMLVideoElement, "autoplay"> & {
5
+ autoplay?: VideoAutoplay;
6
+ }) | null>;
7
+ type VideoRef = RefObject<HTMLVideoElement | null> | null;
8
+
9
+ export type { CustomVideoRef as C, VideoAutoplay as V, VideoRef as a };
@@ -0,0 +1,2 @@
1
+ "use strict";var d=Object.defineProperty;var T=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var w=Object.prototype.hasOwnProperty;var x=(o,t)=>{for(var s in t)d(o,s,{get:t[s],enumerable:!0})},y=(o,t,s,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of F(t))!w.call(o,r)&&r!==s&&d(o,r,{get:()=>t[r],enumerable:!(n=T(t,r))||n.enumerable});return o};var L=o=>y(d({},"__esModule",{value:!0}),o);var Z={};x(Z,{compactTime:()=>b,detailedTime:()=>M,formatTime:()=>$,formatTimeForAccessibility:()=>O,formatTimeWithPercentage:()=>A,getTimeSegments:()=>H,humanizeTime:()=>g,parseTime:()=>W,timeRemaining:()=>z});module.exports=L(Z);function $(o,t="mm:ss"){let s=typeof t=="string"?{format:t}:t,{format:n="mm:ss",showHours:r=!0,showLeadingZeros:i=!0,showMilliseconds:c=!1,humanize:a=!1,compact:m=!1}=s;if(a)return g(o,{compact:m});let u=Math.floor(o),h=Math.floor(u/3600),l=Math.floor(u%3600/60),f=u%60,j=Math.floor(o%1*1e3),e=(p,S=2)=>i?p.toString().padStart(S,"0"):p.toString();switch(n){case"h:mm:ss":return`${e(h)}:${e(l)}:${e(f)}`;case"mm:ss":return r&&h>0?`${e(h)}:${e(l)}:${e(f)}`:`${e(l)}:${e(f)}`;case"ss":return`${u}s`;case"compact":return b(o);case"detailed":return M(o,{showMilliseconds:c});default:return`${e(l)}:${e(f)}`}}function g(o,t={}){let{compact:s=!1}=t,n=Math.floor(o);if(n<60)return`${n} second${n!==1?"s":""}`;let r=Math.floor(n/3600),i=Math.floor(n%3600/60),c=n%60,a=[];return r>0&&a.push(`${r} hour${r!==1?"s":""}`),i>0&&a.push(`${i} minute${i!==1?"s":""}`),c>0&&!s&&a.push(`${c} second${c!==1?"s":""}`),a.join(" ")}function b(o){let t=Math.floor(o),s=Math.floor(t/3600),n=Math.floor(t%3600/60),r=t%60;return s>0?`${s}:${n.toString().padStart(2,"0")}:${r.toString().padStart(2,"0")}`:`${n}:${r.toString().padStart(2,"0")}`}function M(o,t={}){let{showMilliseconds:s=!1}=t,n=Math.floor(o),r=Math.floor(n/3600),i=Math.floor(n%3600/60),c=n%60,a=Math.floor(o%1*1e3),m=`${r.toString().padStart(2,"0")}:${i.toString().padStart(2,"0")}:${c.toString().padStart(2,"0")}`;return s&&(m+=`.${a.toString().padStart(3,"0")}`),m}function W(o){let t=o.toLowerCase().trim();if(t.endsWith("s"))return parseFloat(t.slice(0,-1));if(t.endsWith("m"))return parseFloat(t.slice(0,-1))*60;if(t.endsWith("h"))return parseFloat(t.slice(0,-1))*3600;let s=o.split(":").map(Number);return s.length===2?(s[0]||0)*60+(s[1]||0):s.length===3?(s[0]||0)*3600+(s[1]||0)*60+(s[2]||0):parseFloat(o)||0}function z(o,t,s="mm:ss"){let n=Math.max(0,t-o);return $(n,s)}function A(o,t,s="mm:ss"){let n=t>0?Math.round(o/t*100):0;return`${$(o,s)} (${n}%)`}function H(o,t=10){return Array.from({length:t+1},(s,n)=>o/t*n)}function O(o){let t=Math.floor(o),s=Math.floor(t/3600),n=Math.floor(t%3600/60),r=t%60;return s>0?`${s} hours, ${n} minutes, ${r} seconds`:n>0?`${n} minutes, ${r} seconds`:`${r} seconds`}0&&(module.exports={compactTime,detailedTime,formatTime,formatTimeForAccessibility,formatTimeWithPercentage,getTimeSegments,humanizeTime,parseTime,timeRemaining});
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/index.ts"],"sourcesContent":["// Video Time Formatting Utilities - Similar to date-fns but for video durations\n\nexport type TimeFormat =\n | \"h:mm:ss\"\n | \"mm:ss\"\n | \"ss\"\n | \"human\"\n | \"compact\"\n | \"detailed\";\n\nexport interface TimeFormatOptions {\n format?: TimeFormat;\n showHours?: boolean;\n showLeadingZeros?: boolean;\n showMilliseconds?: boolean;\n humanize?: boolean;\n compact?: boolean;\n}\n\n/**\n * Format time in seconds to various formats\n */\nfunction formatTime(\n time: number,\n options: TimeFormatOptions | TimeFormat = \"mm:ss\"\n): string {\n const opts = typeof options === \"string\" ? { format: options } : options;\n const {\n format = \"mm:ss\",\n showHours = true,\n showLeadingZeros = true,\n showMilliseconds = false,\n humanize = false,\n compact = false,\n } = opts;\n\n if (humanize) {\n return humanizeTime(time, { compact });\n }\n\n const totalSeconds = Math.floor(time);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const milliseconds = Math.floor((time % 1) * 1000);\n\n const pad = (num: number, size: number = 2) =>\n showLeadingZeros ? num.toString().padStart(size, \"0\") : num.toString();\n\n switch (format) {\n case \"h:mm:ss\":\n return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;\n case \"mm:ss\":\n return showHours && hours > 0\n ? `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`\n : `${pad(minutes)}:${pad(seconds)}`;\n case \"ss\":\n return `${totalSeconds}s`;\n case \"compact\":\n return compactTime(time);\n case \"detailed\":\n return detailedTime(time, { showMilliseconds });\n default:\n return `${pad(minutes)}:${pad(seconds)}`;\n }\n}\n\n/**\n * Humanize time duration (e.g., \"2 minutes 30 seconds\")\n */\nfunction humanizeTime(\n time: number,\n options: { compact?: boolean } = {}\n): string {\n const { compact = false } = options;\n const totalSeconds = Math.floor(time);\n\n if (totalSeconds < 60) {\n return `${totalSeconds} second${totalSeconds !== 1 ? \"s\" : \"\"}`;\n }\n\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n const parts: string[] = [];\n\n if (hours > 0) {\n parts.push(`${hours} hour${hours !== 1 ? \"s\" : \"\"}`);\n }\n\n if (minutes > 0) {\n parts.push(`${minutes} minute${minutes !== 1 ? \"s\" : \"\"}`);\n }\n\n if (seconds > 0 && !compact) {\n parts.push(`${seconds} second${seconds !== 1 ? \"s\" : \"\"}`);\n }\n\n return parts.join(\" \");\n}\n\n/**\n * Compact time format (e.g., \"2:30\" for 2 minutes 30 seconds)\n */\nfunction compactTime(time: number): string {\n const totalSeconds = Math.floor(time);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\n }\n\n return `${minutes}:${seconds.toString().padStart(2, \"0\")}`;\n}\n\n/**\n * Detailed time format with milliseconds\n */\nfunction detailedTime(\n time: number,\n options: { showMilliseconds?: boolean } = {}\n): string {\n const { showMilliseconds = false } = options;\n const totalSeconds = Math.floor(time);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const milliseconds = Math.floor((time % 1) * 1000);\n\n let result = `${hours.toString().padStart(2, \"0\")}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\n\n if (showMilliseconds) {\n result += `.${milliseconds.toString().padStart(3, \"0\")}`;\n }\n\n return result;\n}\n\n/**\n * Parse time string to seconds\n */\nfunction parseTime(timeString: string): number {\n // Handle formats like \"2:30\", \"1:23:45\", \"90s\", \"1.5m\"\n const timeStringLower = timeString.toLowerCase().trim();\n\n // Handle seconds format \"90s\"\n if (timeStringLower.endsWith(\"s\")) {\n return parseFloat(timeStringLower.slice(0, -1));\n }\n\n // Handle minutes format \"1.5m\"\n if (timeStringLower.endsWith(\"m\")) {\n return parseFloat(timeStringLower.slice(0, -1)) * 60;\n }\n\n // Handle hours format \"1.5h\"\n if (timeStringLower.endsWith(\"h\")) {\n return parseFloat(timeStringLower.slice(0, -1)) * 3600;\n }\n\n // Handle HH:MM:SS or MM:SS format\n const parts = timeString.split(\":\").map(Number);\n\n if (parts.length === 2) {\n // MM:SS format\n return (parts[0] || 0) * 60 + (parts[1] || 0);\n } else if (parts.length === 3) {\n // HH:MM:SS format\n return (parts[0] || 0) * 3600 + (parts[1] || 0) * 60 + (parts[2] || 0);\n }\n\n // Fallback to parsing as seconds\n return parseFloat(timeString) || 0;\n}\n\n/**\n * Calculate time remaining\n */\nfunction timeRemaining(\n current: number,\n total: number,\n format: TimeFormat = \"mm:ss\"\n): string {\n const remaining = Math.max(0, total - current);\n return formatTime(remaining, format);\n}\n\n/**\n * Format time with percentage\n */\nfunction formatTimeWithPercentage(\n current: number,\n total: number,\n format: TimeFormat = \"mm:ss\"\n): string {\n const percentage = total > 0 ? Math.round((current / total) * 100) : 0;\n return `${formatTime(current, format)} (${percentage}%)`;\n}\n\n/**\n * Get time segments for timeline\n */\nfunction getTimeSegments(duration: number, segments: number = 10): number[] {\n return Array.from(\n { length: segments + 1 },\n (_, i) => (duration / segments) * i\n );\n}\n\n/**\n * Format time for accessibility (screen readers)\n */\nfunction formatTimeForAccessibility(time: number): string {\n const totalSeconds = Math.floor(time);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n if (hours > 0) {\n return `${hours} hours, ${minutes} minutes, ${seconds} seconds`;\n } else if (minutes > 0) {\n return `${minutes} minutes, ${seconds} seconds`;\n } else {\n return `${seconds} seconds`;\n }\n}\n\nexport {\n formatTime,\n humanizeTime,\n compactTime,\n detailedTime,\n parseTime,\n timeRemaining,\n formatTimeWithPercentage,\n getTimeSegments,\n formatTimeForAccessibility,\n};\n"],"mappings":"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","names":["utils_exports","__export","compactTime","detailedTime","formatTime","formatTimeForAccessibility","formatTimeWithPercentage","getTimeSegments","humanizeTime","parseTime","timeRemaining","__toCommonJS","time","options","opts","format","showHours","showLeadingZeros","showMilliseconds","humanize","compact","totalSeconds","hours","minutes","seconds","milliseconds","pad","num","size","parts","result","timeString","timeStringLower","current","total","remaining","percentage","duration","segments","_","i"]}
@@ -0,0 +1,51 @@
1
+ type TimeFormat = "h:mm:ss" | "mm:ss" | "ss" | "human" | "compact" | "detailed";
2
+ interface TimeFormatOptions {
3
+ format?: TimeFormat;
4
+ showHours?: boolean;
5
+ showLeadingZeros?: boolean;
6
+ showMilliseconds?: boolean;
7
+ humanize?: boolean;
8
+ compact?: boolean;
9
+ }
10
+ /**
11
+ * Format time in seconds to various formats
12
+ */
13
+ declare function formatTime(time: number, options?: TimeFormatOptions | TimeFormat): string;
14
+ /**
15
+ * Humanize time duration (e.g., "2 minutes 30 seconds")
16
+ */
17
+ declare function humanizeTime(time: number, options?: {
18
+ compact?: boolean;
19
+ }): string;
20
+ /**
21
+ * Compact time format (e.g., "2:30" for 2 minutes 30 seconds)
22
+ */
23
+ declare function compactTime(time: number): string;
24
+ /**
25
+ * Detailed time format with milliseconds
26
+ */
27
+ declare function detailedTime(time: number, options?: {
28
+ showMilliseconds?: boolean;
29
+ }): string;
30
+ /**
31
+ * Parse time string to seconds
32
+ */
33
+ declare function parseTime(timeString: string): number;
34
+ /**
35
+ * Calculate time remaining
36
+ */
37
+ declare function timeRemaining(current: number, total: number, format?: TimeFormat): string;
38
+ /**
39
+ * Format time with percentage
40
+ */
41
+ declare function formatTimeWithPercentage(current: number, total: number, format?: TimeFormat): string;
42
+ /**
43
+ * Get time segments for timeline
44
+ */
45
+ declare function getTimeSegments(duration: number, segments?: number): number[];
46
+ /**
47
+ * Format time for accessibility (screen readers)
48
+ */
49
+ declare function formatTimeForAccessibility(time: number): string;
50
+
51
+ export { type TimeFormat, type TimeFormatOptions, compactTime, detailedTime, formatTime, formatTimeForAccessibility, formatTimeWithPercentage, getTimeSegments, humanizeTime, parseTime, timeRemaining };
@@ -0,0 +1,51 @@
1
+ type TimeFormat = "h:mm:ss" | "mm:ss" | "ss" | "human" | "compact" | "detailed";
2
+ interface TimeFormatOptions {
3
+ format?: TimeFormat;
4
+ showHours?: boolean;
5
+ showLeadingZeros?: boolean;
6
+ showMilliseconds?: boolean;
7
+ humanize?: boolean;
8
+ compact?: boolean;
9
+ }
10
+ /**
11
+ * Format time in seconds to various formats
12
+ */
13
+ declare function formatTime(time: number, options?: TimeFormatOptions | TimeFormat): string;
14
+ /**
15
+ * Humanize time duration (e.g., "2 minutes 30 seconds")
16
+ */
17
+ declare function humanizeTime(time: number, options?: {
18
+ compact?: boolean;
19
+ }): string;
20
+ /**
21
+ * Compact time format (e.g., "2:30" for 2 minutes 30 seconds)
22
+ */
23
+ declare function compactTime(time: number): string;
24
+ /**
25
+ * Detailed time format with milliseconds
26
+ */
27
+ declare function detailedTime(time: number, options?: {
28
+ showMilliseconds?: boolean;
29
+ }): string;
30
+ /**
31
+ * Parse time string to seconds
32
+ */
33
+ declare function parseTime(timeString: string): number;
34
+ /**
35
+ * Calculate time remaining
36
+ */
37
+ declare function timeRemaining(current: number, total: number, format?: TimeFormat): string;
38
+ /**
39
+ * Format time with percentage
40
+ */
41
+ declare function formatTimeWithPercentage(current: number, total: number, format?: TimeFormat): string;
42
+ /**
43
+ * Get time segments for timeline
44
+ */
45
+ declare function getTimeSegments(duration: number, segments?: number): number[];
46
+ /**
47
+ * Format time for accessibility (screen readers)
48
+ */
49
+ declare function formatTimeForAccessibility(time: number): string;
50
+
51
+ export { type TimeFormat, type TimeFormatOptions, compactTime, detailedTime, formatTime, formatTimeForAccessibility, formatTimeWithPercentage, getTimeSegments, humanizeTime, parseTime, timeRemaining };
@@ -0,0 +1,2 @@
1
+ function $(o,t="mm:ss"){let n=typeof t=="string"?{format:t}:t,{format:s="mm:ss",showHours:r=!0,showLeadingZeros:i=!0,showMilliseconds:c=!1,humanize:a=!1,compact:m=!1}=n;if(a)return g(o,{compact:m});let u=Math.floor(o),h=Math.floor(u/3600),l=Math.floor(u%3600/60),f=u%60,S=Math.floor(o%1*1e3),e=(d,p=2)=>i?d.toString().padStart(p,"0"):d.toString();switch(s){case"h:mm:ss":return`${e(h)}:${e(l)}:${e(f)}`;case"mm:ss":return r&&h>0?`${e(h)}:${e(l)}:${e(f)}`:`${e(l)}:${e(f)}`;case"ss":return`${u}s`;case"compact":return b(o);case"detailed":return M(o,{showMilliseconds:c});default:return`${e(l)}:${e(f)}`}}function g(o,t={}){let{compact:n=!1}=t,s=Math.floor(o);if(s<60)return`${s} second${s!==1?"s":""}`;let r=Math.floor(s/3600),i=Math.floor(s%3600/60),c=s%60,a=[];return r>0&&a.push(`${r} hour${r!==1?"s":""}`),i>0&&a.push(`${i} minute${i!==1?"s":""}`),c>0&&!n&&a.push(`${c} second${c!==1?"s":""}`),a.join(" ")}function b(o){let t=Math.floor(o),n=Math.floor(t/3600),s=Math.floor(t%3600/60),r=t%60;return n>0?`${n}:${s.toString().padStart(2,"0")}:${r.toString().padStart(2,"0")}`:`${s}:${r.toString().padStart(2,"0")}`}function M(o,t={}){let{showMilliseconds:n=!1}=t,s=Math.floor(o),r=Math.floor(s/3600),i=Math.floor(s%3600/60),c=s%60,a=Math.floor(o%1*1e3),m=`${r.toString().padStart(2,"0")}:${i.toString().padStart(2,"0")}:${c.toString().padStart(2,"0")}`;return n&&(m+=`.${a.toString().padStart(3,"0")}`),m}function T(o){let t=o.toLowerCase().trim();if(t.endsWith("s"))return parseFloat(t.slice(0,-1));if(t.endsWith("m"))return parseFloat(t.slice(0,-1))*60;if(t.endsWith("h"))return parseFloat(t.slice(0,-1))*3600;let n=o.split(":").map(Number);return n.length===2?(n[0]||0)*60+(n[1]||0):n.length===3?(n[0]||0)*3600+(n[1]||0)*60+(n[2]||0):parseFloat(o)||0}function F(o,t,n="mm:ss"){let s=Math.max(0,t-o);return $(s,n)}function w(o,t,n="mm:ss"){let s=t>0?Math.round(o/t*100):0;return`${$(o,n)} (${s}%)`}function x(o,t=10){return Array.from({length:t+1},(n,s)=>o/t*s)}function y(o){let t=Math.floor(o),n=Math.floor(t/3600),s=Math.floor(t%3600/60),r=t%60;return n>0?`${n} hours, ${s} minutes, ${r} seconds`:s>0?`${s} minutes, ${r} seconds`:`${r} seconds`}export{b as compactTime,M as detailedTime,$ as formatTime,y as formatTimeForAccessibility,w as formatTimeWithPercentage,x as getTimeSegments,g as humanizeTime,T as parseTime,F as timeRemaining};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils/index.ts"],"sourcesContent":["// Video Time Formatting Utilities - Similar to date-fns but for video durations\n\nexport type TimeFormat =\n | \"h:mm:ss\"\n | \"mm:ss\"\n | \"ss\"\n | \"human\"\n | \"compact\"\n | \"detailed\";\n\nexport interface TimeFormatOptions {\n format?: TimeFormat;\n showHours?: boolean;\n showLeadingZeros?: boolean;\n showMilliseconds?: boolean;\n humanize?: boolean;\n compact?: boolean;\n}\n\n/**\n * Format time in seconds to various formats\n */\nfunction formatTime(\n time: number,\n options: TimeFormatOptions | TimeFormat = \"mm:ss\"\n): string {\n const opts = typeof options === \"string\" ? { format: options } : options;\n const {\n format = \"mm:ss\",\n showHours = true,\n showLeadingZeros = true,\n showMilliseconds = false,\n humanize = false,\n compact = false,\n } = opts;\n\n if (humanize) {\n return humanizeTime(time, { compact });\n }\n\n const totalSeconds = Math.floor(time);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const milliseconds = Math.floor((time % 1) * 1000);\n\n const pad = (num: number, size: number = 2) =>\n showLeadingZeros ? num.toString().padStart(size, \"0\") : num.toString();\n\n switch (format) {\n case \"h:mm:ss\":\n return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;\n case \"mm:ss\":\n return showHours && hours > 0\n ? `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`\n : `${pad(minutes)}:${pad(seconds)}`;\n case \"ss\":\n return `${totalSeconds}s`;\n case \"compact\":\n return compactTime(time);\n case \"detailed\":\n return detailedTime(time, { showMilliseconds });\n default:\n return `${pad(minutes)}:${pad(seconds)}`;\n }\n}\n\n/**\n * Humanize time duration (e.g., \"2 minutes 30 seconds\")\n */\nfunction humanizeTime(\n time: number,\n options: { compact?: boolean } = {}\n): string {\n const { compact = false } = options;\n const totalSeconds = Math.floor(time);\n\n if (totalSeconds < 60) {\n return `${totalSeconds} second${totalSeconds !== 1 ? \"s\" : \"\"}`;\n }\n\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n const parts: string[] = [];\n\n if (hours > 0) {\n parts.push(`${hours} hour${hours !== 1 ? \"s\" : \"\"}`);\n }\n\n if (minutes > 0) {\n parts.push(`${minutes} minute${minutes !== 1 ? \"s\" : \"\"}`);\n }\n\n if (seconds > 0 && !compact) {\n parts.push(`${seconds} second${seconds !== 1 ? \"s\" : \"\"}`);\n }\n\n return parts.join(\" \");\n}\n\n/**\n * Compact time format (e.g., \"2:30\" for 2 minutes 30 seconds)\n */\nfunction compactTime(time: number): string {\n const totalSeconds = Math.floor(time);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\n }\n\n return `${minutes}:${seconds.toString().padStart(2, \"0\")}`;\n}\n\n/**\n * Detailed time format with milliseconds\n */\nfunction detailedTime(\n time: number,\n options: { showMilliseconds?: boolean } = {}\n): string {\n const { showMilliseconds = false } = options;\n const totalSeconds = Math.floor(time);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const milliseconds = Math.floor((time % 1) * 1000);\n\n let result = `${hours.toString().padStart(2, \"0\")}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`;\n\n if (showMilliseconds) {\n result += `.${milliseconds.toString().padStart(3, \"0\")}`;\n }\n\n return result;\n}\n\n/**\n * Parse time string to seconds\n */\nfunction parseTime(timeString: string): number {\n // Handle formats like \"2:30\", \"1:23:45\", \"90s\", \"1.5m\"\n const timeStringLower = timeString.toLowerCase().trim();\n\n // Handle seconds format \"90s\"\n if (timeStringLower.endsWith(\"s\")) {\n return parseFloat(timeStringLower.slice(0, -1));\n }\n\n // Handle minutes format \"1.5m\"\n if (timeStringLower.endsWith(\"m\")) {\n return parseFloat(timeStringLower.slice(0, -1)) * 60;\n }\n\n // Handle hours format \"1.5h\"\n if (timeStringLower.endsWith(\"h\")) {\n return parseFloat(timeStringLower.slice(0, -1)) * 3600;\n }\n\n // Handle HH:MM:SS or MM:SS format\n const parts = timeString.split(\":\").map(Number);\n\n if (parts.length === 2) {\n // MM:SS format\n return (parts[0] || 0) * 60 + (parts[1] || 0);\n } else if (parts.length === 3) {\n // HH:MM:SS format\n return (parts[0] || 0) * 3600 + (parts[1] || 0) * 60 + (parts[2] || 0);\n }\n\n // Fallback to parsing as seconds\n return parseFloat(timeString) || 0;\n}\n\n/**\n * Calculate time remaining\n */\nfunction timeRemaining(\n current: number,\n total: number,\n format: TimeFormat = \"mm:ss\"\n): string {\n const remaining = Math.max(0, total - current);\n return formatTime(remaining, format);\n}\n\n/**\n * Format time with percentage\n */\nfunction formatTimeWithPercentage(\n current: number,\n total: number,\n format: TimeFormat = \"mm:ss\"\n): string {\n const percentage = total > 0 ? Math.round((current / total) * 100) : 0;\n return `${formatTime(current, format)} (${percentage}%)`;\n}\n\n/**\n * Get time segments for timeline\n */\nfunction getTimeSegments(duration: number, segments: number = 10): number[] {\n return Array.from(\n { length: segments + 1 },\n (_, i) => (duration / segments) * i\n );\n}\n\n/**\n * Format time for accessibility (screen readers)\n */\nfunction formatTimeForAccessibility(time: number): string {\n const totalSeconds = Math.floor(time);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n if (hours > 0) {\n return `${hours} hours, ${minutes} minutes, ${seconds} seconds`;\n } else if (minutes > 0) {\n return `${minutes} minutes, ${seconds} seconds`;\n } else {\n return `${seconds} seconds`;\n }\n}\n\nexport {\n formatTime,\n humanizeTime,\n compactTime,\n detailedTime,\n parseTime,\n timeRemaining,\n formatTimeWithPercentage,\n getTimeSegments,\n formatTimeForAccessibility,\n};\n"],"mappings":"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","names":["formatTime","time","options","opts","format","showHours","showLeadingZeros","showMilliseconds","humanize","compact","humanizeTime","totalSeconds","hours","minutes","seconds","milliseconds","pad","num","size","compactTime","detailedTime","parts","result","parseTime","timeString","timeStringLower","timeRemaining","current","total","remaining","formatTimeWithPercentage","percentage","getTimeSegments","duration","segments","_","i","formatTimeForAccessibility"]}