Refactor viewerjs code into separate ImageActions.tsx component and revert ImageWithFallback.tsx
This commit is contained in:
parent
cd7b49042b
commit
038f6bc26c
@ -11,7 +11,7 @@ export default function FullscreenButton({
|
||||
imageRef,
|
||||
}: {
|
||||
className?: string;
|
||||
imageRef: RefObject<HTMLImageElement | null>;
|
||||
imageRef: RefObject<HTMLDivElement | null>;
|
||||
}) {
|
||||
const { isFullscreen, setIsFullscreen } = useAppState();
|
||||
|
||||
@ -55,7 +55,7 @@ export default function FullscreenButton({
|
||||
title="Toggle Fullscreen"
|
||||
className={clsx(
|
||||
className,
|
||||
'text-medium absolute bottom-2 right-2 bg-white p-2 rounded',
|
||||
'text-medium absolute bottom-2 right-2 bg-white p-2 rounded hidden md:block',
|
||||
)}
|
||||
icon={isFullscreen ? <MdFullscreenExit size={18} />
|
||||
: <MdFullscreen size={18} />}
|
||||
|
||||
55
src/components/image/ImageActions.tsx
Normal file
55
src/components/image/ImageActions.tsx
Normal file
@ -0,0 +1,55 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import Viewer from 'viewerjs';
|
||||
import 'viewerjs/dist/viewer.css';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import FullscreenButton from '../FullscreenButton';
|
||||
|
||||
export default function ImageActions({ children, enableImageActions = false, className }: { children: React.ReactNode, enableImageActions?: boolean, className?: string }) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const viewerRef = useRef<Viewer | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (containerRef.current && enableImageActions) {
|
||||
viewerRef.current = new Viewer(containerRef.current, {
|
||||
inline: false,
|
||||
button: true,
|
||||
navbar: false,
|
||||
title: false,
|
||||
toolbar: {
|
||||
zoomIn: 1,
|
||||
zoomOut: 1,
|
||||
reset: 1,
|
||||
tooltip: 1,
|
||||
},
|
||||
});
|
||||
return () => {
|
||||
viewerRef.current?.destroy();
|
||||
};
|
||||
}
|
||||
}, [enableImageActions]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<style jsx global>{`
|
||||
.viewer-canvas {
|
||||
background-color: black !important;
|
||||
}
|
||||
.viewer-reset::before {
|
||||
content: '1:1';
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
bottom: -9px;
|
||||
letter-spacing: -2px;
|
||||
background-image: none;
|
||||
}
|
||||
`}</style>
|
||||
<div className={clsx(className, enableImageActions && 'cursor-zoom-in')} ref={containerRef} >
|
||||
{children}
|
||||
{enableImageActions && <FullscreenButton imageRef={containerRef}/>}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -1,18 +1,22 @@
|
||||
import { IMAGE_WIDTH_LARGE, ImageProps } from '.';
|
||||
import ImageWithFallback from './ImageWithFallback';
|
||||
import ImageActions from './ImageActions';
|
||||
|
||||
export default function ImageLarge(props: ImageProps) {
|
||||
const {
|
||||
aspectRatio,
|
||||
blurCompatibilityMode,
|
||||
enableImageActions = false,
|
||||
...rest
|
||||
} = props;
|
||||
return (
|
||||
<ImageWithFallback {...{
|
||||
...rest,
|
||||
blurCompatibilityLevel: blurCompatibilityMode ? 'high' : 'none',
|
||||
width: IMAGE_WIDTH_LARGE,
|
||||
height: Math.round(IMAGE_WIDTH_LARGE / aspectRatio),
|
||||
}} />
|
||||
<ImageActions enableImageActions={enableImageActions} className="flex relative items-center justify-center h-full">
|
||||
<ImageWithFallback {...{
|
||||
...rest,
|
||||
blurCompatibilityLevel: blurCompatibilityMode ? 'high' : 'none',
|
||||
width: IMAGE_WIDTH_LARGE,
|
||||
height: Math.round(IMAGE_WIDTH_LARGE / aspectRatio),
|
||||
}} />
|
||||
</ImageActions>
|
||||
);
|
||||
};
|
||||
|
||||
@ -3,18 +3,13 @@
|
||||
/* eslint-disable jsx-a11y/alt-text */
|
||||
import { BLUR_ENABLED } from '@/site/config';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { clsx} from 'clsx/lite';
|
||||
import Image, { ImageProps } from 'next/image';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import FullscreenButton from '../FullscreenButton';
|
||||
import Viewer from 'viewerjs';
|
||||
import 'viewerjs/dist/viewer.css';
|
||||
|
||||
export default function ImageWithFallback(props: ImageProps & {
|
||||
blurCompatibilityLevel?: 'none' | 'low' | 'high'
|
||||
imgClassName?: string
|
||||
allowFullscreen?: boolean
|
||||
enableImageActions?: boolean
|
||||
}) {
|
||||
const {
|
||||
className,
|
||||
@ -22,7 +17,6 @@ export default function ImageWithFallback(props: ImageProps & {
|
||||
blurDataURL,
|
||||
blurCompatibilityLevel = 'low',
|
||||
imgClassName = 'object-cover h-full',
|
||||
enableImageActions = false,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
@ -37,10 +31,7 @@ export default function ImageWithFallback(props: ImageProps & {
|
||||
|
||||
const [hideFallback, setHideFallback] = useState(false);
|
||||
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const viewerRef = useRef<Viewer | null>(null);
|
||||
const imgRef = useRef<HTMLImageElement | null>(null);
|
||||
const { isFullscreen } = useAppState();
|
||||
const imgRef = useRef<HTMLImageElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const timeout = setTimeout(
|
||||
@ -59,26 +50,6 @@ export default function ImageWithFallback(props: ImageProps & {
|
||||
}
|
||||
}, [isLoading, didError]);
|
||||
|
||||
useEffect(() => {
|
||||
if (containerRef.current && enableImageActions) {
|
||||
viewerRef.current = new Viewer(containerRef.current, {
|
||||
inline: false,
|
||||
button: true,
|
||||
navbar: false,
|
||||
title: false,
|
||||
toolbar: {
|
||||
zoomIn: 1,
|
||||
zoomOut: 1,
|
||||
reset: 1,
|
||||
tooltip: 1,
|
||||
},
|
||||
});
|
||||
return () => {
|
||||
viewerRef.current?.destroy();
|
||||
};
|
||||
}
|
||||
}, [enableImageActions]);
|
||||
|
||||
const showFallback =
|
||||
!wasCached &&
|
||||
!hideFallback;
|
||||
@ -94,65 +65,45 @@ export default function ImageWithFallback(props: ImageProps & {
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<style jsx global>{` // Viewerjs customizations
|
||||
.viewer-canvas { background-color: black !important; }
|
||||
.viewer-reset::before {
|
||||
content: '1:1';
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
bottom: -9px;
|
||||
letter-spacing: -2px;
|
||||
background-image: none;
|
||||
}`}</style>
|
||||
<div
|
||||
className={clsx(
|
||||
className,
|
||||
'flex relative',
|
||||
)}
|
||||
ref={containerRef}
|
||||
>
|
||||
{(showFallback || shouldDebugImageFallbacks) &&
|
||||
<div className={clsx(
|
||||
'@container',
|
||||
'absolute inset-0',
|
||||
'overflow-hidden',
|
||||
'transition-opacity duration-300 ease-in',
|
||||
!(BLUR_ENABLED && blurDataURL) && 'bg-main',
|
||||
(isLoading || shouldDebugImageFallbacks)
|
||||
? 'opacity-100'
|
||||
: 'opacity-0',
|
||||
)}>
|
||||
{(BLUR_ENABLED && blurDataURL)
|
||||
? <img {...{
|
||||
...rest,
|
||||
src: blurDataURL,
|
||||
className: clsx(
|
||||
imgClassName,
|
||||
getBlurClass(),
|
||||
),
|
||||
}} />
|
||||
: <div className={clsx(
|
||||
'w-full h-full',
|
||||
'bg-gray-100/50 dark:bg-gray-900/50',
|
||||
)} />}
|
||||
</div>}
|
||||
<Image
|
||||
{...rest}
|
||||
ref={imgRef}
|
||||
priority={priority}
|
||||
className={clsx(
|
||||
imgClassName,
|
||||
!isFullscreen && enableImageActions && 'cursor-zoom-in',
|
||||
)}
|
||||
onLoad={onLoad}
|
||||
onError={onError}
|
||||
/>
|
||||
{enableImageActions && <FullscreenButton imageRef={imgRef} />}
|
||||
<div
|
||||
className={clsx(
|
||||
className,
|
||||
'flex relative',
|
||||
)}
|
||||
>
|
||||
{(showFallback || shouldDebugImageFallbacks) &&
|
||||
<div className={clsx(
|
||||
'@container',
|
||||
'absolute inset-0',
|
||||
'overflow-hidden',
|
||||
'transition-opacity duration-300 ease-in',
|
||||
!(BLUR_ENABLED && blurDataURL) && 'bg-main',
|
||||
(isLoading || shouldDebugImageFallbacks)
|
||||
? 'opacity-100'
|
||||
: 'opacity-0',
|
||||
)}>
|
||||
{(BLUR_ENABLED && blurDataURL)
|
||||
? <img {...{
|
||||
...rest,
|
||||
src: blurDataURL,
|
||||
className: clsx(
|
||||
imgClassName,
|
||||
getBlurClass(),
|
||||
),
|
||||
}} />
|
||||
: <div className={clsx(
|
||||
'w-full h-full',
|
||||
'bg-gray-100/50 dark:bg-gray-900/50',
|
||||
)} />}
|
||||
</div>}
|
||||
<Image {...{
|
||||
...rest,
|
||||
ref: imgRef,
|
||||
priority,
|
||||
className: imgClassName,
|
||||
onLoad,
|
||||
onError,
|
||||
}} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user