/** * Inspiration wall for the studio's empty canvas: a small grid of random * template cases sampled host-side across every library source. Clicking a * card hands its prompt to the form; the 随机 button re-rolls the pick. On * failure the wall collapses to nothing (the panel falls back to the plain * empty-state hint). */ import { useEffect, useState } from 'react' import { Button } from '@deepseek-ai/dsh-client-ui-primitives' import type { ImageGenApi } from './api.ts' import { tt } from './helpers.ts' import { TEMPLATES_API, type TemplateSample } from '../protocol.ts' import css from './inspiration.module.css' /** Card count per deal — a 4×3 wall that uses the canvas's spare width. */ const SAMPLE_COUNT = 12 /** Same-origin proxy URL of one sampled case's reference image. */ function imageUrlOf(sample: TemplateSample): string { return `${TEMPLATES_API.image}/${encodeURIComponent(sample.sourceId)}/${encodeURIComponent(sample.case.image)}` } /** One thumbnail that degrades to a text tile when the image 404s. */ function SampleThumb(props: { sample: TemplateSample }) { const [failed, setFailed] = useState(false) return ( {props.sample.case.image !== '' && !failed ? ( {props.sample.case.title} { setFailed(true) }} /> ) : ( )} {props.sample.case.title} ) } /** The random-case wall shown while the canvas has no results. */ export function InspirationGallery(props: { api: ImageGenApi /** Hand the picked prompt back to the studio form. */ onUse: (prompt: string) => void }) { const { api, onUse } = props const [samples, setSamples] = useState(null) const [loading, setLoading] = useState(false) const deal = (): void => { if (loading) return setLoading(true) api.templatesSample(SAMPLE_COUNT) .then(setSamples) .catch(() => { setSamples(current => current ?? []) }) .finally(() => { setLoading(false) }) } // Deal once on mount; shuffles re-use the same handler. useEffect(() => { deal() // eslint-disable-next-line react-hooks/exhaustive-deps }, []) // Sample fetch failed or the libraries are empty: collapse to the plain // empty-state hint so the canvas never looks broken. if (samples !== null && samples.length === 0) { return (
{tt('canvas.emptyTitle')} {tt('canvas.emptyHint')}
) } return (
{tt('inspiration.title')} {samples === null ? (
) }