Files
claudecodeui/src/components/plugins/PluginIcon.tsx

40 lines
1.1 KiB
TypeScript

import { useState, useEffect } from 'react';
import { authenticatedFetch } from '../../utils/api';
type Props = {
pluginName: string;
iconFile: string;
className?: string;
};
// Module-level cache so repeated renders don't re-fetch
const svgCache = new Map<string, string>();
export default function PluginIcon({ pluginName, iconFile, className }: Props) {
const url = `/api/plugins/${encodeURIComponent(pluginName)}/assets/${encodeURIComponent(iconFile)}`;
const [svg, setSvg] = useState<string | null>(svgCache.get(url) ?? null);
useEffect(() => {
if (svgCache.has(url)) return;
authenticatedFetch(url)
.then((r) => r.text())
.then((text) => {
if (text.trimStart().startsWith('<svg')) {
svgCache.set(url, text);
setSvg(text);
}
})
.catch(() => {});
}, [url]);
if (!svg) return <span className={className} />;
return (
<span
className={className}
// SVG is fetched from the user's own installed plugin — same trust level as the plugin code itself
dangerouslySetInnerHTML={{ __html: svg }}
/>
);
}