Files
papercrate/frontend/src/desktop/DesktopPreviewCard.jsx
T
2025-11-06 14:43:43 +01:00

147 lines
3.8 KiB
React

import React, { useEffect } from 'react';
import { ArrowLeftIcon, ArrowRightIcon } from '../ui/icons';
import { useAssetNavigator } from '../hooks/useAssetNavigator';
import { preventAll } from './events';
const DesktopPreviewCard = ({
doc,
title,
ensureAssetUrl,
getDocumentAsset,
prefetch = 3,
onNavigatorSnapshot,
shouldLoad = true,
}) => {
const navigator = useAssetNavigator({
document: doc,
assetType: 'preview',
ensureAssetUrl: shouldLoad ? ensureAssetUrl : null,
getAsset: getDocumentAsset,
prefetch,
});
const { currentUrl, cardinality, canGoPrev, canGoNext, currentMetadata, ordinal } = navigator;
const docId = doc?.id ?? null;
const metadataWidth = Number(currentMetadata?.width);
const metadataHeight = Number(currentMetadata?.height);
useEffect(() => {
if (!onNavigatorSnapshot || !docId) {
return undefined;
}
const snapshot = {
url: currentUrl || null,
alt: title,
canGoPrev,
canGoNext,
goPrev: navigator.goPrev,
goNext: navigator.goNext,
ordinal,
width: Number.isFinite(metadataWidth) && metadataWidth > 0 ? metadataWidth : null,
height: Number.isFinite(metadataHeight) && metadataHeight > 0 ? metadataHeight : null,
};
onNavigatorSnapshot(docId, snapshot);
return () => onNavigatorSnapshot(docId, null);
}, [
docId,
currentUrl,
title,
canGoPrev,
canGoNext,
ordinal,
metadataWidth,
metadataHeight,
navigator.goPrev,
navigator.goNext,
onNavigatorSnapshot,
]);
const hasPreview = Boolean(currentUrl);
const cardClasses = ['desk-item__card'];
if (!hasPreview) cardClasses.push('desk-item__card--empty');
const showNav = hasPreview && (cardinality > 1 || canGoPrev || canGoNext);
return (
<div
className={cardClasses.join(' ')}
onDragStart={(event) => {
if (event instanceof DragEvent) {
event.preventDefault();
}
}}
>
{hasPreview ? (
<img
src={currentUrl}
alt={title}
draggable={false}
onDragStart={(event) => event.preventDefault()}
/>
) : (
<div className="desk-item__empty">
<div className="desk-item__placeholder">DOC</div>
<div className="desk-item__title" title={title}>
{title}
</div>
</div>
)}
{showNav ? (
<div className="desk-card__nav">
<button
type="button"
className="desk-card__nav-button"
onClick={(event) => {
preventAll(event);
navigator.goPrev();
}}
onPointerDown={(event) => {
preventAll(event);
}}
onPointerUp={(event) => {
preventAll(event);
}}
onMouseDown={(event) => {
preventAll(event);
}}
onMouseUp={(event) => {
preventAll(event);
}}
disabled={!canGoPrev}
aria-label="Previous preview"
>
<ArrowLeftIcon />
</button>
<button
type="button"
className="desk-card__nav-button"
onClick={(event) => {
preventAll(event);
navigator.goNext();
}}
onPointerDown={(event) => {
preventAll(event);
}}
onPointerUp={(event) => {
preventAll(event);
}}
onMouseDown={(event) => {
preventAll(event);
}}
onMouseUp={(event) => {
preventAll(event);
}}
disabled={!canGoNext}
aria-label="Next preview"
>
<ArrowRightIcon />
</button>
</div>
) : null}
</div>
);
};
export default DesktopPreviewCard;