CI / check (push) Successful in 30s
CI / tests-imaging-browsers (push) Successful in 1m31s
CI / tests-unit (push) Successful in 1m45s
CI / tests-integration (push) Successful in 1m49s
CI / tests-quality (push) Successful in 47s
CI / tests-ui (push) Successful in 4m24s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 3m39s
The project lints with Biome only, so none of these 78 directives across 57 files ever suppressed anything. Directives that carried the rationale for a flagged dynamic index access keep that rationale as a plain comment.
48 lines
1.1 KiB
TypeScript
48 lines
1.1 KiB
TypeScript
"use client";
|
|
|
|
import { Image as ImageIcon } from "lucide-react";
|
|
import { getHabboCdnIconUrl, getLocalIconUrl } from "@/lib/furni/classname";
|
|
|
|
export function FurniIcon({
|
|
classname,
|
|
revision,
|
|
}: {
|
|
classname: string;
|
|
revision: number;
|
|
}) {
|
|
if (!classname) {
|
|
return (
|
|
<div className="w-10 h-10 rounded bg-muted flex items-center justify-center">
|
|
<ImageIcon className="h-4 w-4 text-muted-foreground" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const localUrl = getLocalIconUrl(classname);
|
|
|
|
function handleError(e: React.SyntheticEvent<HTMLImageElement>) {
|
|
const img = e.target as HTMLImageElement;
|
|
const stage = img.dataset.fallback;
|
|
if (!stage && revision > 0) {
|
|
img.dataset.fallback = "cdn";
|
|
img.src = getHabboCdnIconUrl(classname, revision);
|
|
} else {
|
|
img.dataset.fallback = "none";
|
|
img.style.opacity = "0";
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className="w-10 h-10 rounded bg-muted/50 flex items-center justify-center overflow-hidden">
|
|
<img
|
|
src={localUrl}
|
|
alt={classname}
|
|
className="max-w-full max-h-full object-contain"
|
|
style={{ imageRendering: "pixelated" }}
|
|
onError={handleError}
|
|
loading="lazy"
|
|
/>
|
|
</div>
|
|
);
|
|
}
|