import React, { useEffect, useState } from 'react' function SelectedArtworkCard({ artwork, onClear, disabled = false }) { if (!artwork) return null return (
{artwork.thumbnail ? ( {artwork.title} ) : (
)}
Linked original
{artwork.title}
{artwork.publisher || 'Artist'} {artwork.year ? {artwork.year} : null} {artwork.content_type ? {artwork.content_type} : null}
{artwork.url ? ( Open public ) : null}
) } export default function ArtworkEvolutionSearchPicker({ artworkId, selected, onSelect, disabled = false }) { const [query, setQuery] = useState('') const [options, setOptions] = useState([]) const [loading, setLoading] = useState(false) useEffect(() => { if (!artworkId) return undefined const controller = new AbortController() const handle = window.setTimeout(async () => { setLoading(true) try { const response = await fetch(`/api/studio/artworks/${artworkId}/evolution-options?search=${encodeURIComponent(query)}`, { headers: { Accept: 'application/json' }, credentials: 'same-origin', signal: controller.signal, }) if (!response.ok) { setOptions([]) return } const data = await response.json() setOptions(Array.isArray(data.data) ? data.data : []) } catch (error) { if (error?.name !== 'AbortError') { setOptions([]) } } finally { setLoading(false) } }, query.trim() === '' ? 0 : 220) return () => { controller.abort() window.clearTimeout(handle) } }, [artworkId, query]) const visibleOptions = options.filter((option) => Number(option.id) !== Number(selected?.id)) return (
onSelect(null)} disabled={disabled} />
setQuery(event.target.value)} placeholder="Search by title, slug, creator, or group" disabled={disabled} className="w-full rounded-2xl border border-white/10 bg-[#0d1726] px-4 py-3 text-white outline-none transition focus:border-sky-300/35 disabled:cursor-not-allowed disabled:opacity-60" />
{loading ? 'Searching…' : `${visibleOptions.length} result${visibleOptions.length === 1 ? '' : 's'}`}

Start with your own published artworks. Group-published pieces appear too when you can publish artworks for that group. Results are ranked by visual similarity when the vector index is available.

{visibleOptions.length ? visibleOptions.map((option) => ( )) : (
{loading ? 'Searching artworks…' : 'No manageable published artworks matched this search yet.'}
)}
) }