Files
pdf-tools/src/components/PageWorkspace/PageCard.tsx

214 lines
5.0 KiB
TypeScript

import React from 'react';
import type { PageRef } from '../../pdf/pdfTypes';
import DropIndicator from './DropIndicator';
interface PageCardProps {
page: PageRef;
visualIndex: number;
thumbnail?: string;
selected: boolean;
isDraggingCard: boolean;
isBusy: boolean;
isCopyDragging: boolean;
showLeftLine: boolean;
showRightLine: boolean;
dropIndicatorColor: string;
onDragStart: React.DragEventHandler<HTMLDivElement>;
onDragEnd: React.DragEventHandler<HTMLDivElement>;
onDragOver: React.DragEventHandler<HTMLDivElement>;
onOpenPreview: () => void;
onToggleSelect: React.MouseEventHandler<HTMLButtonElement>;
onRotateClockwise: () => void;
onRotateCounterclockwise: () => void;
onDelete: () => void;
}
const pageActionButtonStyle: React.CSSProperties = {
border: 'none',
borderRadius: '999px',
padding: '0.15rem 0.4rem',
fontSize: '0.75rem',
cursor: 'pointer',
};
const PageCard: React.FC<PageCardProps> = ({
page,
visualIndex,
thumbnail,
selected,
isDraggingCard,
isBusy,
isCopyDragging,
showLeftLine,
showRightLine,
dropIndicatorColor,
onDragStart,
onDragEnd,
onDragOver,
onOpenPreview,
onToggleSelect,
onRotateClockwise,
onRotateCounterclockwise,
onDelete,
}) => {
const background = isDraggingCard
? isCopyDragging
? '#dcfce7'
: '#dbeafe'
: selected
? '#eff6ff'
: '#f9fafb';
return (
<div
draggable
onDragStart={onDragStart}
onDragEnd={onDragEnd}
onDragOver={onDragOver}
onClick={onOpenPreview}
style={{
position: 'relative',
width: '162px',
padding: '0.4rem',
borderRadius: '0.5rem',
border: '1px solid #e5e7eb',
background,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
gap: '0.25rem',
cursor: isBusy ? 'default' : isCopyDragging ? 'copy' : 'grab',
opacity: isBusy ? 0.7 : 1,
}}
>
<button
type="button"
onClick={onToggleSelect}
style={{
position: 'absolute',
top: '4px',
left: '4px',
width: '20px',
height: '20px',
borderRadius: '0.4rem',
border: '1px solid #9ca3af',
background: selected ? '#2563eb' : 'rgba(255,255,255,0.9)',
color: selected ? 'white' : 'transparent',
fontSize: '0.8rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: 0,
cursor: 'pointer',
}}
title="Select page"
>
</button>
{showLeftLine && <DropIndicator side="left" color={dropIndicatorColor} />}
{showRightLine && (
<DropIndicator side="right" color={dropIndicatorColor} />
)}
<div
style={{
width: '110px',
height: '90px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
{thumbnail ? (
<img
src={thumbnail}
alt={`Page ${page.sourcePageIndex + 1}`}
style={{
maxWidth: '100%',
maxHeight: '100%',
width: 'auto',
height: 'auto',
objectFit: 'contain',
borderRadius: '0.25rem',
border: '1px solid #e5e7eb',
background: 'white',
}}
/>
) : (
<div
style={{
width: '60px',
height: '80px',
borderRadius: '0.25rem',
border: '1px dashed #d1d5db',
background: '#f3f4f6',
}}
/>
)}
</div>
<span style={{ fontSize: '0.8rem' }}>
Page {page.sourcePageIndex + 1}
</span>
<span style={{ fontSize: '0.7rem', color: '#6b7280' }}>
Pos {visualIndex + 1} · Rot {page.rotation}°
</span>
<div
style={{
display: 'flex',
gap: '0.25rem',
marginTop: '0.25rem',
}}
>
<button
type="button"
onClick={(e) => {
e.stopPropagation();
onRotateClockwise();
}}
style={{
...pageActionButtonStyle,
background: '#e5e7eb',
}}
>
90°
</button>
<button
type="button"
onClick={(e) => {
e.stopPropagation();
onRotateCounterclockwise();
}}
style={{
...pageActionButtonStyle,
background: '#e5e7eb',
}}
>
90°
</button>
<button
type="button"
onClick={(e) => {
e.stopPropagation();
onDelete();
}}
style={{
...pageActionButtonStyle,
background: '#fecaca',
color: '#b91c1c',
}}
title="Remove this page from the exported PDF"
>
</button>
</div>
</div>
);
};
export default PageCard;