UNPKG

react-video-timestone

Version:

A React component library for video timestone functionality

28 lines (27 loc) 16.4 kB
(function(T,m){typeof exports=="object"&&typeof module<"u"?m(exports,require("react")):typeof define=="function"&&define.amd?define(["exports","react"],m):(T=typeof globalThis<"u"?globalThis:T||self,m(T.ReactVideoTimestone={},T.React))})(this,function(T,m){"use strict";var q=document.createElement("style");q.textContent=`._1spdh1z0{position:absolute;bottom:24px;display:flex;flex-direction:column;gap:8px;align-items:flex-start;padding:0 24px;width:fit-content;text-align:left;z-index:10}._1spdh1z1{display:flex;justify-content:center;align-items:center;gap:10px}._1spdh1z2{font-size:12px;font-weight:700;color:#fff}._1spdh1z3{padding:10px 20px;border:none;border-radius:4px;cursor:pointer;background:#ffffffb3}._1spdh1z3:hover{background:#ffffffe6}._1spdh1z4{position:relative;width:100%;height:4px;background-color:#fff}._1spdh1z5{width:100%;height:4px;background-color:#0f0;transform:scaleX(.5);transform-origin:left}._1spdh1z6{position:absolute;top:50%;left:0;transform:translate(-50%,-50%);background:red;width:16px;height:16px;border-radius:100%;border:none;cursor:pointer}._1spdh1z7{display:block;position:absolute;top:100%;font-size:12px;padding:8px;border:none;border-radius:4px;background:#ffffff80;width:max-content;transform:translate(-50%,-50%);opacity:0}._1spdh1z8{position:absolute;top:50%;right:0;transform:translate(-50%,-50%);width:16px;height:16px;border-radius:100%;background:red;cursor:pointer;z-index:10}._10oingv0{position:relative;width:100%;height:100%}._10oingv1{position:relative;width:100%;height:100%;object-fit:cover;z-index:2}._10oingv2{position:absolute;top:0;left:0;width:100%;height:100%;background-size:cover;background-position:center;z-index:1}._14pkj7w0{position:relative;width:100%;height:100%;background-color:#000;border-radius:8px;overflow:hidden}._14pkj7w1{position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9999;border-radius:0} /*$vite$:1*/`,document.head.appendChild(q);function ue(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}var M={exports:{}},W={};/** * @license React * react-jsx-runtime.production.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */var Z;function ce(){if(Z)return W;Z=1;var r=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function i(c,l,n){var o=null;if(n!==void 0&&(o=""+n),l.key!==void 0&&(o=""+l.key),"key"in l){n={};for(var f in l)f!=="key"&&(n[f]=l[f])}else n=l;return l=n.ref,{$$typeof:r,type:c,key:o,ref:l!==void 0?l:null,props:n}}return W.Fragment=t,W.jsx=i,W.jsxs=i,W}var U={};/** * @license React * react-jsx-runtime.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */var Q;function fe(){return Q||(Q=1,process.env.NODE_ENV!=="production"&&function(){function r(e){if(e==null)return null;if(typeof e=="function")return e.$$typeof===g?null:e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case p:return"Fragment";case b:return"Profiler";case P:return"StrictMode";case w:return"Suspense";case j:return"SuspenseList";case D:return"Activity"}if(typeof e=="object")switch(typeof e.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),e.$$typeof){case x:return"Portal";case z:return(e.displayName||"Context")+".Provider";case _:return(e._context.displayName||"Context")+".Consumer";case k:var a=e.render;return e=e.displayName,e||(e=a.displayName||a.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case C:return a=e.displayName||null,a!==null?a:r(e.type)||"Memo";case S:a=e._payload,e=e._init;try{return r(e(a))}catch{}}return null}function t(e){return""+e}function i(e){try{t(e);var a=!1}catch{a=!0}if(a){a=console;var d=a.error,R=typeof Symbol=="function"&&Symbol.toStringTag&&e[Symbol.toStringTag]||e.constructor.name||"Object";return d.call(a,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",R),t(e)}}function c(e){if(e===p)return"<>";if(typeof e=="object"&&e!==null&&e.$$typeof===S)return"<...>";try{var a=r(e);return a?"<"+a+">":"<...>"}catch{return"<...>"}}function l(){var e=F.A;return e===null?null:e.getOwner()}function n(){return Error("react-stack-top-frame")}function o(e){if(G.call(e,"key")){var a=Object.getOwnPropertyDescriptor(e,"key").get;if(a&&a.isReactWarning)return!1}return e.key!==void 0}function f(e,a){function d(){oe||(oe=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",a))}d.isReactWarning=!0,Object.defineProperty(e,"key",{get:d,configurable:!0})}function s(){var e=r(this.type);return ae[e]||(ae[e]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),e=this.props.ref,e!==void 0?e:null}function u(e,a,d,R,I,N,J,H){return d=N.ref,e={$$typeof:h,type:e,key:a,props:N,_owner:I},(d!==void 0?d:null)!==null?Object.defineProperty(e,"ref",{enumerable:!1,get:s}):Object.defineProperty(e,"ref",{enumerable:!1,value:null}),e._store={},Object.defineProperty(e._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(e,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(e,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:J}),Object.defineProperty(e,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:H}),Object.freeze&&(Object.freeze(e.props),Object.freeze(e)),e}function v(e,a,d,R,I,N,J,H){var E=a.children;if(E!==void 0)if(R)if(L(E)){for(R=0;R<E.length;R++)O(E[R]);Object.freeze&&Object.freeze(E)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else O(E);if(G.call(a,"key")){E=r(e);var V=Object.keys(a).filter(function(Ie){return Ie!=="key"});R=0<V.length?"{key: someKey, "+V.join(": ..., ")+": ...}":"{key: someKey}",le[E+R]||(V=0<V.length?"{"+V.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX: let props = %s; <%s {...props} /> React keys must be passed directly to JSX without using spread: let props = %s; <%s key={someKey} {...props} />`,R,E,V,E),le[E+R]=!0)}if(E=null,d!==void 0&&(i(d),E=""+d),o(a)&&(i(a.key),E=""+a.key),"key"in a){d={};for(var X in a)X!=="key"&&(d[X]=a[X])}else d=a;return E&&f(d,typeof e=="function"?e.displayName||e.name||"Unknown":e),u(e,E,N,I,l(),d,J,H)}function O(e){typeof e=="object"&&e!==null&&e.$$typeof===h&&e._store&&(e._store.validated=1)}var y=m,h=Symbol.for("react.transitional.element"),x=Symbol.for("react.portal"),p=Symbol.for("react.fragment"),P=Symbol.for("react.strict_mode"),b=Symbol.for("react.profiler"),_=Symbol.for("react.consumer"),z=Symbol.for("react.context"),k=Symbol.for("react.forward_ref"),w=Symbol.for("react.suspense"),j=Symbol.for("react.suspense_list"),C=Symbol.for("react.memo"),S=Symbol.for("react.lazy"),D=Symbol.for("react.activity"),g=Symbol.for("react.client.reference"),F=y.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,G=Object.prototype.hasOwnProperty,L=Array.isArray,Y=console.createTask?console.createTask:function(){return null};y={react_stack_bottom_frame:function(e){return e()}};var oe,ae={},ie=y.react_stack_bottom_frame.bind(y,n)(),se=Y(c(n)),le={};U.Fragment=p,U.jsx=function(e,a,d,R,I){var N=1e4>F.recentlyCreatedOwnerStacks++;return v(e,a,d,!1,R,I,N?Error("react-stack-top-frame"):ie,N?Y(c(e)):se)},U.jsxs=function(e,a,d,R,I){var N=1e4>F.recentlyCreatedOwnerStacks++;return v(e,a,d,!0,R,I,N?Error("react-stack-top-frame"):ie,N?Y(c(e)):se)}}()),U}var $;function de(){return $||($=1,process.env.NODE_ENV==="production"?M.exports=ce():M.exports=fe()),M.exports}var A=de(),B={exports:{}};/*! Copyright (c) 2018 Jed Watson. Licensed under the MIT License (MIT), see http://jedwatson.github.io/classnames */var ee;function pe(){return ee||(ee=1,function(r){(function(){var t={}.hasOwnProperty;function i(){for(var n="",o=0;o<arguments.length;o++){var f=arguments[o];f&&(n=l(n,c(f)))}return n}function c(n){if(typeof n=="string"||typeof n=="number")return n;if(typeof n!="object")return"";if(Array.isArray(n))return i.apply(null,n);if(n.toString!==Object.prototype.toString&&!n.toString.toString().includes("[native code]"))return n.toString();var o="";for(var f in n)t.call(n,f)&&n[f]&&(o=l(o,f));return o}function l(n,o){return o?n?n+" "+o:n+o:n}r.exports?(i.default=i,r.exports=i):window.classNames=i})()}(B)),B.exports}var me=pe();const ye=ue(me),Re=(r,t)=>{const i=c=>c==="FORWARD"?"BACKWARD":"FORWARD";switch(r.playerState){case"INIT":return t.type==="LOADING"?{...r,markers:t.payload,playerState:t.type}:r;case"LOADING":return t.type==="LOADING_PROGRESS"?{...r,playerState:t.type}:t.type==="READY"?{...r,playerState:t.type}:r;case"LOADING_PROGRESS":return t.type==="READY"?{...r,playerState:t.type,loadedVideoUrls:t.payload}:t.type==="LOADING_PROGRESS"?{...r,loadingProgress:t.payload}:{...r};case"READY":return t.type==="PLAYING"?{...r,playerState:t.type}:r;case"PLAYING":return t.type==="PAUSED"?{...r,playerState:t.type}:t.type==="ENDED"?{...r,playerState:t.type}:t.type==="TIMELINE_ENDED"?{...r,playerState:t.type}:t.type==="REVERSE"?{...r,playDirection:i(r.playDirection)}:r;case"PAUSED":return t.type==="PLAYING"?{...r,playerState:t.type}:t.type==="REVERSE"?{...r,playDirection:i(r.playDirection)}:r;case"ENDED":return t.type==="PLAYING"?{...r,playIndex:r.playDirection==="FORWARD"?r.playIndex<r.loadedVideoUrls.length-1?r.playIndex+1:0:r.playIndex>0?r.playIndex-1:0,playerState:t.type}:t.type==="REVERSE"?{...r,playDirection:i(r.playDirection)}:r;case"TIMELINE_ENDED":return t.type==="PLAYING"?{...r,playerState:t.type}:t.type==="REVERSE"?{...r,playDirection:i(r.playDirection)}:r;default:return r}},Ee=({videoRef:r,onEnded:t,speed:i=1,videoCount:c,playIndex:l})=>{const n=33.333333333333336,o=m.useRef(null),f=m.useRef("FORWARD"),s=m.useRef(0),u=m.useRef(null),[v,O]=m.useState([]);function y(){let b=null;if(!r.current)throw new Error("videoRef 가 존재하지 않습니다.");s.current=r.current.currentTime;function _(){o.current&&(cancelAnimationFrame(o.current),o.current=null)}function z({markers:w,prevCurrentTime:j,newCurrentTime:C}){if(!w||w.length===0)return;u.current&&Math.abs(s.current-C)>.2&&(u.current=null);const S=w.find(D=>{if(typeof D?.videoIndex<"u"&&l!==D.videoIndex)return null;const g=f.current==="FORWARD",F=D.direction||"BOTH";if(F==="FORWARD"&&!g||F==="BACKWARD"&&g)return null;const G=Number(j.toFixed(2)),L=Number(D.time.toFixed(2)),Y=Number(C.toFixed(2));return g&&L>G&&L<=Y||!g&&Y<=L&&L<G?D:null});S&&u.current!==S.label&&(S.action==="PAUSE"&&(S.triggerPause?.(),_()),S.callback?.(),u.current=S.label)}function k(w){const j=f.current==="FORWARD";if(!r.current)throw new Error("videoRef 가 존재하지 않습니다.");if(b===null){b=w,o.current=requestAnimationFrame(k);return}const C=w-b;if(C>=n){const S=C/1e3*i;b=w;const D=r.current.currentTime,g=j?r.current.currentTime+S:r.current.currentTime-S;r.current.currentTime=g,z({markers:v,prevCurrentTime:D,newCurrentTime:g}),(j?r.current.duration>g:0<g)?o.current=requestAnimationFrame(k):o.current&&(_(),t&&t({isTimelineEnded:j?l===c-1:l===0}))}else o.current=requestAnimationFrame(k)}o.current=requestAnimationFrame(k)}function h(){o.current&&(cancelAnimationFrame(o.current),o.current=null)}function x(){f.current=f.current==="FORWARD"?"BACKWARD":"FORWARD"}function p({time:b,autoPlay:_=!1}){r.current&&(h(),r.current.currentTime=b,_&&y())}function P(b){O(_=>[..._,...b])}return m.useEffect(()=>()=>{o.current&&(cancelAnimationFrame(o.current),o.current=null)},[]),{play:y,pause:h,reverse:x,seekTo:p,addMarkers:P}},re=(r,t)=>r?.map(i=>({...i,triggerPause:()=>{t({type:"PAUSED"})}}))||[];async function he(r){return(await Promise.all(r.map(c=>fetch(c,{method:"HEAD"})))).map(c=>c.headers.get("content-length")).reduce((c,l)=>c+Number(l),0)}const be=async({urls:r,onProgress:t,onReady:i})=>{let c=0;const l=await he(r),n=r.map(()=>0),o=await Promise.all(r.map(async(u,v)=>await f(u,v)));async function f(u,v){const y=await fetch(u,{method:"GET"});return await new Response(new ReadableStream({start(x){const p=y.body?.getReader();P();function P(){p?.read().then(({done:b,value:_})=>{if(b){x.close();return}n[v]=(n?.[v]??0)+(_?.byteLength??0),c=n.reduce((z,k)=>z+k,0)/l*100,t&&t(c),x.enqueue(_),P()})}}}),{status:200,headers:{"Content-Type":"video/mp4"}}).blob()}const s=o.map(u=>URL.createObjectURL(u));return i&&i(s),{blobUrls:s,cleanup:()=>{s.forEach(u=>URL.revokeObjectURL(u))}}},Ae=({ref:r,markers:t,videoUrls:i,speed:c,onLoading:l,onReady:n,onLoaded:o,onStateChange:f})=>{const[s,u]=m.useReducer(Re,{loadingProgress:0,loadedVideoUrls:[],playerState:"INIT",playDirection:"FORWARD",playIndex:0,markers:[]}),{play:v,pause:O,seekTo:y,reverse:h,addMarkers:x}=Ee({videoRef:r,speed:c,playIndex:s.playIndex,videoCount:s.loadedVideoUrls.length,onEnded:({isTimelineEnded:p})=>u({type:p?"TIMELINE_ENDED":"ENDED"})});return m.useEffect(()=>{s.playerState==="INIT"&&(u({type:"LOADING",...t&&{payload:t}}),t&&x(re(t,u))),s.playerState==="LOADING"&&be({urls:i,onProgress:p=>{u({type:"LOADING_PROGRESS",payload:p}),l&&l(p)}}).then(({blobUrls:p})=>{u({type:"READY",payload:p}),o?.()}).catch(p=>{u({type:"ERROR",payload:p})}),s.playerState==="READY"&&n&&n(),s.playerState==="PLAYING"&&v(),s.playerState==="PAUSED"&&O(),s.playerState==="ENDED"&&(s.playDirection==="FORWARD"&&s.playIndex<s.loadedVideoUrls.length-1&&u({type:"PLAYING"}),s.playIndex>0&&u({type:"PLAYING"})),f?.({isPlaying:s.playerState==="PLAYING",isRewind:s.playDirection==="BACKWARD",playerState:s.playerState,currentTime:r.current?.currentTime})},[s.playerState]),{state:s,play:()=>{s.playDirection==="BACKWARD"&&(u({type:"REVERSE"}),h()),u({type:"PLAYING"})},pause:()=>u({type:"PAUSED"}),reverse:()=>u({type:"REVERSE"}),rewind:()=>{s.playDirection==="FORWARD"&&(u({type:"REVERSE"}),h()),u({type:"PLAYING"})},seekTo:y,moveToFirstFrame:()=>{s.playDirection==="BACKWARD"&&s.playerState==="PLAYING"&&y({time:r.current.duration,autoPlay:!0})}}},te=m.createContext(null);var ve="_1spdh1z0",_e="_1spdh1z1",Se="_1spdh1z2",K="_1spdh1z3";function ne({onPlay:r,onPause:t,onRewind:i}){const c=m.useContext(te);return A.jsxs("div",{className:ve,children:[A.jsx("p",{className:Se,children:c?.playDirection}),A.jsxs("div",{className:_e,children:[A.jsx("button",{className:K,type:"button",onClick:r,children:"Play"}),A.jsx("button",{className:K,type:"button",onClick:t,children:"Pause"}),A.jsx("button",{className:K,type:"button",onClick:i,children:"Rewind"})]})]})}var Te="_10oingv0",xe="_10oingv1",ge="_10oingv2";const De=m.memo(function({ref:t,url:i,loop:c,poster:l,onLoadedData:n}){return A.jsxs("div",{className:Te,children:[A.jsx("video",{className:xe,src:i,ref:t,loop:c,onLoadedData:n,muted:!0,playsInline:!0,preload:"metadata",poster:l},i),l&&A.jsx("div",{className:ge,style:{backgroundImage:`url(${l})`}})]})},(r,t)=>r.url===t.url&&r.poster===t.poster);var Ne="_14pkj7w0",Oe="_14pkj7w1";function Pe({speed:r,className:t,videoUrls:i,markers:c,controls:l,posters:n,onLoading:o,onLoaded:f,onReady:s,onStateChange:u,fullScreen:v,ref:O}){const y=m.useRef(null),{state:h,play:x,pause:p,rewind:P,seekTo:b,moveToFirstFrame:_}=Ae({ref:y,speed:r,videoUrls:i,markers:c,onLoading:o,onLoaded:f,onReady:s,onStateChange:u});return m.useImperativeHandle(O,()=>({videoElement:y.current||void 0,play:x,pause:p,rewind:P,seekTo:b})),A.jsx("div",{className:ye(Ne,v&&Oe,t),children:A.jsxs(te.Provider,{value:h,children:[A.jsx(De,{poster:n&&n[h.playIndex],ref:y,url:h.loadedVideoUrls[h.playIndex]||"",onLoadedData:()=>_()}),l&&A.jsx(ne,{onPlay:x,onPause:p,onRewind:P})]})})}const we={FORWARD:"FORWARD",BACKWARD:"BACKWARD",BOTH:"BOTH"},ke={CONTINUE:"CONTINUE",PAUSE:"PAUSE"};T.MARKER_ACTION=ke,T.MARKER_DIRECTION=we,T.VideoControl=ne,T.VideoTimestone=Pe,T.setupMarkers=re,Object.defineProperty(T,Symbol.toStringTag,{value:"Module"})});