import { useState, useMemo } from 'react' import Icon from './Icon' import { BarToggle, BarButton, BAR_H } from './BarControls' /* Preview — abhaengig vom Typ: material → Color-Swatch symbol/object → Typ-Icon-Placeholder (spaeter: PNG-Thumbnail aus library/previews/) */ function ItemPreview({ item }) { if (item.type === 'material') { return (
) } const iconName = item.type === 'symbol' ? 'navigation' : 'forest' return (
) } /* ItemCard — Preview + Name + Tags + Import-Pill */ function ItemCard({ item, imported, onImport }) { // material wird "importiert" gezeigt wenn schon in Project-Settings. // symbol/object koennen N-mal eingefuegt werden → "Importiert" wird // nicht persistent, jeder Klick legt eine weitere Instanz an. const isMaterial = item.type === 'material' const ctaLabel = isMaterial ? (imported ? 'Importiert' : 'Importieren') : 'Einfügen' const ctaDisabled = isMaterial && imported return (
{ if (ctaDisabled) return e.currentTarget.style.borderColor = 'var(--accent)' }} onMouseLeave={(e) => { e.currentTarget.style.borderColor = 'var(--border)' }} onDoubleClick={() => { if (!ctaDisabled) onImport(item.id) }} title={ctaDisabled ? 'Bereits importiert' : 'Doppelklick = importieren'}>
{item.name} {ctaDisabled && ( )}
{(item.tags || []).length > 0 && (
{(item.tags || []).slice(0, 4).map(t => ( {t} ))}
)} { if (!ctaDisabled) onImport(item.id) }} disabled={ctaDisabled} />
) } export default function LibraryBrowser({ manifest, importedIds, libraryRoot, onImport, onReload, onClose, }) { const [search, setSearch] = useState('') const [typeFilter, setTypeFilter] = useState('all') const items = manifest?.items || [] const importedSet = useMemo(() => new Set(importedIds || []), [importedIds]) const filtered = useMemo(() => { const q = search.trim().toLowerCase() return items.filter(it => { if (typeFilter !== 'all' && it.type !== typeFilter) return false if (!q) return true if ((it.name || '').toLowerCase().includes(q)) return true if ((it.tags || []).some(t => t.toLowerCase().includes(q))) return true return false }) }, [items, search, typeFilter]) const types = useMemo(() => { const s = new Set(items.map(i => i.type)) return ['all', ...Array.from(s)] }, [items]) return (
{/* Toolbar — Suche + Pill-Filter + Reload */}
setSearch(ev.target.value)} placeholder="Suchen (Name oder Tag)…" style={{ flex: 1, height: BAR_H, padding: '0 12px', fontSize: 11 }} />
{types.map(t => ( setTypeFilter(t)} /> ))}
{/* Grid */}
{filtered.length === 0 ? (
{items.length === 0 ? 'Library ist leer. Manifest unter:' : 'Nichts gefunden — Filter aendern?'} {items.length === 0 && libraryRoot && (
{libraryRoot}/library.json
)}
) : (
{filtered.map(it => ( ))}
)}
{/* Footer */}
{filtered.length} / {items.length} Items
{libraryRoot || ''}
) }