react-video-timestone
Version:
A React component library for video timestone functionality
723 lines (722 loc) • 21.3 kB
JavaScript
import ue, { useRef as V, useState as le, useEffect as ae, useReducer as se, createContext as ce, useContext as fe, memo as pe, useImperativeHandle as de } from "react";
import './index.css';function me(r) {
return r && r.__esModule && Object.prototype.hasOwnProperty.call(r, "default") ? r.default : r;
}
var M = { exports: {} }, U = {};
/**
* @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 ee;
function ye() {
if (ee) return U;
ee = 1;
var r = Symbol.for("react.transitional.element"), t = Symbol.for("react.fragment");
function i(c, l, n) {
var a = null;
if (n !== void 0 && (a = "" + n), l.key !== void 0 && (a = "" + 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: a,
ref: l !== void 0 ? l : null,
props: n
};
}
return U.Fragment = t, U.jsx = i, U.jsxs = i, U;
}
var G = {};
/**
* @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 re;
function Ee() {
return re || (re = 1, process.env.NODE_ENV !== "production" && function() {
function r(e) {
if (e == null) return null;
if (typeof e == "function")
return e.$$typeof === _ ? null : e.displayName || e.name || null;
if (typeof e == "string") return e;
switch (e) {
case d:
return "Fragment";
case A:
return "Profiler";
case h:
return "StrictMode";
case x:
return "Suspense";
case k:
return "SuspenseList";
case N:
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 D:
return "Portal";
case Y:
return (e.displayName || "Context") + ".Provider";
case T:
return (e._context.displayName || "Context") + ".Consumer";
case I:
var o = e.render;
return e = e.displayName, e || (e = o.displayName || o.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
case g:
return o = e.displayName || null, o !== null ? o : r(e.type) || "Memo";
case b:
o = e._payload, e = e._init;
try {
return r(e(o));
} catch {
}
}
return null;
}
function t(e) {
return "" + e;
}
function i(e) {
try {
t(e);
var o = !1;
} catch {
o = !0;
}
if (o) {
o = console;
var p = o.error, y = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
return p.call(
o,
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
y
), t(e);
}
}
function c(e) {
if (e === d) return "<>";
if (typeof e == "object" && e !== null && e.$$typeof === b)
return "<...>";
try {
var o = r(e);
return o ? "<" + o + ">" : "<...>";
} catch {
return "<...>";
}
}
function l() {
var e = j.A;
return e === null ? null : e.getOwner();
}
function n() {
return Error("react-stack-top-frame");
}
function a(e) {
if (W.call(e, "key")) {
var o = Object.getOwnPropertyDescriptor(e, "key").get;
if (o && o.isReactWarning) return !1;
}
return e.key !== void 0;
}
function f(e, o) {
function p() {
K || (K = !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)",
o
));
}
p.isReactWarning = !0, Object.defineProperty(e, "key", {
get: p,
configurable: !0
});
}
function u() {
var e = r(this.type);
return H[e] || (H[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 s(e, o, p, y, w, O, $, q) {
return p = O.ref, e = {
$$typeof: R,
type: e,
key: o,
props: O,
_owner: w
}, (p !== void 0 ? p : null) !== null ? Object.defineProperty(e, "ref", {
enumerable: !1,
get: u
}) : 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: $
}), Object.defineProperty(e, "_debugTask", {
configurable: !1,
enumerable: !1,
writable: !0,
value: q
}), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
}
function S(e, o, p, y, w, O, $, q) {
var E = o.children;
if (E !== void 0)
if (y)
if (C(E)) {
for (y = 0; y < E.length; y++)
P(E[y]);
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 P(E);
if (W.call(o, "key")) {
E = r(e);
var L = Object.keys(o).filter(function(ie) {
return ie !== "key";
});
y = 0 < L.length ? "{key: someKey, " + L.join(": ..., ") + ": ...}" : "{key: someKey}", Q[E + y] || (L = 0 < L.length ? "{" + L.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} />`,
y,
E,
L,
E
), Q[E + y] = !0);
}
if (E = null, p !== void 0 && (i(p), E = "" + p), a(o) && (i(o.key), E = "" + o.key), "key" in o) {
p = {};
for (var B in o)
B !== "key" && (p[B] = o[B]);
} else p = o;
return E && f(
p,
typeof e == "function" ? e.displayName || e.name || "Unknown" : e
), s(
e,
E,
O,
w,
l(),
p,
$,
q
);
}
function P(e) {
typeof e == "object" && e !== null && e.$$typeof === R && e._store && (e._store.validated = 1);
}
var m = ue, R = Symbol.for("react.transitional.element"), D = Symbol.for("react.portal"), d = Symbol.for("react.fragment"), h = Symbol.for("react.strict_mode"), A = Symbol.for("react.profiler"), T = Symbol.for("react.consumer"), Y = Symbol.for("react.context"), I = Symbol.for("react.forward_ref"), x = Symbol.for("react.suspense"), k = Symbol.for("react.suspense_list"), g = Symbol.for("react.memo"), b = Symbol.for("react.lazy"), N = Symbol.for("react.activity"), _ = Symbol.for("react.client.reference"), j = m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, W = Object.prototype.hasOwnProperty, C = Array.isArray, F = console.createTask ? console.createTask : function() {
return null;
};
m = {
react_stack_bottom_frame: function(e) {
return e();
}
};
var K, H = {}, X = m.react_stack_bottom_frame.bind(
m,
n
)(), Z = F(c(n)), Q = {};
G.Fragment = d, G.jsx = function(e, o, p, y, w) {
var O = 1e4 > j.recentlyCreatedOwnerStacks++;
return S(
e,
o,
p,
!1,
y,
w,
O ? Error("react-stack-top-frame") : X,
O ? F(c(e)) : Z
);
}, G.jsxs = function(e, o, p, y, w) {
var O = 1e4 > j.recentlyCreatedOwnerStacks++;
return S(
e,
o,
p,
!0,
y,
w,
O ? Error("react-stack-top-frame") : X,
O ? F(c(e)) : Z
);
};
}()), G;
}
var te;
function Re() {
return te || (te = 1, process.env.NODE_ENV === "production" ? M.exports = ye() : M.exports = Ee()), M.exports;
}
var v = Re(), z = { exports: {} };
/*!
Copyright (c) 2018 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/
var ne;
function Ae() {
return ne || (ne = 1, function(r) {
(function() {
var t = {}.hasOwnProperty;
function i() {
for (var n = "", a = 0; a < arguments.length; a++) {
var f = arguments[a];
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 a = "";
for (var f in n)
t.call(n, f) && n[f] && (a = l(a, f));
return a;
}
function l(n, a) {
return a ? n ? n + " " + a : n + a : n;
}
r.exports ? (i.default = i, r.exports = i) : window.classNames = i;
})();
}(z)), z.exports;
}
var Se = Ae();
const Te = /* @__PURE__ */ me(Se), ve = (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;
}
}, be = ({
videoRef: r,
onEnded: t,
speed: i = 1,
videoCount: c,
playIndex: l
}) => {
const n = 33.333333333333336, a = V(null), f = V("FORWARD"), u = V(0), s = V(null), [S, P] = le([]);
function m() {
let A = null;
if (!r.current)
throw new Error("videoRef 가 존재하지 않습니다.");
u.current = r.current.currentTime;
function T() {
a.current && (cancelAnimationFrame(a.current), a.current = null);
}
function Y({
markers: x,
prevCurrentTime: k,
newCurrentTime: g
}) {
if (!x || x.length === 0)
return;
s.current && Math.abs(u.current - g) > 0.2 && (s.current = null);
const b = x.find((N) => {
if (typeof N?.videoIndex < "u" && l !== N.videoIndex)
return null;
const _ = f.current === "FORWARD", j = N.direction || "BOTH";
if (j === "FORWARD" && !_ || j === "BACKWARD" && _)
return null;
const W = Number(k.toFixed(2)), C = Number(N.time.toFixed(2)), F = Number(g.toFixed(2));
return _ && C > W && C <= F || !_ && F <= C && C < W ? N : null;
});
b && s.current !== b.label && (b.action === "PAUSE" && (b.triggerPause?.(), T()), b.callback?.(), s.current = b.label);
}
function I(x) {
const k = f.current === "FORWARD";
if (!r.current)
throw new Error("videoRef 가 존재하지 않습니다.");
if (A === null) {
A = x, a.current = requestAnimationFrame(I);
return;
}
const g = x - A;
if (g >= n) {
const b = g / 1e3 * i;
A = x;
const N = r.current.currentTime, _ = k ? r.current.currentTime + b : r.current.currentTime - b;
r.current.currentTime = _, Y({
markers: S,
prevCurrentTime: N,
newCurrentTime: _
}), (k ? r.current.duration > _ : 0 < _) ? a.current = requestAnimationFrame(I) : a.current && (T(), t && t({
isTimelineEnded: k ? l === c - 1 : l === 0
}));
} else
a.current = requestAnimationFrame(I);
}
a.current = requestAnimationFrame(I);
}
function R() {
a.current && (cancelAnimationFrame(a.current), a.current = null);
}
function D() {
f.current = f.current === "FORWARD" ? "BACKWARD" : "FORWARD";
}
function d({ time: A, autoPlay: T = !1 }) {
r.current && (R(), r.current.currentTime = A, T && m());
}
function h(A) {
P((T) => [...T, ...A]);
}
return ae(() => () => {
a.current && (cancelAnimationFrame(a.current), a.current = null);
}, []), {
play: m,
pause: R,
reverse: D,
seekTo: d,
addMarkers: h
};
}, De = (r, t) => r?.map((i) => ({
...i,
triggerPause: () => {
t({ type: "PAUSED" });
}
})) || [];
async function _e(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 Ne = async ({
urls: r,
onProgress: t,
onReady: i
}) => {
let c = 0;
const l = await _e(r), n = r.map(() => 0), a = await Promise.all(
r.map(async (s, S) => await f(s, S))
);
async function f(s, S) {
const m = await fetch(s, { method: "GET" });
return await new Response(
new ReadableStream({
start(D) {
const d = m.body?.getReader();
h();
function h() {
d?.read().then(({ done: A, value: T }) => {
if (A) {
D.close();
return;
}
n[S] = (n?.[S] ?? 0) + (T?.byteLength ?? 0), c = n.reduce((Y, I) => Y + I, 0) / l * 100, t && t(c), D.enqueue(T), h();
});
}
}
}),
{
status: 200,
headers: {
"Content-Type": "video/mp4"
}
}
).blob();
}
const u = a.map((s) => URL.createObjectURL(s));
return i && i(u), {
blobUrls: u,
cleanup: () => {
u.forEach((s) => URL.revokeObjectURL(s));
}
};
}, Oe = ({
ref: r,
markers: t,
videoUrls: i,
speed: c,
onLoading: l,
onReady: n,
onLoaded: a,
onStateChange: f
}) => {
const [u, s] = se(ve, {
loadingProgress: 0,
loadedVideoUrls: [],
playerState: "INIT",
playDirection: "FORWARD",
playIndex: 0,
markers: []
}), { play: S, pause: P, seekTo: m, reverse: R, addMarkers: D } = be({
videoRef: r,
speed: c,
playIndex: u.playIndex,
videoCount: u.loadedVideoUrls.length,
onEnded: ({ isTimelineEnded: d }) => s({ type: d ? "TIMELINE_ENDED" : "ENDED" })
});
return ae(() => {
u.playerState === "INIT" && (s({ type: "LOADING", ...t && { payload: t } }), t && D(De(t, s))), u.playerState === "LOADING" && Ne({
urls: i,
onProgress: (d) => {
s({ type: "LOADING_PROGRESS", payload: d }), l && l(d);
}
}).then(({ blobUrls: d }) => {
s({ type: "READY", payload: d }), a?.();
}).catch((d) => {
s({ type: "ERROR", payload: d });
}), u.playerState === "READY" && n && n(), u.playerState === "PLAYING" && S(), u.playerState === "PAUSED" && P(), u.playerState === "ENDED" && (u.playDirection === "FORWARD" && u.playIndex < u.loadedVideoUrls.length - 1 && s({ type: "PLAYING" }), u.playIndex > 0 && s({ type: "PLAYING" })), f?.({
isPlaying: u.playerState === "PLAYING",
isRewind: u.playDirection === "BACKWARD",
playerState: u.playerState,
currentTime: r.current?.currentTime
});
}, [u.playerState]), {
state: u,
play: () => {
u.playDirection === "BACKWARD" && (s({ type: "REVERSE" }), R()), s({ type: "PLAYING" });
},
pause: () => s({ type: "PAUSED" }),
reverse: () => s({ type: "REVERSE" }),
rewind: () => {
u.playDirection === "FORWARD" && (s({ type: "REVERSE" }), R()), s({ type: "PLAYING" });
},
seekTo: m,
moveToFirstFrame: () => {
u.playDirection === "BACKWARD" && u.playerState === "PLAYING" && m({
time: r.current.duration,
autoPlay: !0
});
}
};
}, oe = ce(null);
var Pe = "_1spdh1z0", he = "_1spdh1z1", xe = "_1spdh1z2", J = "_1spdh1z3";
function Ie({
onPlay: r,
onPause: t,
onRewind: i
}) {
const c = fe(oe);
return /* @__PURE__ */ v.jsxs("div", { className: Pe, children: [
/* @__PURE__ */ v.jsx("p", { className: xe, children: c?.playDirection }),
/* @__PURE__ */ v.jsxs("div", { className: he, children: [
/* @__PURE__ */ v.jsx("button", { className: J, type: "button", onClick: r, children: "Play" }),
/* @__PURE__ */ v.jsx(
"button",
{
className: J,
type: "button",
onClick: t,
children: "Pause"
}
),
/* @__PURE__ */ v.jsx(
"button",
{
className: J,
type: "button",
onClick: i,
children: "Rewind"
}
)
] })
] });
}
var we = "_10oingv0", ke = "_10oingv1", ge = "_10oingv2";
const je = pe(
function({ ref: t, url: i, loop: c, poster: l, onLoadedData: n }) {
return /* @__PURE__ */ v.jsxs("div", { className: we, children: [
/* @__PURE__ */ v.jsx(
"video",
{
className: ke,
src: i,
ref: t,
loop: c,
onLoadedData: n,
muted: !0,
playsInline: !0,
preload: "metadata",
poster: l
},
i
),
l && /* @__PURE__ */ v.jsx(
"div",
{
className: ge,
style: { backgroundImage: `url(${l})` }
}
)
] });
},
(r, t) => r.url === t.url && r.poster === t.poster
);
var Ce = "_14pkj7w0", Fe = "_14pkj7w1";
function Ye({
speed: r,
className: t,
videoUrls: i,
markers: c,
controls: l,
posters: n,
onLoading: a,
onLoaded: f,
onReady: u,
onStateChange: s,
fullScreen: S,
ref: P
}) {
const m = V(null), { state: R, play: D, pause: d, rewind: h, seekTo: A, moveToFirstFrame: T } = Oe({
ref: m,
speed: r,
videoUrls: i,
markers: c,
onLoading: a,
onLoaded: f,
onReady: u,
onStateChange: s
});
return de(P, () => ({
videoElement: m.current || void 0,
play: D,
pause: d,
rewind: h,
seekTo: A
})), /* @__PURE__ */ v.jsx(
"div",
{
className: Te(
Ce,
S && Fe,
t
),
children: /* @__PURE__ */ v.jsxs(oe.Provider, { value: R, children: [
/* @__PURE__ */ v.jsx(
je,
{
poster: n && n[R.playIndex],
ref: m,
url: R.loadedVideoUrls[R.playIndex] || "",
onLoadedData: () => T()
}
),
l && /* @__PURE__ */ v.jsx(Ie, { onPlay: D, onPause: d, onRewind: h })
] })
}
);
}
const We = {
FORWARD: "FORWARD",
BACKWARD: "BACKWARD",
BOTH: "BOTH"
}, Ue = {
CONTINUE: "CONTINUE",
PAUSE: "PAUSE"
};
export {
Ue as MARKER_ACTION,
We as MARKER_DIRECTION,
Ie as VideoControl,
Ye as VideoTimestone,
De as setupMarkers
};