@ttt-productions/media-viewer 0.2.9 → 0.2.11
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/audio-viewer.d.ts +2 -2
- package/dist/audio-viewer.d.ts.map +1 -1
- package/dist/audio-viewer.js +61 -4
- package/dist/audio-viewer.js.map +1 -1
- package/dist/fallback.d.ts +11 -1
- package/dist/fallback.d.ts.map +1 -1
- package/dist/fallback.js +14 -1
- package/dist/fallback.js.map +1 -1
- package/dist/image-viewer.d.ts +2 -2
- package/dist/image-viewer.d.ts.map +1 -1
- package/dist/image-viewer.js +72 -9
- package/dist/image-viewer.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/media-viewer.d.ts +2 -2
- package/dist/media-viewer.d.ts.map +1 -1
- package/dist/media-viewer.js +70 -15
- package/dist/media-viewer.js.map +1 -1
- package/dist/types.d.ts +52 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/video-viewer.d.ts +2 -2
- package/dist/video-viewer.d.ts.map +1 -1
- package/dist/video-viewer.js +80 -6
- package/dist/video-viewer.js.map +1 -1
- package/package.json +7 -4
- package/src/styles/media-viewer.css +95 -0
package/dist/audio-viewer.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function AudioViewer(props:
|
|
1
|
+
import type { AudioViewerProps } from "./types.js";
|
|
2
|
+
export declare function AudioViewer(props: AudioViewerProps): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=audio-viewer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio-viewer.d.ts","sourceRoot":"","sources":["../src/audio-viewer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"audio-viewer.d.ts","sourceRoot":"","sources":["../src/audio-viewer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,2CA6IlD"}
|
package/dist/audio-viewer.js
CHANGED
|
@@ -1,9 +1,57 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
+
import { useInView } from "react-intersection-observer";
|
|
4
|
+
import { Skeleton } from "@ttt-productions/ui-core";
|
|
3
5
|
export function AudioViewer(props) {
|
|
4
|
-
const { url, className, mediaClassName, controls = true, autoPlay, loop, } = props;
|
|
6
|
+
const { url, className, mediaClassName, controls = true, autoPlay, loop = false, lazy = true, skeleton: showSkeleton = true, priority = false, preload = "metadata", onLoad, onLoadChange, onError, fallback, } = props;
|
|
7
|
+
const [isLoaded, setIsLoaded] = React.useState(false);
|
|
8
|
+
const [hasError, setHasError] = React.useState(false);
|
|
9
|
+
const [shouldLoad, setShouldLoad] = React.useState(priority || !lazy);
|
|
5
10
|
const audioRef = React.useRef(null);
|
|
6
|
-
|
|
11
|
+
const { ref: inViewRef, inView } = useInView({
|
|
12
|
+
triggerOnce: false,
|
|
13
|
+
threshold: 0.01,
|
|
14
|
+
skip: priority || shouldLoad,
|
|
15
|
+
rootMargin: "100px",
|
|
16
|
+
});
|
|
17
|
+
// Load when in view
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
if (inView && !shouldLoad) {
|
|
20
|
+
setShouldLoad(true);
|
|
21
|
+
}
|
|
22
|
+
}, [inView, shouldLoad]);
|
|
23
|
+
// Accordion compatibility: delayed auto-load on mount
|
|
24
|
+
React.useEffect(() => {
|
|
25
|
+
if (priority || shouldLoad)
|
|
26
|
+
return;
|
|
27
|
+
const timer = setTimeout(() => {
|
|
28
|
+
if (!shouldLoad)
|
|
29
|
+
setShouldLoad(true);
|
|
30
|
+
}, 100);
|
|
31
|
+
return () => clearTimeout(timer);
|
|
32
|
+
}, [url, priority, shouldLoad]);
|
|
33
|
+
// Report loading state
|
|
34
|
+
React.useEffect(() => {
|
|
35
|
+
onLoadChange?.(!isLoaded);
|
|
36
|
+
}, [isLoaded, onLoadChange]);
|
|
37
|
+
// Reset on URL change
|
|
38
|
+
React.useEffect(() => {
|
|
39
|
+
setHasError(false);
|
|
40
|
+
setIsLoaded(false);
|
|
41
|
+
}, [url]);
|
|
42
|
+
const handleLoadedData = React.useCallback(() => {
|
|
43
|
+
setIsLoaded(true);
|
|
44
|
+
onLoad?.();
|
|
45
|
+
}, [onLoad]);
|
|
46
|
+
const handleCanPlay = React.useCallback(() => {
|
|
47
|
+
setIsLoaded(true);
|
|
48
|
+
}, []);
|
|
49
|
+
const handleError = React.useCallback(() => {
|
|
50
|
+
setHasError(true);
|
|
51
|
+
setIsLoaded(true); // Stop skeleton on error
|
|
52
|
+
onError?.();
|
|
53
|
+
}, [onError]);
|
|
54
|
+
// Tap-to-toggle when controls are off
|
|
7
55
|
const togglePlay = React.useCallback(() => {
|
|
8
56
|
const el = audioRef.current;
|
|
9
57
|
if (!el)
|
|
@@ -21,6 +69,15 @@ export function AudioViewer(props) {
|
|
|
21
69
|
togglePlay();
|
|
22
70
|
}
|
|
23
71
|
}, [controls, togglePlay]);
|
|
24
|
-
|
|
72
|
+
if (hasError) {
|
|
73
|
+
if (fallback)
|
|
74
|
+
return _jsx(_Fragment, { children: fallback });
|
|
75
|
+
return (_jsx("div", { className: className, children: _jsx("div", { className: "mv-audio-error", children: _jsx("p", { children: "Failed to load audio" }) }) }));
|
|
76
|
+
}
|
|
77
|
+
return (_jsx("div", { ref: inViewRef, className: className, role: controls ? undefined : "button", tabIndex: controls ? undefined : 0, "aria-label": controls ? undefined : "Toggle audio playback", onClick: controls ? undefined : togglePlay, onKeyDown: controls ? undefined : onKeyDown, style: { position: "relative", width: "100%", outline: "none" }, children: !shouldLoad ? (showSkeleton ? _jsx(Skeleton, { style: { height: "3.5rem", width: "100%" } }) : null) : (_jsxs(_Fragment, { children: [showSkeleton && !isLoaded && (_jsx(Skeleton, { style: { position: "absolute", inset: 0, height: "3.5rem", width: "100%" } })), _jsx("audio", { ref: audioRef, src: url, className: mediaClassName, controls: controls, autoPlay: autoPlay, loop: loop, preload: preload, onLoadedData: handleLoadedData, onCanPlay: handleCanPlay, onError: handleError, style: {
|
|
78
|
+
width: "100%",
|
|
79
|
+
opacity: isLoaded ? 1 : 0,
|
|
80
|
+
transition: "opacity 300ms ease",
|
|
81
|
+
} })] })) }));
|
|
25
82
|
}
|
|
26
83
|
//# sourceMappingURL=audio-viewer.js.map
|
package/dist/audio-viewer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audio-viewer.js","sourceRoot":"","sources":["../src/audio-viewer.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"audio-viewer.js","sourceRoot":"","sources":["../src/audio-viewer.tsx"],"names":[],"mappings":"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"}
|
package/dist/fallback.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FallbackMode } from "./types";
|
|
1
|
+
import type { FallbackMode } from "./types.js";
|
|
2
2
|
export declare function MediaFallbackLink(props: {
|
|
3
3
|
url: string;
|
|
4
4
|
filename?: string;
|
|
@@ -6,4 +6,14 @@ export declare function MediaFallbackLink(props: {
|
|
|
6
6
|
label?: string;
|
|
7
7
|
}): import("react/jsx-runtime").JSX.Element;
|
|
8
8
|
export declare function shouldShowFallback(mode: FallbackMode | undefined): boolean;
|
|
9
|
+
/** Empty state: no URL provided */
|
|
10
|
+
export declare function EmptyFallback(props: {
|
|
11
|
+
isCircular?: boolean;
|
|
12
|
+
className?: string;
|
|
13
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
/** Error state: failed to load */
|
|
15
|
+
export declare function ErrorFallback(props: {
|
|
16
|
+
isCircular?: boolean;
|
|
17
|
+
className?: string;
|
|
18
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
9
19
|
//# sourceMappingURL=fallback.d.ts.map
|
package/dist/fallback.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../src/fallback.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../src/fallback.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,2CAcA;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,OAAO,CAE1E;AAED,mCAAmC;AACnC,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAehF;AAED,kCAAkC;AAClC,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,2CAchF"}
|
package/dist/fallback.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
export function MediaFallbackLink(props) {
|
|
3
3
|
const { url, filename, className, label } = props;
|
|
4
4
|
return (_jsx("a", { href: url, target: "_blank", rel: "noreferrer", download: filename || undefined, className: className, children: label ?? "Download" }));
|
|
@@ -6,4 +6,17 @@ export function MediaFallbackLink(props) {
|
|
|
6
6
|
export function shouldShowFallback(mode) {
|
|
7
7
|
return mode !== "none";
|
|
8
8
|
}
|
|
9
|
+
/** Empty state: no URL provided */
|
|
10
|
+
export function EmptyFallback(props) {
|
|
11
|
+
const { isCircular, className } = props;
|
|
12
|
+
if (isCircular) {
|
|
13
|
+
return (_jsx("div", { className: className ?? "mv-avatar-fallback", children: "?" }));
|
|
14
|
+
}
|
|
15
|
+
return (_jsx("div", { className: className ?? "mv-empty-fallback", children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }), _jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" })] }) }));
|
|
16
|
+
}
|
|
17
|
+
/** Error state: failed to load */
|
|
18
|
+
export function ErrorFallback(props) {
|
|
19
|
+
const { isCircular, className } = props;
|
|
20
|
+
return (_jsx("div", { className: className ?? "mv-error-fallback", style: isCircular ? { borderRadius: "50%" } : undefined, children: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z" }), _jsx("path", { d: "M14 2v4a2 2 0 0 0 2 2h4" }), _jsx("line", { x1: "9", x2: "15", y1: "15", y2: "9" })] }) }));
|
|
21
|
+
}
|
|
9
22
|
//# sourceMappingURL=fallback.js.map
|
package/dist/fallback.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fallback.js","sourceRoot":"","sources":["../src/fallback.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,iBAAiB,CAAC,KAKjC;IACC,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAElD,OAAO,CACL,YACE,IAAI,EAAE,GAAG,EACT,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAChB,QAAQ,EAAE,QAAQ,IAAI,SAAS,EAC/B,SAAS,EAAE,SAAS,YAEnB,KAAK,IAAI,UAAU,GAClB,CACL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAA8B;IAC/D,OAAO,IAAI,KAAK,MAAM,CAAC;AACzB,CAAC"}
|
|
1
|
+
{"version":3,"file":"fallback.js","sourceRoot":"","sources":["../src/fallback.tsx"],"names":[],"mappings":";AAEA,MAAM,UAAU,iBAAiB,CAAC,KAKjC;IACC,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAElD,OAAO,CACL,YACE,IAAI,EAAE,GAAG,EACT,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,EAChB,QAAQ,EAAE,QAAQ,IAAI,SAAS,EAC/B,SAAS,EAAE,SAAS,YAEnB,KAAK,IAAI,UAAU,GAClB,CACL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAA8B;IAC/D,OAAO,IAAI,KAAK,MAAM,CAAC;AACzB,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,aAAa,CAAC,KAAmD;IAC/E,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACxC,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CACL,cAAK,SAAS,EAAE,SAAS,IAAI,oBAAoB,kBAAS,CAC3D,CAAC;IACJ,CAAC;IACD,OAAO,CACL,cAAK,SAAS,EAAE,SAAS,IAAI,mBAAmB,YAC9C,eAAK,KAAK,EAAC,4BAA4B,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,GAAG,EAAC,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,aAC/K,eAAM,CAAC,EAAC,4DAA4D,GAAG,EACvE,eAAM,CAAC,EAAC,yBAAyB,GAAG,IAChC,GACF,CACP,CAAC;AACJ,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,aAAa,CAAC,KAAmD;IAC/E,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACxC,OAAO,CACL,cACE,SAAS,EAAE,SAAS,IAAI,mBAAmB,EAC3C,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,YAEvD,eAAK,KAAK,EAAC,4BAA4B,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,IAAI,EAAC,OAAO,EAAC,WAAW,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,WAAW,EAAC,GAAG,EAAC,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,aAC/K,eAAM,CAAC,EAAC,4DAA4D,GAAG,EACvE,eAAM,CAAC,EAAC,yBAAyB,GAAG,EACpC,eAAM,EAAE,EAAC,GAAG,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,IAAI,EAAC,EAAE,EAAC,GAAG,GAAG,IAClC,GACF,CACP,CAAC;AACJ,CAAC"}
|
package/dist/image-viewer.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function ImageViewer(props:
|
|
1
|
+
import type { ImageViewerProps } from "./types.js";
|
|
2
|
+
export declare function ImageViewer(props: ImageViewerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
3
3
|
//# sourceMappingURL=image-viewer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-viewer.d.ts","sourceRoot":"","sources":["../src/image-viewer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"image-viewer.d.ts","sourceRoot":"","sources":["../src/image-viewer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,kDA8IlD"}
|
package/dist/image-viewer.js
CHANGED
|
@@ -1,8 +1,58 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
+
import { useInView } from "react-intersection-observer";
|
|
4
|
+
import { Skeleton } from "@ttt-productions/ui-core";
|
|
3
5
|
export function ImageViewer(props) {
|
|
4
|
-
const { url, alt, className, mediaClassName, enableZoom = true } = props;
|
|
6
|
+
const { url, alt, className, mediaClassName, enableZoom = true, lazy = true, unloadOnExit = false, priority = false, skeleton: showSkeleton = true, isCircular = false, preventGestures = true, onLoad, onError, fallback, } = props;
|
|
7
|
+
const [isLoaded, setIsLoaded] = React.useState(false);
|
|
8
|
+
const [hasError, setHasError] = React.useState(false);
|
|
9
|
+
const [shouldLoad, setShouldLoad] = React.useState(priority || !lazy);
|
|
5
10
|
const [zoomed, setZoomed] = React.useState(false);
|
|
11
|
+
const imgRef = React.useRef(null);
|
|
12
|
+
const { ref: inViewRef, inView } = useInView({
|
|
13
|
+
triggerOnce: !unloadOnExit,
|
|
14
|
+
threshold: 0.01,
|
|
15
|
+
rootMargin: "50px",
|
|
16
|
+
skip: priority || !lazy,
|
|
17
|
+
});
|
|
18
|
+
// Load when entering viewport
|
|
19
|
+
React.useEffect(() => {
|
|
20
|
+
if (inView && !shouldLoad) {
|
|
21
|
+
setShouldLoad(true);
|
|
22
|
+
}
|
|
23
|
+
// Unload when leaving viewport (if enabled)
|
|
24
|
+
if (!inView && unloadOnExit && shouldLoad && !priority) {
|
|
25
|
+
setShouldLoad(false);
|
|
26
|
+
setIsLoaded(false);
|
|
27
|
+
}
|
|
28
|
+
}, [inView, shouldLoad, unloadOnExit, priority]);
|
|
29
|
+
// Reset error state when URL changes
|
|
30
|
+
React.useEffect(() => {
|
|
31
|
+
setHasError(false);
|
|
32
|
+
setIsLoaded(false);
|
|
33
|
+
}, [url]);
|
|
34
|
+
const handleLoad = React.useCallback(() => {
|
|
35
|
+
setIsLoaded(true);
|
|
36
|
+
onLoad?.();
|
|
37
|
+
}, [onLoad]);
|
|
38
|
+
const handleError = React.useCallback(() => {
|
|
39
|
+
setHasError(true);
|
|
40
|
+
onError?.();
|
|
41
|
+
}, [onError]);
|
|
42
|
+
// iOS: prevent multi-touch zoom gestures on the image
|
|
43
|
+
React.useEffect(() => {
|
|
44
|
+
const img = imgRef.current;
|
|
45
|
+
if (!img || !preventGestures)
|
|
46
|
+
return;
|
|
47
|
+
const prevent = (e) => {
|
|
48
|
+
if (e.touches.length > 1)
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
};
|
|
51
|
+
img.addEventListener("touchstart", prevent, { passive: false });
|
|
52
|
+
return () => {
|
|
53
|
+
img.removeEventListener("touchstart", prevent);
|
|
54
|
+
};
|
|
55
|
+
}, [preventGestures, shouldLoad]);
|
|
6
56
|
const toggleZoom = React.useCallback(() => {
|
|
7
57
|
if (!enableZoom)
|
|
8
58
|
return;
|
|
@@ -16,12 +66,25 @@ export function ImageViewer(props) {
|
|
|
16
66
|
toggleZoom();
|
|
17
67
|
}
|
|
18
68
|
}, [enableZoom, toggleZoom]);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
69
|
+
if (hasError) {
|
|
70
|
+
return fallback ? _jsx(_Fragment, { children: fallback }) : null;
|
|
71
|
+
}
|
|
72
|
+
const wrapperStyle = isCircular
|
|
73
|
+
? { borderRadius: "50%", overflow: "hidden" }
|
|
74
|
+
: {};
|
|
75
|
+
return (_jsxs("div", { ref: inViewRef, className: className, role: enableZoom ? "button" : undefined, tabIndex: enableZoom ? 0 : undefined, "aria-pressed": enableZoom ? zoomed : undefined, "aria-label": enableZoom ? (zoomed ? "Zoom out image" : "Zoom in image") : undefined, onClick: toggleZoom, onKeyDown: onKeyDown, style: { position: "relative", width: "100%", height: "100%", outline: "none", ...wrapperStyle }, children: [showSkeleton && !isLoaded && shouldLoad && (_jsx(Skeleton, { style: { position: "absolute", inset: 0, width: "100%", height: "100%" } })), shouldLoad && (_jsx("img", { ref: imgRef, src: url, alt: alt ?? "", draggable: false, className: mediaClassName, onLoad: handleLoad, onError: handleError, loading: priority ? "eager" : "lazy", decoding: "async", style: {
|
|
76
|
+
maxWidth: "100%",
|
|
77
|
+
maxHeight: "100%",
|
|
78
|
+
width: "100%",
|
|
79
|
+
height: "100%",
|
|
80
|
+
objectFit: "cover",
|
|
81
|
+
opacity: isLoaded ? 1 : 0,
|
|
82
|
+
transition: "opacity 300ms ease, transform 150ms ease",
|
|
83
|
+
transform: zoomed ? "scale(1.5)" : "scale(1)",
|
|
84
|
+
cursor: enableZoom ? (zoomed ? "zoom-out" : "zoom-in") : undefined,
|
|
85
|
+
WebkitUserSelect: "none",
|
|
86
|
+
WebkitTouchCallout: "none",
|
|
87
|
+
WebkitTapHighlightColor: "transparent",
|
|
88
|
+
} }))] }));
|
|
26
89
|
}
|
|
27
90
|
//# sourceMappingURL=image-viewer.js.map
|
package/dist/image-viewer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-viewer.js","sourceRoot":"","sources":["../src/image-viewer.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"image-viewer.js","sourceRoot":"","sources":["../src/image-viewer.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAGpD,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,MAAM,EACJ,GAAG,EACH,GAAG,EACH,SAAS,EACT,cAAc,EACd,UAAU,GAAG,IAAI,EACjB,IAAI,GAAG,IAAI,EACX,YAAY,GAAG,KAAK,EACpB,QAAQ,GAAG,KAAK,EAChB,QAAQ,EAAE,YAAY,GAAG,IAAI,EAC7B,UAAU,GAAG,KAAK,EAClB,eAAe,GAAG,IAAI,EACtB,MAAM,EACN,OAAO,EACP,QAAQ,GACT,GAAG,KAAK,CAAC;IAEV,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAmB,IAAI,CAAC,CAAC;IAEpD,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;QAC3C,WAAW,EAAE,CAAC,YAAY;QAC1B,SAAS,EAAE,IAAI;QACf,UAAU,EAAE,MAAM;QAClB,IAAI,EAAE,QAAQ,IAAI,CAAC,IAAI;KACxB,CAAC,CAAC;IAEH,8BAA8B;IAC9B,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1B,aAAa,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QACD,4CAA4C;QAC5C,IAAI,CAAC,MAAM,IAAI,YAAY,IAAI,UAAU,IAAI,CAAC,QAAQ,EAAE,CAAC;YACvD,aAAa,CAAC,KAAK,CAAC,CAAC;YACrB,WAAW,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEjD,qCAAqC;IACrC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,WAAW,CAAC,KAAK,CAAC,CAAC;QACnB,WAAW,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEV,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QACxC,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,MAAM,EAAE,EAAE,CAAC;IACb,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QACzC,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,OAAO,EAAE,EAAE,CAAC;IACd,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,sDAAsD;IACtD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC;QAC3B,IAAI,CAAC,GAAG,IAAI,CAAC,eAAe;YAAE,OAAO;QAErC,MAAM,OAAO,GAAG,CAAC,CAAa,EAAE,EAAE;YAChC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,CAAC,CAAC,cAAc,EAAE,CAAC;QAC/C,CAAC,CAAC;QAEF,GAAG,CAAC,gBAAgB,CAAC,YAAY,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,OAAO,GAAG,EAAE;YACV,GAAG,CAAC,mBAAmB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACjD,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC,CAAC;IAElC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QACxC,IAAI,CAAC,UAAU;YAAE,OAAO;QACxB,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACvB,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;IAEjB,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CACjC,CAAC,CAAsB,EAAE,EAAE;QACzB,IAAI,CAAC,UAAU;YAAE,OAAO;QACxB,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;YACvC,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,UAAU,EAAE,CAAC;QACf,CAAC;IACH,CAAC,EACD,CAAC,UAAU,EAAE,UAAU,CAAC,CACzB,CAAC;IAEF,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,QAAQ,CAAC,CAAC,CAAC,4BAAG,QAAQ,GAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3C,CAAC;IAED,MAAM,YAAY,GAAwB,UAAU;QAClD,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE;QAC7C,CAAC,CAAC,EAAE,CAAC;IAEP,OAAO,CACL,eACE,GAAG,EAAE,SAAS,EACd,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,EACvC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,kBACtB,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,gBACjC,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS,EAClF,OAAO,EAAE,UAAU,EACnB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,aAE/F,YAAY,IAAI,CAAC,QAAQ,IAAI,UAAU,IAAI,CAC1C,KAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAI,CACvF,EACA,UAAU,IAAI,CACb,cACE,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,IAAI,EAAE,EACd,SAAS,EAAE,KAAK,EAChB,SAAS,EAAE,cAAc,EACzB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,EACpC,QAAQ,EAAC,OAAO,EAChB,KAAK,EAAE;oBACL,QAAQ,EAAE,MAAM;oBAChB,SAAS,EAAE,MAAM;oBACjB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,MAAM;oBACd,SAAS,EAAE,OAAO;oBAClB,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBACzB,UAAU,EAAE,0CAA0C;oBACtD,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU;oBAC7C,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;oBAClE,gBAAgB,EAAE,MAAM;oBACxB,kBAAkB,EAAE,MAAM;oBAC1B,uBAAuB,EAAE,aAAa;iBAChB,GACxB,CACH,IACG,CACP,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { MediaViewer, MediaPreview } from "./media-viewer";
|
|
2
|
-
export
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
1
|
+
export { MediaViewer, MediaPreview } from "./media-viewer.js";
|
|
2
|
+
export { ImageViewer } from "./image-viewer.js";
|
|
3
|
+
export { VideoViewer } from "./video-viewer.js";
|
|
4
|
+
export { AudioViewer } from "./audio-viewer.js";
|
|
5
|
+
export { MediaFallbackLink, shouldShowFallback, EmptyFallback, ErrorFallback } from "./fallback.js";
|
|
6
|
+
export type { MediaViewerType, FallbackMode, BaseMediaProps, ImageViewerProps, VideoViewerProps, AudioViewerProps, MediaPreviewProps, MediaViewerProps, } from "./types.js";
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEpG,YAAY,EACV,eAAe,EACf,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { MediaViewer, MediaPreview } from "./media-viewer";
|
|
2
|
-
export { ImageViewer } from "./image-viewer";
|
|
3
|
-
export { VideoViewer } from "./video-viewer";
|
|
4
|
-
export { AudioViewer } from "./audio-viewer";
|
|
5
|
-
export { MediaFallbackLink, shouldShowFallback } from "./fallback";
|
|
1
|
+
export { MediaViewer, MediaPreview } from "./media-viewer.js";
|
|
2
|
+
export { ImageViewer } from "./image-viewer.js";
|
|
3
|
+
export { VideoViewer } from "./video-viewer.js";
|
|
4
|
+
export { AudioViewer } from "./audio-viewer.js";
|
|
5
|
+
export { MediaFallbackLink, shouldShowFallback, EmptyFallback, ErrorFallback } from "./fallback.js";
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/media-viewer.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function MediaViewer(props:
|
|
1
|
+
import type { MediaPreviewProps } from "./types.js";
|
|
2
|
+
export declare function MediaViewer(props: MediaPreviewProps): import("react/jsx-runtime").JSX.Element | null;
|
|
3
3
|
/** Back-compat alias */
|
|
4
4
|
export declare const MediaPreview: typeof MediaViewer;
|
|
5
5
|
//# sourceMappingURL=media-viewer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-viewer.d.ts","sourceRoot":"","sources":["../src/media-viewer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"media-viewer.d.ts","sourceRoot":"","sources":["../src/media-viewer.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAiC,MAAM,YAAY,CAAC;AAoBnF,wBAAgB,WAAW,CAAC,KAAK,EAAE,iBAAiB,kDAwJnD;AAED,wBAAwB;AACxB,eAAO,MAAM,YAAY,oBAAc,CAAC"}
|
package/dist/media-viewer.js
CHANGED
|
@@ -1,26 +1,81 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
2
3
|
import { getSimplifiedMediaType } from "@ttt-productions/media-contracts";
|
|
3
|
-
import { MediaFallbackLink, shouldShowFallback } from "./fallback";
|
|
4
|
-
import { ImageViewer } from "./image-viewer";
|
|
5
|
-
import { VideoViewer } from "./video-viewer";
|
|
6
|
-
import { AudioViewer } from "./audio-viewer";
|
|
4
|
+
import { MediaFallbackLink, shouldShowFallback, EmptyFallback, ErrorFallback } from "./fallback.js";
|
|
5
|
+
import { ImageViewer } from "./image-viewer.js";
|
|
6
|
+
import { VideoViewer } from "./video-viewer.js";
|
|
7
|
+
import { AudioViewer } from "./audio-viewer.js";
|
|
7
8
|
function inferType(props) {
|
|
8
|
-
if (props.type)
|
|
9
|
-
|
|
9
|
+
if (props.type) {
|
|
10
|
+
// Handle MIME strings like "image/png" -> "image"
|
|
11
|
+
const primary = typeof props.type === "string" ? props.type.split("/")[0] : props.type;
|
|
12
|
+
if (primary === "image" || primary === "video" || primary === "audio")
|
|
13
|
+
return primary;
|
|
14
|
+
if (primary === "other")
|
|
15
|
+
return "other";
|
|
16
|
+
}
|
|
10
17
|
const hint = props.mime ?? props.name ?? props.url;
|
|
18
|
+
if (!hint)
|
|
19
|
+
return "other";
|
|
11
20
|
const simplified = getSimplifiedMediaType(hint);
|
|
12
21
|
return simplified;
|
|
13
22
|
}
|
|
14
23
|
export function MediaViewer(props) {
|
|
15
|
-
const { url, className,
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
const { url, alt, type, className, unloadOnExit, isCircular = false, priority, skeleton, lazy, controls, autoPlay, muted, loop, posterUrl, preload, onLoad, onError, onLoadChange, fallbackMode = "link", fallbackLabel, filename, mime, name, } = props;
|
|
25
|
+
const [hasError, setHasError] = React.useState(false);
|
|
26
|
+
const [sourceUrl, setSourceUrl] = React.useState(null);
|
|
27
|
+
// Handle string / Blob / File / null URLs
|
|
28
|
+
React.useEffect(() => {
|
|
29
|
+
setHasError(false);
|
|
30
|
+
let objectUrl = null;
|
|
31
|
+
if (typeof url === "string") {
|
|
32
|
+
setSourceUrl(url);
|
|
33
|
+
}
|
|
34
|
+
else if (url instanceof Blob) {
|
|
35
|
+
objectUrl = URL.createObjectURL(url);
|
|
36
|
+
setSourceUrl(objectUrl);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
setSourceUrl(null);
|
|
40
|
+
}
|
|
41
|
+
return () => {
|
|
42
|
+
if (objectUrl)
|
|
43
|
+
URL.revokeObjectURL(objectUrl);
|
|
44
|
+
};
|
|
45
|
+
}, [url]);
|
|
46
|
+
const handleError = React.useCallback(() => {
|
|
47
|
+
setHasError(true);
|
|
48
|
+
onError?.();
|
|
49
|
+
}, [onError]);
|
|
50
|
+
const circularStyle = isCircular
|
|
51
|
+
? { borderRadius: "50%", overflow: "hidden" }
|
|
52
|
+
: {};
|
|
53
|
+
const wrapperStyle = {
|
|
54
|
+
position: "relative",
|
|
55
|
+
width: "100%",
|
|
56
|
+
height: "100%",
|
|
57
|
+
...circularStyle,
|
|
58
|
+
};
|
|
59
|
+
// No URL -> empty fallback
|
|
60
|
+
if (!sourceUrl) {
|
|
61
|
+
return (_jsx("div", { className: className, style: wrapperStyle, children: _jsx(EmptyFallback, { isCircular: isCircular }) }));
|
|
62
|
+
}
|
|
63
|
+
// Error -> error fallback
|
|
64
|
+
if (hasError) {
|
|
65
|
+
return (_jsx("div", { className: className, style: wrapperStyle, children: _jsx(ErrorFallback, { isCircular: isCircular }) }));
|
|
66
|
+
}
|
|
67
|
+
const t = inferType({ type, mime, name, url: sourceUrl });
|
|
68
|
+
if (t === "image") {
|
|
69
|
+
return (_jsx("div", { className: className, style: wrapperStyle, children: _jsx(ImageViewer, { url: sourceUrl, alt: alt, lazy: lazy, priority: priority, skeleton: skeleton, unloadOnExit: unloadOnExit, isCircular: isCircular, onLoad: onLoad, onError: handleError, fallback: _jsx(ErrorFallback, { isCircular: isCircular }) }) }));
|
|
70
|
+
}
|
|
71
|
+
if (t === "video") {
|
|
72
|
+
return (_jsx("div", { className: className, style: wrapperStyle, children: _jsx(VideoViewer, { url: sourceUrl, lazy: lazy, priority: priority, skeleton: skeleton, unloadOnExit: unloadOnExit, controls: controls, autoPlay: autoPlay, muted: muted, loop: loop, posterUrl: posterUrl, preload: preload, onLoad: onLoad, onError: handleError }) }));
|
|
73
|
+
}
|
|
74
|
+
if (t === "audio") {
|
|
75
|
+
return (_jsx("div", { className: className, style: wrapperStyle, children: _jsx(AudioViewer, { url: sourceUrl, lazy: lazy, priority: priority, skeleton: skeleton, controls: controls, autoPlay: autoPlay, loop: loop, preload: preload, onLoad: onLoad, onLoadChange: onLoadChange, onError: handleError }) }));
|
|
76
|
+
}
|
|
77
|
+
// Unknown type -> fallback link
|
|
78
|
+
return shouldShowFallback(fallbackMode) ? (_jsx("div", { className: className, style: wrapperStyle, children: _jsx(MediaFallbackLink, { url: sourceUrl, filename: filename, label: fallbackLabel ?? "Download" }) })) : null;
|
|
24
79
|
}
|
|
25
80
|
/** Back-compat alias */
|
|
26
81
|
export const MediaPreview = MediaViewer;
|
package/dist/media-viewer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"media-viewer.js","sourceRoot":"","sources":["../src/media-viewer.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAI1E,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"media-viewer.js","sourceRoot":"","sources":["../src/media-viewer.tsx"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,32 +1,67 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
1
2
|
export type MediaViewerType = "image" | "video" | "audio" | "other";
|
|
2
3
|
export type FallbackMode = "none" | "link";
|
|
3
|
-
export type
|
|
4
|
-
/** If omitted, inferred from mime/name/url. */
|
|
5
|
-
type?: MediaViewerType;
|
|
6
|
-
/** Required media URL */
|
|
4
|
+
export type BaseMediaProps = {
|
|
7
5
|
url: string;
|
|
8
|
-
/** Optional hints for inference */
|
|
9
|
-
mime?: string;
|
|
10
|
-
name?: string;
|
|
11
|
-
/** Optional download filename (fallback link) */
|
|
12
|
-
filename?: string;
|
|
13
|
-
/** Wrapper class */
|
|
14
6
|
className?: string;
|
|
15
|
-
/** Media element class */
|
|
16
7
|
mediaClassName?: string;
|
|
17
|
-
|
|
8
|
+
lazy?: boolean;
|
|
9
|
+
priority?: boolean;
|
|
10
|
+
skeleton?: boolean;
|
|
11
|
+
onLoad?: () => void;
|
|
12
|
+
onError?: () => void;
|
|
13
|
+
fallback?: React.ReactNode;
|
|
14
|
+
};
|
|
15
|
+
export type ImageViewerProps = BaseMediaProps & {
|
|
18
16
|
alt?: string;
|
|
19
|
-
/** Fallback rendering */
|
|
20
|
-
fallbackMode?: FallbackMode;
|
|
21
|
-
fallbackLabel?: string;
|
|
22
|
-
/** Image */
|
|
23
17
|
enableZoom?: boolean;
|
|
24
|
-
|
|
18
|
+
unloadOnExit?: boolean;
|
|
19
|
+
isCircular?: boolean;
|
|
20
|
+
preventGestures?: boolean;
|
|
21
|
+
};
|
|
22
|
+
export type VideoViewerProps = BaseMediaProps & {
|
|
25
23
|
controls?: boolean;
|
|
26
24
|
autoPlay?: boolean;
|
|
27
25
|
muted?: boolean;
|
|
28
26
|
loop?: boolean;
|
|
29
27
|
posterUrl?: string;
|
|
30
28
|
enableFullscreen?: boolean;
|
|
29
|
+
unloadOnExit?: boolean;
|
|
30
|
+
preload?: "auto" | "metadata" | "none";
|
|
31
|
+
autoPlayOnVisible?: boolean;
|
|
32
|
+
};
|
|
33
|
+
export type AudioViewerProps = BaseMediaProps & {
|
|
34
|
+
controls?: boolean;
|
|
35
|
+
autoPlay?: boolean;
|
|
36
|
+
loop?: boolean;
|
|
37
|
+
preload?: "auto" | "metadata" | "none";
|
|
38
|
+
onLoadChange?: (isLoading: boolean) => void;
|
|
39
|
+
};
|
|
40
|
+
export type MediaPreviewProps = {
|
|
41
|
+
url?: string | File | Blob | null;
|
|
42
|
+
alt?: string;
|
|
43
|
+
type?: MediaViewerType | string;
|
|
44
|
+
className?: string;
|
|
45
|
+
unloadOnExit?: boolean;
|
|
46
|
+
isCircular?: boolean;
|
|
47
|
+
priority?: boolean;
|
|
48
|
+
skeleton?: boolean;
|
|
49
|
+
lazy?: boolean;
|
|
50
|
+
controls?: boolean;
|
|
51
|
+
autoPlay?: boolean;
|
|
52
|
+
muted?: boolean;
|
|
53
|
+
loop?: boolean;
|
|
54
|
+
posterUrl?: string;
|
|
55
|
+
preload?: "auto" | "metadata" | "none";
|
|
56
|
+
onLoad?: () => void;
|
|
57
|
+
onError?: () => void;
|
|
58
|
+
onLoadChange?: (isLoading: boolean) => void;
|
|
59
|
+
fallbackMode?: FallbackMode;
|
|
60
|
+
fallbackLabel?: string;
|
|
61
|
+
filename?: string;
|
|
62
|
+
mime?: string;
|
|
63
|
+
name?: string;
|
|
31
64
|
};
|
|
65
|
+
/** Back-compat alias */
|
|
66
|
+
export type MediaViewerProps = MediaPreviewProps;
|
|
32
67
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/video-viewer.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function VideoViewer(props:
|
|
1
|
+
import type { VideoViewerProps } from "./types.js";
|
|
2
|
+
export declare function VideoViewer(props: VideoViewerProps): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=video-viewer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-viewer.d.ts","sourceRoot":"","sources":["../src/video-viewer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"video-viewer.d.ts","sourceRoot":"","sources":["../src/video-viewer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,2CAgLlD"}
|
package/dist/video-viewer.js
CHANGED
|
@@ -1,8 +1,70 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
+
import { useInView } from "react-intersection-observer";
|
|
4
|
+
import { Skeleton } from "@ttt-productions/ui-core";
|
|
3
5
|
export function VideoViewer(props) {
|
|
4
|
-
const { url, className, mediaClassName, controls = true, autoPlay, muted, loop, posterUrl, enableFullscreen = true, } = props;
|
|
6
|
+
const { url, className, mediaClassName, controls = true, autoPlay = false, muted, loop = false, posterUrl, enableFullscreen = true, lazy = true, unloadOnExit = true, priority = false, skeleton: showSkeleton = true, preload = "metadata", autoPlayOnVisible = false, onLoad, onError, fallback, } = props;
|
|
7
|
+
const resolvedMuted = muted ?? autoPlay;
|
|
8
|
+
const [isLoaded, setIsLoaded] = React.useState(false);
|
|
9
|
+
const [hasError, setHasError] = React.useState(false);
|
|
10
|
+
const [shouldLoad, setShouldLoad] = React.useState(priority || !lazy);
|
|
5
11
|
const videoRef = React.useRef(null);
|
|
12
|
+
const { ref: inViewRef, inView } = useInView({
|
|
13
|
+
triggerOnce: !unloadOnExit,
|
|
14
|
+
threshold: 0.01,
|
|
15
|
+
rootMargin: "200px",
|
|
16
|
+
skip: priority || !lazy,
|
|
17
|
+
});
|
|
18
|
+
// Load/unload based on viewport
|
|
19
|
+
React.useEffect(() => {
|
|
20
|
+
if (inView && !shouldLoad) {
|
|
21
|
+
setShouldLoad(true);
|
|
22
|
+
}
|
|
23
|
+
if (!inView && unloadOnExit && shouldLoad && !priority) {
|
|
24
|
+
const video = videoRef.current;
|
|
25
|
+
if (video) {
|
|
26
|
+
video.pause();
|
|
27
|
+
video.removeAttribute("src");
|
|
28
|
+
video.load();
|
|
29
|
+
}
|
|
30
|
+
setIsLoaded(false);
|
|
31
|
+
setShouldLoad(false);
|
|
32
|
+
}
|
|
33
|
+
}, [inView, shouldLoad, unloadOnExit, priority]);
|
|
34
|
+
// Reset state when URL changes
|
|
35
|
+
React.useEffect(() => {
|
|
36
|
+
setHasError(false);
|
|
37
|
+
setIsLoaded(false);
|
|
38
|
+
}, [url]);
|
|
39
|
+
const handleLoadedData = React.useCallback(() => {
|
|
40
|
+
setIsLoaded(true);
|
|
41
|
+
onLoad?.();
|
|
42
|
+
}, [onLoad]);
|
|
43
|
+
const handleError = React.useCallback(() => {
|
|
44
|
+
setHasError(true);
|
|
45
|
+
onError?.();
|
|
46
|
+
}, [onError]);
|
|
47
|
+
// Autoplay on visible / pause on exit
|
|
48
|
+
React.useEffect(() => {
|
|
49
|
+
const video = videoRef.current;
|
|
50
|
+
if (!video || !shouldLoad || (!autoPlayOnVisible && !autoPlay))
|
|
51
|
+
return;
|
|
52
|
+
const observer = new IntersectionObserver((entries) => {
|
|
53
|
+
for (const entry of entries) {
|
|
54
|
+
if (entry.isIntersecting) {
|
|
55
|
+
if (video.paused) {
|
|
56
|
+
video.play().catch(() => { });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (!video.paused) {
|
|
60
|
+
video.pause();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}, { threshold: 0.5 });
|
|
64
|
+
observer.observe(video);
|
|
65
|
+
return () => observer.disconnect();
|
|
66
|
+
}, [autoPlayOnVisible, autoPlay, shouldLoad]);
|
|
67
|
+
// Fullscreen
|
|
6
68
|
const requestFullscreen = React.useCallback(() => {
|
|
7
69
|
if (!enableFullscreen)
|
|
8
70
|
return;
|
|
@@ -17,9 +79,7 @@ export function VideoViewer(props) {
|
|
|
17
79
|
try {
|
|
18
80
|
fn.call(el);
|
|
19
81
|
}
|
|
20
|
-
catch {
|
|
21
|
-
// ignore
|
|
22
|
-
}
|
|
82
|
+
catch { /* ignore */ }
|
|
23
83
|
}
|
|
24
84
|
}, [enableFullscreen]);
|
|
25
85
|
const onKeyDown = React.useCallback((e) => {
|
|
@@ -30,6 +90,20 @@ export function VideoViewer(props) {
|
|
|
30
90
|
requestFullscreen();
|
|
31
91
|
}
|
|
32
92
|
}, [enableFullscreen, requestFullscreen]);
|
|
33
|
-
|
|
93
|
+
if (hasError) {
|
|
94
|
+
if (fallback)
|
|
95
|
+
return _jsx(_Fragment, { children: fallback });
|
|
96
|
+
return (_jsx("div", { className: className, children: _jsx("div", { className: "mv-video-error", children: _jsx("p", { children: "Failed to load video" }) }) }));
|
|
97
|
+
}
|
|
98
|
+
return (_jsxs("div", { ref: inViewRef, className: className, role: enableFullscreen ? "button" : undefined, tabIndex: enableFullscreen ? 0 : undefined, "aria-label": enableFullscreen ? "Open video fullscreen" : undefined, onDoubleClick: requestFullscreen, onKeyDown: onKeyDown, style: { position: "relative", width: "100%", height: "100%", overflow: "hidden", outline: "none" }, children: [showSkeleton && !isLoaded && shouldLoad && (_jsx(Skeleton, { style: { position: "absolute", inset: 0, width: "100%", height: "100%" } })), shouldLoad && (_jsx("video", { ref: videoRef, src: url, className: mediaClassName, controls: controls, autoPlay: autoPlay, muted: resolvedMuted, loop: loop, poster: posterUrl, onLoadedData: handleLoadedData, onError: handleError, preload: priority ? "auto" : preload, playsInline: true, style: {
|
|
99
|
+
width: "100%",
|
|
100
|
+
height: "100%",
|
|
101
|
+
objectFit: "cover",
|
|
102
|
+
opacity: isLoaded ? 1 : 0,
|
|
103
|
+
transition: "opacity 300ms ease",
|
|
104
|
+
WebkitUserSelect: "none",
|
|
105
|
+
WebkitTouchCallout: "none",
|
|
106
|
+
WebkitTapHighlightColor: "transparent",
|
|
107
|
+
} }))] }));
|
|
34
108
|
}
|
|
35
109
|
//# sourceMappingURL=video-viewer.js.map
|
package/dist/video-viewer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-viewer.js","sourceRoot":"","sources":["../src/video-viewer.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"video-viewer.js","sourceRoot":"","sources":["../src/video-viewer.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttt-productions/media-viewer",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.11",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/ttt-productions/ttt-packages.git",
|
|
@@ -12,13 +12,15 @@
|
|
|
12
12
|
"types": "dist/index.d.ts",
|
|
13
13
|
"sideEffects": false,
|
|
14
14
|
"files": [
|
|
15
|
-
"dist"
|
|
15
|
+
"dist",
|
|
16
|
+
"src/styles"
|
|
16
17
|
],
|
|
17
18
|
"exports": {
|
|
18
19
|
".": {
|
|
19
20
|
"types": "./dist/index.d.ts",
|
|
20
21
|
"default": "./dist/index.js"
|
|
21
|
-
}
|
|
22
|
+
},
|
|
23
|
+
"./styles": "./src/styles/media-viewer.css"
|
|
22
24
|
},
|
|
23
25
|
"scripts": {
|
|
24
26
|
"build": "tsc",
|
|
@@ -33,7 +35,8 @@
|
|
|
33
35
|
"peerDependencies": {
|
|
34
36
|
"react": ">=18.0.0",
|
|
35
37
|
"react-dom": ">=18.0.0",
|
|
36
|
-
"lucide-react": ">=0.0.0"
|
|
38
|
+
"lucide-react": ">=0.0.0",
|
|
39
|
+
"react-intersection-observer": ">=9.0.0"
|
|
37
40
|
},
|
|
38
41
|
"devDependencies": {
|
|
39
42
|
"typescript": "^5.8.3"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/* @ttt-productions/media-viewer styles */
|
|
2
|
+
|
|
3
|
+
/* Skeleton fallback (CSS-only, for environments without ui-core) */
|
|
4
|
+
.mv-skeleton {
|
|
5
|
+
background: hsl(var(--muted, 220 14% 96%));
|
|
6
|
+
animation: mv-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
7
|
+
border-radius: var(--radius, 0.375rem);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@keyframes mv-pulse {
|
|
11
|
+
0%, 100% { opacity: 1; }
|
|
12
|
+
50% { opacity: 0.5; }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* Error fallback */
|
|
16
|
+
.mv-error-fallback {
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
justify-content: center;
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 100%;
|
|
22
|
+
background: hsl(var(--destructive, 0 84% 60%) / 0.1);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.mv-error-fallback svg {
|
|
26
|
+
width: 50%;
|
|
27
|
+
height: 50%;
|
|
28
|
+
max-width: 4rem;
|
|
29
|
+
max-height: 4rem;
|
|
30
|
+
color: hsl(var(--destructive, 0 84% 60%) / 0.8);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Empty fallback */
|
|
34
|
+
.mv-empty-fallback {
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: center;
|
|
37
|
+
justify-content: center;
|
|
38
|
+
width: 100%;
|
|
39
|
+
height: 100%;
|
|
40
|
+
background: hsl(var(--muted, 220 14% 96%));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.mv-empty-fallback svg {
|
|
44
|
+
width: 50%;
|
|
45
|
+
height: 50%;
|
|
46
|
+
max-width: 4rem;
|
|
47
|
+
max-height: 4rem;
|
|
48
|
+
color: hsl(var(--muted-foreground, 220 9% 46%));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* Avatar/circular empty fallback */
|
|
52
|
+
.mv-avatar-fallback {
|
|
53
|
+
display: flex;
|
|
54
|
+
align-items: center;
|
|
55
|
+
justify-content: center;
|
|
56
|
+
width: 100%;
|
|
57
|
+
height: 100%;
|
|
58
|
+
border-radius: 50%;
|
|
59
|
+
background: hsl(var(--muted, 220 14% 96%));
|
|
60
|
+
font-size: 1.125rem;
|
|
61
|
+
color: hsl(var(--muted-foreground, 220 9% 46%));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Video error state */
|
|
65
|
+
.mv-video-error {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
align-items: center;
|
|
69
|
+
justify-content: center;
|
|
70
|
+
width: 100%;
|
|
71
|
+
height: 100%;
|
|
72
|
+
background: hsl(var(--muted, 220 14% 96%));
|
|
73
|
+
border-radius: var(--radius, 0.375rem);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.mv-video-error p {
|
|
77
|
+
color: hsl(var(--muted-foreground, 220 9% 46%));
|
|
78
|
+
font-size: 0.875rem;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Audio error state */
|
|
82
|
+
.mv-audio-error {
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
justify-content: center;
|
|
86
|
+
background: hsl(var(--muted, 220 14% 96%));
|
|
87
|
+
border-radius: var(--radius, 0.375rem);
|
|
88
|
+
padding: 1rem;
|
|
89
|
+
height: 3.5rem;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.mv-audio-error p {
|
|
93
|
+
color: hsl(var(--destructive, 0 84% 60%));
|
|
94
|
+
font-size: 0.75rem;
|
|
95
|
+
}
|