1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
/**
* ImageView shows a workspace image (png, jpeg, gif, webp, svg, bmp, ico,
* avif) at its natural size, capped to the pane width, over a checkerboard
* that reveals transparency. The bytes stream from GET /api/raw, and the
* natural dimensions appear once the browser has decoded the image.
*
* @example
* <ImageView path="/work/docs/logo.png" />
*/
import { useState } from "react";
import { rawFileUrl } from "../api";
export function ImageView({ path }: { path: string }) {
const [size, setSize] = useState<{ width: number; height: number } | null>(
null,
);
const [failed, setFailed] = useState(false);
if (failed) {
return <p className="pane-error">the image could not be loaded</p>;
}
return (
<figure className="image-view">
<div className="image-view-canvas">
<img
src={rawFileUrl(path)}
alt={path.split("/").pop() ?? path}
onLoad={(event) => {
const img = event.currentTarget;
setSize({ width: img.naturalWidth, height: img.naturalHeight });
}}
onError={() => setFailed(true)}
/>
</div>
<figcaption className="image-view-meta">
{size ? `${size.width} × ${size.height} px` : "loading…"}
</figcaption>
</figure>
);
}
|