Files
web-cad/frontend/src/components/LibraryProviderPanel.tsx
T

85 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Task F4 UI für LibraryProviderExtensions.
*
* Lädt alle übergebenen Provider (builtin/user/global) und rendert je Ordner
* eine Sektion mit Thumbnail-Blöcken. Jeder Block ist als DragSource an den
* bestehenden 'text/global-block-data'-Kanal angebunden (DragDrop → Canvas).
*/
import React, { useEffect, useState } from 'react';
import type { LibraryProviderExtension, LibBlock } from '../plugins/types';
interface Props {
providers: LibraryProviderExtension[];
}
interface Section { key: string; label: string; blocks: LibBlock[]; }
const LibraryProviderPanel: React.FC<Props> = ({ providers }) => {
const [sections, setSections] = useState<Section[]>([]);
useEffect(() => {
let cancelled = false;
(async () => {
const out: Section[] = [];
for (const provider of providers) {
try {
const folders = await provider.listFolders();
for (const folder of folders) {
try {
const blocks = await provider.listBlocks(folder.id);
if (blocks.length > 0) {
out.push({ key: `${provider.id}/${folder.id}`, label: folder.label, blocks });
}
} catch {
// Ordner bei Fehler überspringen
}
}
} catch {
// Provider bei Fehler überspringen
}
}
if (!cancelled) setSections(out);
})();
return () => {
cancelled = true;
};
}, [providers]);
const handleDragStart = (e: React.DragEvent, block: LibBlock) => {
const payload = typeof block.payload === 'string' ? block.payload : JSON.stringify(block.payload ?? []);
e.dataTransfer.setData('text/global-block-data', payload);
e.dataTransfer.effectAllowed = 'copy';
};
if (sections.length === 0) return null;
return (
<div className="lib-provider-panel">
{sections.map((section) => (
<div className="lprov-section" key={section.key}>
<div className="lprov-title">{section.label}</div>
<div className="lprov-grid">
{section.blocks.map((block) => (
<button
key={block.id}
type="button"
className="lprov-block"
aria-label={block.name}
title={block.name}
draggable
onDragStart={(e) => handleDragStart(e, block)}
>
{block.thumbnail
? <span className="tree-thumb" dangerouslySetInnerHTML={{ __html: block.thumbnail }} />
: <span className="lib-grid-placeholder">📦</span>}
</button>
))}
</div>
</div>
))}
</div>
);
};
export default LibraryProviderPanel;