|
1 | 1 | import { useImperativeHandle, forwardRef } from 'react'; |
2 | 2 | import { convertFileSrc } from '@tauri-apps/api/core'; |
3 | 3 | import { useZoomTransform } from '@/hooks/useZoomTransform'; |
| 4 | +import { |
| 5 | + PLACEHOLDER_IMAGE_SRC, |
| 6 | + handlePlaceholderImageError, |
| 7 | +} from '@/utils/imageFallback'; |
4 | 8 |
|
5 | 9 | interface ZoomableImageProps { |
6 | 10 | imagePath: string; |
@@ -35,11 +39,15 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>( |
35 | 39 | reset, |
36 | 40 | } = useZoomTransform({ imagePath, rotation, resetSignal }); |
37 | 41 |
|
38 | | - useImperativeHandle(ref, () => ({ |
39 | | - zoomIn, |
40 | | - zoomOut, |
41 | | - reset, |
42 | | - })); |
| 42 | + useImperativeHandle( |
| 43 | + ref, |
| 44 | + () => ({ |
| 45 | + zoomIn, |
| 46 | + zoomOut, |
| 47 | + reset, |
| 48 | + }), |
| 49 | + [zoomIn, zoomOut, reset], |
| 50 | + ); |
43 | 51 |
|
44 | 52 | return ( |
45 | 53 | <div |
@@ -75,26 +83,22 @@ export const ZoomableImage = forwardRef<ZoomableImageRef, ZoomableImageProps>( |
75 | 83 | <img |
76 | 84 | key={imagePath} |
77 | 85 | ref={imageRef} |
78 | | - src={convertFileSrc(imagePath) || '/placeholder.svg'} |
| 86 | + src={convertFileSrc(imagePath) || PLACEHOLDER_IMAGE_SRC} |
79 | 87 | alt={alt} |
80 | 88 | draggable={false} |
81 | | - className="select-none" |
82 | 89 | onLoad={handleImageLoad} |
83 | | - onError={(e) => { |
84 | | - const img = e.target as HTMLImageElement; |
85 | | - img.onerror = null; |
86 | | - img.src = '/placeholder.svg'; |
87 | | - }} |
| 90 | + onError={handlePlaceholderImageError} |
88 | 91 | style={{ |
89 | 92 | position: contentDimensions ? 'absolute' : 'relative', |
90 | 93 | left: `${imageOffset.left}px`, |
91 | 94 | top: `${imageOffset.top}px`, |
92 | 95 | width: rawDimensions ? `${rawDimensions.width}px` : undefined, |
93 | 96 | height: rawDimensions ? `${rawDimensions.height}px` : undefined, |
| 97 | + // Override the framework's `img { max-width: 100% }` reset so the |
| 98 | + // image can scale beyond the viewport while zoomed. |
94 | 99 | maxWidth: 'none', |
95 | 100 | maxHeight: 'none', |
96 | 101 | objectFit: 'contain', |
97 | | - zIndex: 50, |
98 | 102 | transform: `rotate(${rotation}deg)`, |
99 | 103 | transformOrigin: 'center center', |
100 | 104 | pointerEvents: 'none', |
|
0 commit comments