Files
image-studio/view/layers/LayerThumbnail.tsx
2026-07-11 12:20:26 +02:00

30 lines
1.8 KiB
TypeScript

import { FolderSimple, ImageBroken } from "@phosphor-icons/react";
import type { LayerThumbnailModel, RasterThumbnailModel } from "./thumbnailModel";
export function LayerThumbnail({ model, label, compact = false }: { model: LayerThumbnailModel; label: string; compact?: boolean }) {
const sizeClass = compact ? "h-7 w-9 rounded-md" : "h-8 w-10 rounded-lg";
return (
<span role="img" aria-label={label} className={`relative grid shrink-0 place-items-center overflow-hidden bg-black/25 ring-1 ring-inset ring-white/15 ${sizeClass}`}>
{model.kind === "raster" ? <RasterPreview model={model} /> : null}
{model.kind === "group" ? (
<>
<span className="absolute inset-1 grid grid-cols-2 gap-px overflow-hidden rounded">
{model.previews.map((preview, index) => <RasterPreview key={`${preview.source}-${index}`} model={preview} />)}
</span>
<FolderSimple size={compact ? 14 : 17} weight="fill" className="relative drop-shadow-[0_1px_2px_rgba(0,0,0,0.8)]" />
</>
) : null}
{model.kind === "empty" ? <ImageBroken size={compact ? 14 : 17} className="text-white/35" /> : null}
</span>
);
}
function RasterPreview({ model }: { model: RasterThumbnailModel }) {
const { x, y, w, h } = model.viewBox;
return (
<svg aria-hidden="true" className="h-full w-full bg-[linear-gradient(45deg,rgba(255,255,255,.06)_25%,transparent_25%,transparent_75%,rgba(255,255,255,.06)_75%),linear-gradient(45deg,rgba(255,255,255,.06)_25%,transparent_25%,transparent_75%,rgba(255,255,255,.06)_75%)] bg-[length:8px_8px] bg-[position:0_0,4px_4px]" viewBox={`${x} ${y} ${w} ${h}`} preserveAspectRatio="xMidYMid meet">
<image href={model.source} x="0" y="0" width={model.intrinsicWidth} height={model.intrinsicHeight} onError={(event) => event.currentTarget.setAttribute("visibility", "hidden")} />
</svg>
);
}