@tangle-network/agent-app 0.45.64 → 0.45.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assistant/index.js +2 -2
- package/dist/chat-react/index.js +1 -1
- package/dist/{chunk-FZKNVQYP.js → chunk-23J72UUA.js} +104 -15
- package/dist/chunk-23J72UUA.js.map +1 -0
- package/dist/{chunk-OMGV3CX2.js → chunk-AWM4H5XR.js} +142 -34
- package/dist/chunk-AWM4H5XR.js.map +1 -0
- package/dist/{chunk-HSBJB46C.js → chunk-E2CWFUUP.js} +3 -58
- package/dist/chunk-E2CWFUUP.js.map +1 -0
- package/dist/stories/chat-controls/fixtures.d.ts +5 -1
- package/dist/stories/studio/fixtures.d.ts +0 -4
- package/dist/studio/generation.d.ts +2 -51
- package/dist/studio/index.d.ts +1 -2
- package/dist/studio/index.js +1 -11
- package/dist/studio-react/composer-hero.d.ts +1 -3
- package/dist/studio-react/index.d.ts +3 -5
- package/dist/studio-react/index.js +303 -510
- package/dist/studio-react/index.js.map +1 -1
- package/dist/studio-react/studio-workspace.d.ts +2 -4
- package/dist/web-react/chat-composer.d.ts +87 -5
- package/dist/web-react/composer-file-accept.d.ts +77 -0
- package/dist/web-react/index.d.ts +1 -0
- package/dist/web-react/index.js +10 -2
- package/dist/web-react/use-composer-attachments.d.ts +3 -4
- package/package.json +1 -1
- package/dist/chunk-FZKNVQYP.js.map +0 -1
- package/dist/chunk-HSBJB46C.js.map +0 -1
- package/dist/chunk-OMGV3CX2.js.map +0 -1
- package/dist/studio-react/publish-package-composer.d.ts +0 -18
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/studio-react/studio-workspace.tsx","../../src/studio-react/use-studio-generations.ts","../../src/studio-react/composer-hero.tsx","../../src/studio-react/type-config.ts","../../src/studio-react/composer-shell.tsx","../../src/studio-react/image-composer.tsx","../../src/studio-react/video-composer.tsx","../../src/studio-react/speech-composer.tsx","../../src/studio-react/avatar-composer.tsx","../../src/studio-react/transcription-composer.tsx","../../src/studio-react/publish-package-composer.tsx","../../src/studio-react/studio-header.tsx","../../src/studio-react/result-canvas.tsx","../../src/studio-react/library-drawer.tsx","../../src/studio-react/studio-sheet.tsx","../../src/studio-react/generation-grid.tsx","../../src/studio-react/generation-card.tsx","../../src/studio-react/generation-detail.tsx","../../src/studio-react/library-panel.tsx","../../src/studio-react/generation-detail-modal.tsx"],"sourcesContent":["import { useRef, useState } from 'react'\nimport { useSearchParams } from 'react-router'\nimport { Button } from '@tangle-network/sandbox-ui/primitives'\nimport { Images } from 'lucide-react'\nimport type { Generation } from '../studio'\nimport { useStudioGenerations } from './use-studio-generations'\nimport { ComposerHero } from './composer-hero'\nimport { StudioHeader } from './studio-header'\nimport { ResultCanvas } from './result-canvas'\nimport { LibraryDrawer } from './library-drawer'\n\nexport type StudioRole = 'owner' | 'admin' | 'editor' | 'viewer'\n\nexport interface StudioWorkspaceProps {\n generations: Generation[]\n totalCost: number\n workspaceId?: string\n role: StudioRole\n /** Polling endpoint override (default `/api/generations`). */\n generationsEndpoint?: string\n /** Build a vault link, optionally to a specific file. Defaults to `/app/<workspaceId>/vault`. */\n vaultHref?: (filePath?: string | null) => string\n /** Integrations page href for the publish-package \"Connect\" link. Defaults to `/app/<workspaceId>/integrations`. */\n integrationsHref?: string\n}\n\n/**\n * The full studio surface: header + composer + result canvas + library drawer,\n * with the generation orchestrator (merge/poll/revalidate) wired in. The host\n * route owns the loader (auth, RBAC, the generation query) and the server\n * endpoints (`/api/generate`, `/api/media-models`, `/api/generations`); this\n * shell renders that data and drives the live UI. Role gates the composer\n * (viewers get a read-only library) and the integration-management affordances.\n */\nexport function StudioWorkspace({\n generations,\n totalCost,\n workspaceId,\n role,\n generationsEndpoint,\n vaultHref,\n integrationsHref,\n}: StudioWorkspaceProps) {\n const [searchParams, setSearchParams] = useSearchParams()\n const typeFilter = searchParams.get('type')\n const [drawerOpen, setDrawerOpen] = useState(false)\n const [selected, setSelected] = useState<Generation | null>(null)\n const canvasRef = useRef<HTMLDivElement>(null)\n const canGenerate = role !== 'viewer'\n const canManageIntegrations = role === 'owner' || role === 'admin'\n // Default the navigation hrefs to the conventional /app/<workspaceId>/… routes;\n // a host on a different route scheme passes its own builders.\n const resolvedVaultHref = vaultHref ?? (workspaceId\n ? (filePath?: string | null) => (filePath\n ? `/app/${workspaceId}/vault?file=${encodeURIComponent(filePath)}`\n : `/app/${workspaceId}/vault`)\n : undefined)\n const resolvedIntegrationsHref = integrationsHref\n ?? (workspaceId ? `/app/${workspaceId}/integrations` : undefined)\n\n const { mergedGenerations, latestBatch, onGenerated } = useStudioGenerations(generations, {\n workspaceId,\n generationsEndpoint,\n })\n\n function setFilter(type: string | null) {\n if (type) setSearchParams({ type })\n else setSearchParams({})\n }\n\n function openLibrary() {\n setSelected(null)\n setDrawerOpen(true)\n }\n\n function openDetail(generation: Generation) {\n setSelected(generation)\n setDrawerOpen(true)\n }\n\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto bg-background\">\n <StudioHeader\n count={mergedGenerations.length}\n canGenerate={canGenerate}\n onOpenLibrary={openLibrary}\n />\n\n <div className=\"mx-auto w-full max-w-3xl space-y-4 px-4 py-6 sm:px-6\">\n {canGenerate ? (\n <>\n <ComposerHero\n workspaceId={workspaceId}\n integrationsHref={resolvedIntegrationsHref}\n canManageIntegrations={canManageIntegrations}\n onGenerated={(generation) => {\n onGenerated(generation)\n requestAnimationFrame(() => {\n canvasRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' })\n })\n }}\n />\n <div ref={canvasRef}>\n <ResultCanvas\n batch={latestBatch}\n onOpenLibrary={openLibrary}\n onSelect={openDetail}\n />\n </div>\n </>\n ) : (\n <section className=\"flex flex-col items-center justify-center gap-3 rounded-xl border border-border bg-card p-10 text-center shadow-sm\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <Images className=\"h-6 w-6 text-muted-foreground/40\" />\n </div>\n <p className=\"text-sm font-medium text-foreground\">\n {mergedGenerations.length > 0\n ? `${mergedGenerations.length} asset${mergedGenerations.length !== 1 ? 's' : ''} in this workspace`\n : 'No generations yet'}\n </p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">\n Team generations appear in the library.\n </p>\n <Button size=\"sm\" variant=\"outline\" onClick={openLibrary}>\n <Images className=\"mr-1.5 h-4 w-4\" />\n Open library\n </Button>\n </section>\n )}\n </div>\n\n <LibraryDrawer\n open={drawerOpen}\n onOpenChange={(open) => { setDrawerOpen(open); if (!open) setSelected(null) }}\n generations={mergedGenerations}\n totalCost={totalCost}\n typeFilter={typeFilter}\n onFilterChange={setFilter}\n vaultHref={resolvedVaultHref}\n selected={selected}\n onSelect={(generation) => { setSelected(generation); if (generation) setDrawerOpen(true) }}\n />\n </div>\n )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useRevalidator } from 'react-router'\nimport {\n type Generation,\n generationStatus,\n isLocalGeneration,\n latestBatchOf,\n mergeLiveGeneration,\n mergeLoaderAndLive,\n} from '../studio'\n\n/**\n * The generation orchestrator behind a studio surface: it merges the loader's\n * rows with in-flight live generations, computes the latest batch for the\n * canvas, polls running generations until they settle, and revalidates the\n * route loader when a status changes.\n *\n * The merge keeps the canvas, the library, and the polling path looking at the\n * same full list. Polling hits `generationsEndpoint` (default `/api/generations`,\n * the convention both apps already serve); pass an override if a product routes\n * it elsewhere. `onGenerated` is wired to the composer's per-result callback.\n */\nexport function useStudioGenerations(\n loaderGenerations: Generation[],\n options: { workspaceId?: string; generationsEndpoint?: string } = {},\n) {\n const { workspaceId, generationsEndpoint = '/api/generations' } = options\n const revalidator = useRevalidator()\n const [liveGenerations, setLiveGenerations] = useState<Generation[]>([])\n\n const mergedGenerations = useMemo(\n () => mergeLoaderAndLive(loaderGenerations, liveGenerations),\n [loaderGenerations, liveGenerations],\n )\n\n const latestBatch = useMemo(() => latestBatchOf(mergedGenerations), [mergedGenerations])\n\n const runningGenerationIds = useMemo(() => mergedGenerations\n .filter((gen) => {\n const status = generationStatus(gen)\n return status === 'pending' || status === 'running'\n })\n .map((gen) => gen.id)\n .filter((id) => !id.startsWith('local-')), [mergedGenerations])\n\n // The poll loop must not churn the effect. `runningGenerationIds` is a fresh\n // array every render and react-router's `revalidator` identity flips while a\n // revalidation is in flight — depending on either restarts the interval on\n // every tick, collapsing the 4s cadence into a request flood. Key the effect\n // on the STABLE join of the running ids (re-subscribe only when the set\n // actually changes) and reach the live ids / revalidate through refs.\n const runningIdsRef = useRef(runningGenerationIds)\n runningIdsRef.current = runningGenerationIds\n const revalidateRef = useRef(revalidator.revalidate)\n revalidateRef.current = revalidator.revalidate\n const runningKey = runningGenerationIds.join(',')\n\n useEffect(() => {\n if (!workspaceId || !runningKey) return\n let cancelled = false\n const poll = async () => {\n const responses = await Promise.all(runningIdsRef.current.map(async (id) => {\n const res = await fetch(`${generationsEndpoint}?workspaceId=${encodeURIComponent(workspaceId)}&id=${encodeURIComponent(id)}`)\n if (!res.ok) return null\n const data = await res.json() as { generation?: Generation }\n return data.generation ?? null\n }))\n if (cancelled) return\n const refreshed = responses.filter((gen): gen is Generation => Boolean(gen))\n if (refreshed.length > 0) {\n setLiveGenerations((current) => refreshed.reduce(mergeLiveGeneration, current))\n }\n if (refreshed.some((gen) => generationStatus(gen) !== 'running' && generationStatus(gen) !== 'pending')) {\n revalidateRef.current()\n }\n }\n const interval = window.setInterval(() => { void poll() }, 4_000)\n void poll()\n return () => {\n cancelled = true\n window.clearInterval(interval)\n }\n }, [runningKey, workspaceId, generationsEndpoint])\n\n const onGenerated = useCallback((generation: Generation) => {\n setLiveGenerations((current) => mergeLiveGeneration(current, generation))\n if (!isLocalGeneration(generation)) revalidateRef.current()\n }, [])\n\n return { mergedGenerations, latestBatch, onGenerated }\n}\n","import { useEffect, useMemo, useRef, useState } from 'react'\nimport {\n Badge, Button, Input, Label, Textarea,\n Select, SelectContent, SelectItem, SelectTrigger, SelectValue,\n} from '@tangle-network/sandbox-ui/primitives'\nimport { useIntegrations } from '@tangle-network/sandbox-ui/integrations'\nimport { Sparkles } from 'lucide-react'\nimport {\n type Generation,\n type GenerationType,\n type MediaModelCatalogResponse,\n CADENCES,\n DESTINATIONS,\n buildGenerationRequestBody,\n buildPublishPackage,\n failedOptimisticGeneration,\n isDestinationConnected,\n modelMessage,\n normalizeImageCount,\n optimisticGeneration,\n outputPathFor,\n preferredModelId,\n selectedModelsWithDefaults,\n userSafeGenerationMessage,\n} from '../studio'\nimport { TYPE_CONFIG, typeConfigFor } from './type-config'\nimport { ProviderLogo } from '../web-react/provider-logo'\nimport { ComposerDisclosure, Field } from './composer-shell'\nimport { ImageComposer } from './image-composer'\nimport { VideoComposer } from './video-composer'\nimport { SpeechComposer } from './speech-composer'\nimport { AvatarComposer } from './avatar-composer'\nimport { TranscriptionComposer, TranscriptionOptions } from './transcription-composer'\nimport { PublishPackageComposer } from './publish-package-composer'\n\nconst HUB_BASE_URL = '/api/integrations/hub'\n\nconst SUGGESTIONS: Array<{ label: string; prompt: string; type: GenerationType }> = [\n {\n label: 'Storyboard frame',\n type: 'image',\n prompt: 'A vertical storyboard frame for a product launch teaser — dark cinematic lighting, sleek studio aesthetic, 9:16 composition.',\n },\n {\n label: 'Launch teaser clip',\n type: 'video',\n prompt: 'A 6-second vertical launch teaser: animated product reveal, dynamic camera move, hero music swell.',\n },\n {\n label: 'Scratch voiceover',\n type: 'speech',\n prompt: 'A confident 12-second scratch voiceover for a product launch teaser: warm tone, conversational pace.',\n },\n {\n label: 'Transcribe dailies',\n type: 'transcription',\n prompt: 'Transcribe the latest dailies recording with timestamps, speaker labels, and key story beats highlighted.',\n },\n]\n\nexport function ComposerHero({\n workspaceId,\n integrationsHref,\n canManageIntegrations,\n align = 'start',\n surfaceClassName = 'bg-card',\n onGenerated,\n}: {\n workspaceId?: string\n integrationsHref?: string\n canManageIntegrations: boolean\n /** Heading treatment: `center` (focus mode) vs `start` (composer as a left rail). */\n align?: 'center' | 'start'\n /** Background of the composer card. Host apps pass their own surface token so\n * the card can share a tone with the app shell (e.g. the sidebar). */\n surfaceClassName?: string\n onGenerated: (generation: Generation) => void\n}) {\n const [type, setType] = useState<GenerationType>('image')\n const [prompt, setPrompt] = useState('')\n const [negativePrompt, setNegativePrompt] = useState('')\n const [outputPath, setOutputPath] = useState(outputPathFor('image'))\n const [caption, setCaption] = useState('')\n const [postDescription, setPostDescription] = useState('')\n const [mentions, setMentions] = useState('')\n const [cadence, setCadence] = useState(CADENCES[0] ?? 'Manual approval')\n const [selectedDestinations, setSelectedDestinations] = useState<string[]>([])\n const [size, setSize] = useState('1536x1024')\n const [quality, setQuality] = useState('high')\n const [imageCount, setImageCount] = useState(1)\n const [duration, setDuration] = useState('6')\n const [resolution, setResolution] = useState('720p')\n const [aspectRatio, setAspectRatio] = useState('16:9')\n const [referenceImageUrl, setReferenceImageUrl] = useState('')\n const [voice, setVoice] = useState('alloy')\n const [avatarAudioUrl, setAvatarAudioUrl] = useState('')\n const [avatarImageUrl, setAvatarImageUrl] = useState('')\n const [avatarId, setAvatarId] = useState('')\n const [transcriptionAudioUrl, setTranscriptionAudioUrl] = useState('')\n const [transcriptionLanguage, setTranscriptionLanguage] = useState('')\n const [transcriptionResponseFormat, setTranscriptionResponseFormat] = useState('json')\n const [transcriptionTemperature, setTranscriptionTemperature] = useState('0')\n const [mediaModels, setMediaModels] = useState<MediaModelCatalogResponse | null>(null)\n const [mediaModelsLoading, setMediaModelsLoading] = useState(false)\n const [mediaModelsError, setMediaModelsError] = useState<string | null>(null)\n const [selectedModels, setSelectedModels] = useState<Partial<Record<GenerationType, string>>>({})\n const submitLockRef = useRef(false)\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const modelsForType = mediaModels?.models[type] ?? []\n const selectedModel = selectedModels[type] ?? preferredModelId(type, mediaModels) ?? ''\n const selectedModelOption = modelsForType.find((model) => model.id === selectedModel)\n const modelReady = Boolean(selectedModelOption)\n && selectedModelOption?.status !== 'unavailable'\n && !mediaModelsLoading\n && !mediaModelsError\n const hasRequiredInput = type === 'transcription'\n ? Boolean(transcriptionAudioUrl.trim())\n : type === 'avatar'\n ? Boolean(avatarAudioUrl.trim())\n : Boolean(prompt.trim())\n const canSubmit = Boolean(workspaceId)\n && modelReady\n && hasRequiredInput\n && !isSubmitting\n const integrations = useIntegrations({ apiBaseUrl: HUB_BASE_URL })\n const selectedConnectedDestinations = useMemo(() => selectedDestinations.filter((destinationId) => {\n const destination = DESTINATIONS.find((item) => item.id === destinationId)\n return Boolean(destination && isDestinationConnected(destination, integrations.connections))\n }), [integrations.connections, selectedDestinations])\n\n useEffect(() => {\n if (!workspaceId) return\n let cancelled = false\n setMediaModelsLoading(true)\n setMediaModelsError(null)\n\n fetch(`/api/media-models?workspaceId=${encodeURIComponent(workspaceId)}`)\n .then(async (res) => {\n const data = await res.json() as MediaModelCatalogResponse\n if (!res.ok) throw new Error(data.error ?? 'Could not load media models')\n return data\n })\n .then((data) => {\n if (cancelled) return\n setMediaModels(data)\n setSelectedModels((current) => selectedModelsWithDefaults(current, data))\n })\n .catch(() => {\n if (cancelled) return\n setMediaModels(null)\n // Never surface the raw fetch/parse error — a non-JSON 404 page reads\n // as `Unexpected token 'N', \"Not Found\" is not valid JSON` to users.\n setMediaModelsError('Could not load media models')\n })\n .finally(() => {\n if (!cancelled) setMediaModelsLoading(false)\n })\n\n return () => {\n cancelled = true\n }\n }, [workspaceId])\n\n function changeType(next: GenerationType) {\n setType(next)\n setOutputPath(outputPathFor(next))\n }\n\n async function generate() {\n if (!workspaceId || submitLockRef.current) return\n const promptText = prompt.trim()\n const avatarAudioUrlText = avatarAudioUrl.trim()\n const transcriptionAudioUrlText = transcriptionAudioUrl.trim()\n if (type !== 'transcription' && type !== 'avatar' && !promptText) {\n setError('prompt is required')\n return\n }\n if (type === 'avatar' && !avatarAudioUrlText) {\n setError('audioUrl is required')\n return\n }\n if (type === 'transcription' && !transcriptionAudioUrlText) {\n setError('audioUrl is required')\n return\n }\n if (!selectedModelOption || selectedModelOption.status === 'unavailable') {\n setError(`Select an available ${typeConfigFor(type).label} model`)\n return\n }\n if (cadence === 'Publish now' && selectedConnectedDestinations.length === 0) {\n setError('Select a connected destination to publish now')\n return\n }\n submitLockRef.current = true\n setIsSubmitting(true)\n setError(null)\n const clientRequestId = crypto.randomUUID()\n const requestedImageCount = type === 'image' ? normalizeImageCount(imageCount) : 1\n if (type === 'image' && requestedImageCount !== imageCount) setImageCount(requestedImageCount)\n const localGenerations = Array.from({ length: requestedImageCount }, (_, outputIndex) => optimisticGeneration({\n type,\n // avatar hides the prompt field (promptText is stale); transcription's is\n // an optional vocab hint. Never surface the source audio URL as the prompt.\n prompt: type === 'avatar' ? '' : promptText,\n model: selectedModel,\n clientRequestId,\n outputIndex: type === 'image' ? outputIndex : undefined,\n outputCount: type === 'image' ? requestedImageCount : undefined,\n }))\n localGenerations.slice().reverse().forEach(onGenerated)\n setPrompt('')\n let receivedServerGeneration = false\n try {\n const body = buildGenerationRequestBody({\n workspaceId,\n clientRequestId,\n type,\n model: selectedModel,\n prompt,\n negativePrompt,\n outputPath,\n publishPackage: buildPublishPackage({\n caption,\n postDescription,\n mentions,\n cadence,\n destinations: selectedConnectedDestinations,\n }),\n image: { size, quality, count: requestedImageCount },\n video: { duration, resolution, aspectRatio, referenceImageUrl },\n speech: { voice },\n avatar: { audioUrl: avatarAudioUrl, imageUrl: avatarImageUrl, avatarId },\n transcription: {\n audioUrl: transcriptionAudioUrl,\n language: transcriptionLanguage,\n responseFormat: transcriptionResponseFormat,\n temperature: transcriptionTemperature,\n },\n })\n\n const res = await fetch('/api/generate', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n const data = await res.json() as { generation?: Generation; generations?: Generation[]; error?: string }\n const serverGenerations = data.generations?.length ? data.generations : data.generation ? [data.generation] : []\n if (serverGenerations.length > 0) {\n receivedServerGeneration = true\n serverGenerations.slice().reverse().forEach(onGenerated)\n }\n if (!res.ok || serverGenerations.length === 0) throw new Error(data.error ?? 'Generation failed')\n } catch (err) {\n if (!receivedServerGeneration) localGenerations.map(failedOptimisticGeneration).forEach(onGenerated)\n setError(err instanceof Error ? userSafeGenerationMessage(err.message) : 'Generation failed')\n } finally {\n submitLockRef.current = false\n setIsSubmitting(false)\n }\n }\n\n const mediaTypes = Object.entries(TYPE_CONFIG) as Array<[GenerationType, typeof TYPE_CONFIG[string]]>\n\n return (\n <section className={`rounded-2xl border border-border p-5 shadow-sm ${surfaceClassName}`}>\n <div className={`mb-5 ${align === 'center' ? 'text-center' : 'text-left'}`}>\n <h2\n className={`font-semibold tracking-tight text-foreground transition-all duration-300 ${\n align === 'center' ? 'text-xl' : 'text-base'\n }`}\n >\n Media Generation\n </h2>\n </div>\n\n <div role=\"tablist\" aria-label=\"Generation type\" className=\"grid grid-cols-5 gap-1.5\">\n {mediaTypes.map(([key, cfg]) => {\n const Icon = cfg.icon\n const active = type === key\n return (\n <button\n key={key}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n onClick={() => changeType(key)}\n className={`flex flex-col items-center gap-1.5 rounded-lg border px-1 pb-2 pt-2.5 text-xs transition-all ${\n active\n ? 'border-primary/30 bg-primary/10 font-semibold text-primary'\n : 'border-border bg-background font-medium text-muted-foreground hover:border-foreground/20 hover:text-foreground'\n }`}\n >\n <Icon className=\"h-[17px] w-[17px] shrink-0\" />\n <span className=\"truncate\">{cfg.label}</span>\n </button>\n )\n })}\n </div>\n\n {type !== 'avatar' && (\n <div className=\"mt-5\">\n <Label\n htmlFor=\"studio-prompt\"\n className=\"mb-1.5 block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\"\n >\n Prompt\n </Label>\n <div className=\"rounded-xl border border-border bg-background transition-colors focus-within:border-primary/30 focus-within:ring-[3px] focus-within:ring-primary/10\">\n <textarea\n id=\"studio-prompt\"\n value={prompt}\n onChange={(event) => setPrompt(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n void generate()\n }\n }}\n rows={4}\n placeholder={type === 'transcription'\n ? 'Optional vocabulary, speaker names, timestamp style, or context...'\n : 'A vertical hero frame for a product launch teaser, dark cinematic lighting...'}\n className=\"block min-h-[96px] w-full resize-none border-0 bg-transparent px-3.5 pb-1.5 pt-3 text-sm leading-relaxed outline-none placeholder:text-muted-foreground\"\n />\n <div className=\"flex flex-wrap items-center gap-1.5 px-2.5 pb-2.5\">\n {SUGGESTIONS.map((suggestion) => (\n <button\n key={suggestion.label}\n type=\"button\"\n onClick={() => {\n setPrompt(suggestion.prompt)\n changeType(suggestion.type)\n }}\n className=\"rounded-full border border-border bg-background px-2.5 py-1 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/30 hover:text-primary\"\n >\n {suggestion.label}\n </button>\n ))}\n </div>\n </div>\n {type === 'transcription' && (\n <p className=\"mt-2 text-xs text-muted-foreground\">\n Optional — biases spelling, vocabulary, and speaker names (not an instruction).\n </p>\n )}\n </div>\n )}\n\n {type === 'avatar' && (\n <AvatarComposer\n audioUrl={avatarAudioUrl}\n imageUrl={avatarImageUrl}\n avatarId={avatarId}\n onAudioUrlChange={setAvatarAudioUrl}\n onImageUrlChange={setAvatarImageUrl}\n onAvatarIdChange={setAvatarId}\n />\n )}\n {type === 'transcription' && (\n <TranscriptionComposer\n audioUrl={transcriptionAudioUrl}\n language={transcriptionLanguage}\n onAudioUrlChange={setTranscriptionAudioUrl}\n onLanguageChange={setTranscriptionLanguage}\n />\n )}\n\n <div className=\"mt-5 space-y-3\">\n <div className=\"space-y-1.5\">\n <Field label=\"Model\" htmlFor=\"studio-media-model\">\n <Select\n value={selectedModel || undefined}\n onValueChange={(value) => setSelectedModels((current) => ({ ...current, [type]: value }))}\n disabled={mediaModelsLoading || Boolean(mediaModelsError) || modelsForType.length === 0}\n >\n <SelectTrigger id=\"studio-media-model\" className=\"h-9 w-full bg-background\">\n {selectedModelOption ? (\n <span className=\"flex min-w-0 items-center gap-2\">\n {selectedModelOption.provider && (\n <ProviderLogo provider={selectedModelOption.provider} size={14} />\n )}\n <span className=\"truncate\">{selectedModelOption.name || selectedModelOption.id}</span>\n {selectedModelOption.provider && (\n <span className=\"shrink-0 text-muted-foreground\">· {selectedModelOption.provider}</span>\n )}\n {selectedModelOption.status !== 'available' && (\n <span className=\"shrink-0 rounded-full bg-warning/10 px-1.5 py-0.5 text-xs font-semibold uppercase tracking-[0.05em] text-warning\">\n {selectedModelOption.status}\n </span>\n )}\n </span>\n ) : (\n <SelectValue placeholder={mediaModelsLoading ? 'Loading models…' : 'Select a model'} />\n )}\n </SelectTrigger>\n <SelectContent className=\"bg-background\">\n {modelsForType.map((model) => (\n <SelectItem key={model.id} value={model.id} disabled={model.status === 'unavailable'}>\n <span className=\"flex w-full items-center justify-between gap-3\">\n <span className=\"flex min-w-0 items-center gap-2\">\n {model.provider && <ProviderLogo provider={model.provider} size={14} />}\n <span className=\"truncate\">\n {model.name || model.id}{model.provider ? ` · ${model.provider}` : ''}\n </span>\n </span>\n {model.status !== 'available' && (\n <span className=\"shrink-0 text-xs capitalize text-muted-foreground\">{model.status}</span>\n )}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </Field>\n {(mediaModelsError || modelMessage(selectedModelOption, mediaModelsLoading, modelsForType.length)) && (\n <p className={`text-xs ${mediaModelsError || selectedModelOption?.status === 'unavailable' ? 'text-destructive' : 'text-muted-foreground'}`}>\n {mediaModelsError ?? modelMessage(selectedModelOption, mediaModelsLoading, modelsForType.length)}\n </p>\n )}\n </div>\n {type === 'image' && (\n <ImageComposer\n size={size}\n quality={quality}\n imageCount={imageCount}\n onSizeChange={setSize}\n onQualityChange={setQuality}\n onImageCountChange={setImageCount}\n />\n )}\n {type === 'video' && (\n <VideoComposer\n duration={duration}\n resolution={resolution}\n aspectRatio={aspectRatio}\n referenceImageUrl={referenceImageUrl}\n onDurationChange={setDuration}\n onResolutionChange={setResolution}\n onAspectRatioChange={setAspectRatio}\n onReferenceImageUrlChange={setReferenceImageUrl}\n />\n )}\n {type === 'speech' && (\n <SpeechComposer voice={voice} onVoiceChange={setVoice} />\n )}\n </div>\n\n <div className=\"mt-4 space-y-2\">\n <ComposerDisclosure summary=\"Advanced options\">\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Negative prompt\">\n <Textarea\n value={negativePrompt}\n onChange={(event) => setNegativePrompt(event.target.value)}\n rows={2}\n placeholder=\"Avoid artifacts, off-style composition...\"\n className=\"bg-background\"\n />\n </Field>\n <Field label=\"Save to\">\n <Input value={outputPath} onChange={(event) => setOutputPath(event.target.value)} className=\"bg-background\" />\n </Field>\n {type === 'transcription' && (\n <TranscriptionOptions\n responseFormat={transcriptionResponseFormat}\n temperature={transcriptionTemperature}\n onResponseFormatChange={setTranscriptionResponseFormat}\n onTemperatureChange={setTranscriptionTemperature}\n />\n )}\n </div>\n </ComposerDisclosure>\n\n <ComposerDisclosure\n summary={(\n <>\n Schedule a post\n {selectedConnectedDestinations.length > 0 && (\n <Badge variant=\"outline\" className=\"ml-1 text-xs\">\n {selectedConnectedDestinations.length}\n </Badge>\n )}\n </>\n )}\n >\n <PublishPackageComposer\n caption={caption}\n postDescription={postDescription}\n mentions={mentions}\n cadence={cadence}\n selectedDestinations={selectedDestinations}\n connections={integrations.connections}\n connectionError={integrations.error}\n connectionsLoading={integrations.isLoading}\n integrationsHref={integrationsHref}\n canManageIntegrations={canManageIntegrations}\n onCaptionChange={setCaption}\n onDescriptionChange={setPostDescription}\n onMentionsChange={setMentions}\n onCadenceChange={setCadence}\n onDestinationToggle={(destination) => {\n const destinationConfig = DESTINATIONS.find((item) => item.id === destination)\n if (!destinationConfig || !isDestinationConnected(destinationConfig, integrations.connections)) return\n setSelectedDestinations((current) => current.includes(destination)\n ? current.filter((item) => item !== destination)\n : [...current, destination])\n }}\n />\n </ComposerDisclosure>\n </div>\n\n {error && (\n <div className=\"mt-4 rounded-md border border-destructive/20 bg-destructive/10 p-3 text-sm text-destructive\">\n {error}\n </div>\n )}\n\n <Button\n onClick={generate}\n disabled={!canSubmit}\n size=\"lg\"\n className=\"mt-5 w-full disabled:bg-muted disabled:text-muted-foreground disabled:opacity-100\"\n >\n <Sparkles className=\"mr-2 h-4 w-4\" />\n Generate\n <span className=\"ml-2 text-xs opacity-60\">⌘↵</span>\n </Button>\n </section>\n )\n}\n","import { FileText, Image, Mic, User, Video } from 'lucide-react'\n\n/** Define configuration options for a type including label, icon, and color properties */\nexport interface TypeConfig {\n label: string\n icon: typeof Image\n color: string\n}\n\n/* Type badges sit on top of media thumbnails, where a per-type hue is\n illegible and off-token — every type gets the same neutral scrim chip\n (no backdrop-blur, so the thumbnail doesn't smear through). The type\n icon inside the badge carries the identity instead of a color. */\nconst MEDIA_SCRIM = 'bg-black/60 text-white border-white/10'\n\nconst IMAGE: TypeConfig = { label: 'Image', icon: Image, color: MEDIA_SCRIM }\n\n// string-keyed so list cards can index by Generation.type\n/** Map type keys to their corresponding configuration objects including labels, icons, and colors */\nexport const TYPE_CONFIG: Record<string, TypeConfig> = {\n image: IMAGE,\n video: { label: 'Video', icon: Video, color: MEDIA_SCRIM },\n avatar: { label: 'Avatar', icon: User, color: MEDIA_SCRIM },\n speech: { label: 'Audio', icon: Mic, color: MEDIA_SCRIM },\n transcription: { label: 'Transcript', icon: FileText, color: MEDIA_SCRIM },\n}\n\n// Safe lookup for an arbitrary `Generation.type` — always defined (the table is\n// declared `Record<string, …>`, so a raw index is `T | undefined`). Falls back\n// to the image config, matching the prior `?? TYPE_CONFIG.image` call sites.\n/** Resolve the configuration object for a given type or return the default image configuration */\nexport function typeConfigFor(type: string): TypeConfig {\n return TYPE_CONFIG[type] ?? IMAGE\n}\n","import type { ReactNode, SelectHTMLAttributes } from 'react'\nimport { Label } from '@tangle-network/sandbox-ui/primitives'\nimport { ChevronRight, Minus, Plus } from 'lucide-react'\n\nexport function Field({\n label,\n htmlFor,\n className = 'space-y-1.5',\n children,\n}: {\n label: string\n htmlFor?: string\n className?: string\n children: ReactNode\n}) {\n return (\n <div className={className}>\n <Label\n htmlFor={htmlFor}\n className=\"text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\"\n >\n {label}\n </Label>\n {children}\n </div>\n )\n}\n\nexport function Stepper({\n value,\n min,\n max,\n onChange,\n}: {\n value: number\n min: number\n max: number\n onChange: (value: number) => void\n}) {\n return (\n <div className=\"flex h-9 items-center justify-between rounded-md border border-input bg-background px-1.5\">\n <button\n type=\"button\"\n aria-label=\"Decrease\"\n onClick={() => onChange(Math.max(min, value - 1))}\n disabled={value <= min}\n className=\"flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-40\"\n >\n <Minus className=\"h-3.5 w-3.5\" />\n </button>\n <span className=\"text-sm font-medium tabular-nums\">{value}</span>\n <button\n type=\"button\"\n aria-label=\"Increase\"\n onClick={() => onChange(Math.min(max, value + 1))}\n disabled={value >= max}\n className=\"flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-40\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n )\n}\n\nexport function ComposerDisclosure({ summary, children }: { summary: ReactNode; children: ReactNode }) {\n return (\n <details className=\"group rounded-lg border border-border bg-background transition-colors\">\n <summary className=\"flex cursor-pointer list-none items-center gap-1.5 px-3 py-2.5 text-xs font-medium text-foreground/80 transition-colors hover:text-foreground [&::-webkit-details-marker]:hidden\">\n <ChevronRight className=\"h-3.5 w-3.5 text-muted-foreground transition-transform group-open:rotate-90\" />\n {summary}\n </summary>\n <div className=\"border-t border-border px-3 py-3\">{children}</div>\n </details>\n )\n}\n\nexport function NativeSelect(props: SelectHTMLAttributes<HTMLSelectElement>) {\n return (\n <select {...props} className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm\" />\n )\n}\n","import { Input } from '@tangle-network/sandbox-ui/primitives'\nimport {\n IMAGE_QUALITIES,\n IMAGE_SIZE_HINT,\n IMAGE_SIZE_PATTERN,\n MIN_IMAGE_COUNT,\n MAX_IMAGE_COUNT,\n normalizeImageCount,\n} from '../studio'\nimport { Field, NativeSelect, Stepper } from './composer-shell'\n\nexport function ImageComposer({\n size,\n quality,\n imageCount,\n onSizeChange,\n onQualityChange,\n onImageCountChange,\n}: {\n size: string\n quality: string\n imageCount: number\n onSizeChange: (value: string) => void\n onQualityChange: (value: string) => void\n onImageCountChange: (value: number) => void\n}) {\n return (\n <div className=\"space-y-3\">\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Size\">\n <Input\n value={size}\n onChange={(event) => onSizeChange(event.target.value)}\n pattern={IMAGE_SIZE_PATTERN}\n placeholder={IMAGE_SIZE_HINT}\n className=\"bg-background\"\n />\n </Field>\n <Field label=\"Quality\">\n <NativeSelect value={quality} onChange={(event) => onQualityChange(event.target.value)}>\n {IMAGE_QUALITIES.map((option) => (\n <option key={option} value={option}>{option.charAt(0).toUpperCase() + option.slice(1)}</option>\n ))}\n </NativeSelect>\n </Field>\n </div>\n <Field label=\"Images\">\n <Stepper\n value={imageCount}\n min={MIN_IMAGE_COUNT}\n max={MAX_IMAGE_COUNT}\n onChange={(value) => onImageCountChange(normalizeImageCount(value))}\n />\n </Field>\n </div>\n )\n}\n","import { Input } from '@tangle-network/sandbox-ui/primitives'\nimport { VIDEO_ASPECT_RATIOS, VIDEO_DURATIONS, VIDEO_RESOLUTIONS } from '../studio'\nimport { Field, NativeSelect } from './composer-shell'\n\nexport function VideoComposer({\n duration,\n resolution,\n aspectRatio,\n referenceImageUrl,\n onDurationChange,\n onResolutionChange,\n onAspectRatioChange,\n onReferenceImageUrlChange,\n}: {\n duration: string\n resolution: string\n aspectRatio: string\n referenceImageUrl: string\n onDurationChange: (value: string) => void\n onResolutionChange: (value: string) => void\n onAspectRatioChange: (value: string) => void\n onReferenceImageUrlChange: (value: string) => void\n}) {\n return (\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Duration (s)\">\n <NativeSelect value={duration} onChange={(event) => onDurationChange(event.target.value)}>\n {VIDEO_DURATIONS.map((option) => <option key={option} value={option}>{option}</option>)}\n </NativeSelect>\n </Field>\n <Field label=\"Resolution\">\n <NativeSelect value={resolution} onChange={(event) => onResolutionChange(event.target.value)}>\n {VIDEO_RESOLUTIONS.map((option) => <option key={option} value={option}>{option}</option>)}\n </NativeSelect>\n </Field>\n <Field label=\"Aspect ratio\">\n <NativeSelect value={aspectRatio} onChange={(event) => onAspectRatioChange(event.target.value)}>\n {VIDEO_ASPECT_RATIOS.map((option) => <option key={option} value={option}>{option}</option>)}\n </NativeSelect>\n </Field>\n <Field label=\"Reference image URL\"><Input value={referenceImageUrl} onChange={(event) => onReferenceImageUrlChange(event.target.value)} className=\"bg-background\" /></Field>\n </div>\n )\n}\n","import { Input } from '@tangle-network/sandbox-ui/primitives'\nimport { Field } from './composer-shell'\n\nexport function SpeechComposer({\n voice,\n onVoiceChange,\n}: {\n voice: string\n onVoiceChange: (value: string) => void\n}) {\n return (\n <Field label=\"Voice\"><Input value={voice} onChange={(event) => onVoiceChange(event.target.value)} className=\"bg-background\" /></Field>\n )\n}\n","import { Input } from '@tangle-network/sandbox-ui/primitives'\nimport { Field } from './composer-shell'\n\nexport function AvatarComposer({\n audioUrl,\n imageUrl,\n avatarId,\n onAudioUrlChange,\n onImageUrlChange,\n onAvatarIdChange,\n}: {\n audioUrl: string\n imageUrl: string\n avatarId: string\n onAudioUrlChange: (value: string) => void\n onImageUrlChange: (value: string) => void\n onAvatarIdChange: (value: string) => void\n}) {\n return (\n <div className=\"mt-4 grid gap-3 sm:grid-cols-2\">\n <Field label=\"Audio URL\" htmlFor=\"studio-audio-url\">\n <Input\n id=\"studio-audio-url\"\n value={audioUrl}\n onChange={(event) => onAudioUrlChange(event.target.value)}\n placeholder=\"https://cdn.example.com/source-audio.mp3\"\n className=\"bg-background\"\n />\n </Field>\n <Field label=\"Image URL\" htmlFor=\"studio-avatar-image-url\">\n <Input\n id=\"studio-avatar-image-url\"\n value={imageUrl}\n onChange={(event) => onImageUrlChange(event.target.value)}\n placeholder=\"https://cdn.example.com/portrait.png\"\n className=\"bg-background\"\n />\n </Field>\n <Field label=\"Avatar ID\" htmlFor=\"studio-avatar-id\">\n <Input\n id=\"studio-avatar-id\"\n value={avatarId}\n onChange={(event) => onAvatarIdChange(event.target.value)}\n placeholder=\"Optional provider avatar id\"\n className=\"bg-background\"\n />\n </Field>\n </div>\n )\n}\n","import { Input } from '@tangle-network/sandbox-ui/primitives'\nimport { Field, NativeSelect } from './composer-shell'\n\nexport function TranscriptionComposer({\n audioUrl,\n language,\n onAudioUrlChange,\n onLanguageChange,\n}: {\n audioUrl: string\n language: string\n onAudioUrlChange: (value: string) => void\n onLanguageChange: (value: string) => void\n}) {\n return (\n <div className=\"mt-4 grid gap-3 sm:grid-cols-2\">\n <Field label=\"Audio URL\" htmlFor=\"studio-audio-url\">\n <Input\n id=\"studio-audio-url\"\n value={audioUrl}\n onChange={(event) => onAudioUrlChange(event.target.value)}\n placeholder=\"https://cdn.example.com/source-audio.mp3\"\n className=\"bg-background\"\n />\n </Field>\n <Field label=\"Language\" htmlFor=\"studio-transcription-language\">\n <Input\n id=\"studio-transcription-language\"\n value={language}\n onChange={(event) => onLanguageChange(event.target.value)}\n placeholder=\"en\"\n className=\"bg-background\"\n />\n </Field>\n </div>\n )\n}\n\nexport function TranscriptionOptions({\n responseFormat,\n temperature,\n onResponseFormatChange,\n onTemperatureChange,\n}: {\n responseFormat: string\n temperature: string\n onResponseFormatChange: (value: string) => void\n onTemperatureChange: (value: string) => void\n}) {\n return (\n <>\n <Field label=\"Response format\">\n <NativeSelect value={responseFormat} onChange={(event) => onResponseFormatChange(event.target.value)}>\n <option value=\"json\">JSON</option>\n <option value=\"text\">Text</option>\n <option value=\"srt\">SRT</option>\n <option value=\"verbose_json\">Verbose JSON</option>\n <option value=\"vtt\">VTT</option>\n </NativeSelect>\n </Field>\n <Field label=\"Temperature\"><Input type=\"number\" min=\"0\" max=\"1\" step=\"0.1\" value={temperature} onChange={(event) => onTemperatureChange(event.target.value)} className=\"bg-background\" /></Field>\n </>\n )\n}\n","import { Link } from 'react-router'\nimport { Badge, Button, Input, Textarea } from '@tangle-network/sandbox-ui/primitives'\nimport { ProviderIcon, type IntegrationConnection } from '@tangle-network/sandbox-ui/integrations'\nimport { AlertTriangle, Check } from 'lucide-react'\nimport { CADENCES, DESTINATIONS, isDestinationConnected } from '../studio'\nimport { Field, NativeSelect } from './composer-shell'\n\nexport function PublishPackageComposer({\n caption,\n postDescription,\n mentions,\n cadence,\n selectedDestinations,\n connections,\n connectionError,\n connectionsLoading,\n integrationsHref,\n canManageIntegrations,\n onCaptionChange,\n onDescriptionChange,\n onMentionsChange,\n onCadenceChange,\n onDestinationToggle,\n}: {\n caption: string\n postDescription: string\n mentions: string\n cadence: string\n selectedDestinations: string[]\n connections: IntegrationConnection[]\n connectionError: Error | null\n connectionsLoading: boolean\n integrationsHref?: string\n canManageIntegrations: boolean\n onCaptionChange: (value: string) => void\n onDescriptionChange: (value: string) => void\n onMentionsChange: (value: string) => void\n onCadenceChange: (value: string) => void\n onDestinationToggle: (destination: string) => void\n}) {\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between gap-3\">\n {connectionError ? (\n <div className=\"flex items-center gap-2 rounded-md border border-warning/25 bg-warning/10 px-2.5 py-1.5 text-xs text-warning\">\n <AlertTriangle className=\"h-3.5 w-3.5 shrink-0\" />\n Couldn't load connected apps. Check Integrations.\n </div>\n ) : (\n <p className=\"text-xs text-muted-foreground\">\n {connectionsLoading\n ? 'Checking connected apps…'\n : 'Saved with the generated asset.'}\n </p>\n )}\n {integrationsHref && canManageIntegrations && (\n <Link to={integrationsHref} prefetch=\"intent\" className=\"shrink-0\">\n <Button variant=\"outline\" size=\"sm\">Connect</Button>\n </Link>\n )}\n </div>\n <div className=\"grid gap-2\">\n {DESTINATIONS.map((destination) => {\n const connected = isDestinationConnected(destination, connections)\n const active = connected && selectedDestinations.includes(destination.id)\n return (\n <button\n key={destination.id}\n type=\"button\"\n disabled={!connected}\n aria-pressed={active}\n onClick={() => onDestinationToggle(destination.id)}\n className={`rounded-md border p-2 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-60 ${\n active\n ? 'border-primary bg-primary/10 ring-1 ring-primary/20'\n : 'border-border bg-background hover:bg-accent'\n }`}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"flex items-center gap-1.5 text-xs font-medium text-foreground\">\n {active && <Check className=\"h-3.5 w-3.5 text-primary\" />}\n <ProviderIcon id={destination.providerIds[0] ?? destination.id} displayName={destination.label} size={16} className=\"rounded\" />\n {destination.label}\n </span>\n <Badge variant={active || connected ? 'default' : 'outline'}>{active ? 'Selected' : connected ? 'Ready' : 'Not connected'}</Badge>\n </div>\n <p className=\"mt-1 text-xs text-muted-foreground\">{destination.fields}</p>\n </button>\n )\n })}\n </div>\n <Field label=\"Caption\" className=\"space-y-2\">\n <Textarea value={caption} onChange={(event) => onCaptionChange(event.target.value)} rows={3} placeholder=\"Write or generate the caption for selected destinations...\" className=\"bg-background\" />\n </Field>\n <Field label=\"Description / CTA\" className=\"space-y-2\">\n <Textarea value={postDescription} onChange={(event) => onDescriptionChange(event.target.value)} rows={2} placeholder=\"Release note, product context, link, or approval instruction...\" className=\"bg-background\" />\n </Field>\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Mentions\" className=\"space-y-2\">\n <Input value={mentions} onChange={(event) => onMentionsChange(event.target.value)} placeholder=\"@creator, @partner\" className=\"bg-background\" />\n </Field>\n <Field label=\"Cadence\" className=\"space-y-2\">\n <NativeSelect value={cadence} onChange={(event) => onCadenceChange(event.target.value)}>\n {CADENCES.map((option) => <option key={option} value={option}>{option}</option>)}\n </NativeSelect>\n </Field>\n </div>\n </div>\n )\n}\n","import { Button } from '@tangle-network/sandbox-ui/primitives'\nimport { Images } from 'lucide-react'\n\nexport function StudioHeader({\n count,\n onOpenLibrary,\n canGenerate,\n}: {\n count: number\n onOpenLibrary: () => void\n canGenerate: boolean\n}) {\n return (\n <header className=\"sticky top-0 z-20 border-b border-border bg-card\">\n <div className=\"mx-auto flex w-full max-w-3xl items-center justify-between gap-3 px-4 py-3 sm:px-6\">\n <div className=\"min-w-0\">\n <h1 className=\"text-lg font-semibold tracking-tight text-foreground\">Studio</h1>\n <p className=\"truncate text-xs text-muted-foreground\">\n {canGenerate\n ? 'Generate images, video, voice, avatars, and transcripts.'\n : \"Browse your team's generations.\"}\n </p>\n </div>\n <Button size=\"sm\" variant=\"outline\" onClick={onOpenLibrary} className=\"shrink-0\">\n <Images className=\"mr-1.5 h-4 w-4\" />\n Library\n {count > 0 && (\n <span className=\"ml-2 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-primary/15 px-1.5 text-xs font-semibold text-primary\">\n {count}\n </span>\n )}\n </Button>\n </div>\n </header>\n )\n}\n","import { Badge } from '@tangle-network/sandbox-ui/primitives'\nimport { ArrowRight, Sparkles } from 'lucide-react'\nimport {\n type Generation,\n generationError,\n generationStatus,\n} from '../studio'\nimport { typeConfigFor } from './type-config'\n\nexport function ResultCanvas({\n batch,\n onOpenLibrary,\n onSelect,\n}: {\n batch: Generation[]\n onOpenLibrary: () => void\n onSelect: (generation: Generation) => void\n}) {\n const cardClass = 'rounded-xl border border-border bg-card shadow-sm'\n\n if (batch.length === 0) {\n return (\n <section className={`${cardClass} flex min-h-[180px] flex-col items-center justify-center gap-2 p-8 text-center`}>\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <Sparkles className=\"h-6 w-6 text-muted-foreground/40\" />\n </div>\n <p className=\"text-sm font-medium text-foreground\">Your creations appear here</p>\n <p className=\"max-w-xs text-xs text-muted-foreground\">\n Generate above — results appear here and are saved to your library.\n </p>\n </section>\n )\n }\n\n const cfg = typeConfigFor(batch[0]?.type ?? 'image')\n const Icon = cfg.icon\n const statuses = batch.map(generationStatus)\n const runLabel = statuses.some((s) => s === 'pending' || s === 'running')\n ? 'Generating…'\n : statuses.every((s) => s === 'failed')\n ? 'Last run failed'\n : 'Latest creation'\n const isWorking = statuses.some((s) => s === 'pending' || s === 'running')\n\n return (\n <section className={`${cardClass} p-5`}>\n <div className=\"mb-3 flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"outline\" className={`${cfg.color} gap-1 text-xs`}>\n <Icon className=\"h-3 w-3\" />\n {cfg.label}\n </Badge>\n <span className=\"text-sm font-medium text-foreground\">{runLabel}</span>\n {isWorking && <span className=\"h-2 w-2 animate-pulse rounded-full bg-primary\" />}\n </div>\n <button\n type=\"button\"\n onClick={onOpenLibrary}\n className=\"flex items-center gap-1 text-xs font-medium text-primary transition-colors hover:text-primary/80\"\n >\n View in Library\n <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n\n <div className={`grid gap-3 ${batch.length === 1 ? 'grid-cols-1' : 'grid-cols-2'}`}>\n {batch.map((generation) => (\n <button\n key={generation.id}\n type=\"button\"\n onClick={() => onSelect(generation)}\n className=\"studio-bloom group relative aspect-video overflow-hidden rounded-lg border border-border bg-secondary transition-colors hover:border-primary/40\"\n >\n <CanvasTile generation={generation} />\n </button>\n ))}\n </div>\n\n {batch.length > 1 && !isWorking && (\n <p className=\"mt-2 text-xs text-muted-foreground\">{batch.length} results from this run</p>\n )}\n </section>\n )\n}\n\nfunction CanvasTile({ generation }: { generation: Generation }) {\n const cfg = typeConfigFor(generation.type)\n const Icon = cfg.icon\n const status = generationStatus(generation)\n\n if (status === 'pending' || status === 'running') {\n return <div className=\"studio-shimmer absolute inset-0 h-full w-full\" />\n }\n if (status === 'failed') {\n return (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 p-4 text-center\">\n <Icon className=\"h-6 w-6 text-destructive/50\" />\n <p className=\"line-clamp-3 text-xs text-destructive\">{generationError(generation) ?? 'Generation failed'}</p>\n </div>\n )\n }\n if (generation.type === 'image' && generation.result) {\n return <img src={generation.result} alt={generation.prompt} className=\"absolute inset-0 h-full w-full object-contain\" />\n }\n if ((generation.type === 'video' || generation.type === 'avatar') && generation.result) {\n return <video src={generation.result} controls className=\"absolute inset-0 h-full w-full object-contain\" />\n }\n if (generation.type === 'speech' && generation.result) {\n return (\n <div className=\"absolute inset-0 flex items-center justify-center p-4\">\n <audio src={generation.result} controls className=\"w-full\" />\n </div>\n )\n }\n if (generation.type === 'transcription' && generation.result) {\n return (\n <div className=\"absolute inset-0 overflow-y-auto p-4\">\n <p className=\"whitespace-pre-wrap text-xs text-foreground\">{generation.result}</p>\n </div>\n )\n }\n return (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <Icon className=\"h-8 w-8 text-muted-foreground/20\" />\n </div>\n )\n}\n","import { useMemo } from 'react'\nimport { Link } from 'react-router'\nimport {\n Button,\n Tabs, TabsList, TabsTrigger,\n} from '@tangle-network/sandbox-ui/primitives'\nimport { ArrowLeft, DollarSign, FolderOpen, X } from 'lucide-react'\nimport { type Generation } from '../studio'\nimport { TYPE_CONFIG } from './type-config'\nimport { StudioSheet } from './studio-sheet'\nimport { GenerationGrid, filterGenerations } from './generation-grid'\nimport { GenerationDetail } from './generation-detail'\n\nexport function LibraryDrawer({\n open,\n onOpenChange,\n generations,\n totalCost,\n typeFilter,\n onFilterChange,\n vaultHref,\n selected,\n onSelect,\n}: {\n open: boolean\n onOpenChange: (open: boolean) => void\n generations: Generation[]\n totalCost: number\n typeFilter: string | null\n onFilterChange: (type: string | null) => void\n vaultHref?: (filePath?: string | null) => string\n selected: Generation | null\n onSelect: (generation: Generation | null) => void\n}) {\n const visible = useMemo(() => filterGenerations(generations, typeFilter), [generations, typeFilter])\n\n return (\n <StudioSheet open={open} onOpenChange={onOpenChange} title=\"Asset library\">\n <header className=\"flex shrink-0 items-center justify-between gap-3 border-b border-border px-4 py-3\">\n {selected ? (\n <button\n type=\"button\"\n onClick={() => onSelect(null)}\n className=\"flex items-center gap-1.5 text-sm font-medium text-foreground transition-colors hover:text-primary\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to library\n </button>\n ) : (\n <h2 className=\"text-sm font-semibold text-foreground\">Asset library</h2>\n )}\n <button\n type=\"button\"\n aria-label=\"Close library\"\n onClick={() => onOpenChange(false)}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </header>\n\n {selected ? (\n <div className=\"flex-1 overflow-y-auto p-4\">\n <GenerationDetail\n generation={selected}\n vaultHref={vaultHref}\n onNavigate={() => onOpenChange(false)}\n />\n </div>\n ) : (\n <>\n <div className=\"shrink-0 border-b border-border px-4 pt-3\">\n <div className=\"mb-2 flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-3 text-xs text-muted-foreground\">\n <span>{visible.length} generation{visible.length !== 1 ? 's' : ''}</span>\n <span className=\"flex items-center gap-0.5\">\n <DollarSign className=\"h-3 w-3\" />\n {totalCost.toFixed(2)} spent\n </span>\n </div>\n {vaultHref && (\n <Link to={vaultHref()} prefetch=\"intent\" onClick={() => onOpenChange(false)}>\n <Button size=\"sm\" variant=\"outline\">\n <FolderOpen className=\"mr-1.5 h-3.5 w-3.5\" />\n Vault\n </Button>\n </Link>\n )}\n </div>\n <Tabs value={typeFilter ?? 'all'} onValueChange={(v) => onFilterChange(v === 'all' ? null : v)}>\n <TabsList className=\"h-9 w-full justify-start gap-1 overflow-x-auto bg-transparent\">\n <TabsTrigger value=\"all\" className=\"text-xs\">All</TabsTrigger>\n {Object.entries(TYPE_CONFIG).map(([key, cfg]) => (\n <TabsTrigger key={key} value={key} className=\"text-xs\">{cfg.label}</TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n </div>\n\n <div className=\"flex-1 overflow-y-auto p-4\">\n <GenerationGrid generations={visible} typeFilter={typeFilter} onSelect={onSelect} />\n </div>\n </>\n )}\n </StudioSheet>\n )\n}\n","import type { ReactNode } from 'react'\nimport * as Dialog from '@radix-ui/react-dialog'\n\n/**\n * Right-side overlay sheet built on Radix Dialog — gives focus-trap, scroll-lock,\n * and Escape-to-close for free. Slide/fade come from the studio-sheet-* classes in\n * ./studio.css (driven by Radix data-state), not tailwindcss-animate.\n */\nexport function StudioSheet({\n open,\n onOpenChange,\n title,\n children,\n}: {\n open: boolean\n onOpenChange: (open: boolean) => void\n title: string\n children: ReactNode\n}) {\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"studio-sheet-overlay fixed inset-0 z-50 bg-black/50\" />\n <Dialog.Content\n className=\"studio-sheet-content fixed inset-y-0 right-0 z-50 flex w-[min(92vw,30rem)] flex-col border-l border-card-edge bg-popover shadow-[var(--shadow-overlay)] focus:outline-none\"\n aria-describedby={undefined}\n >\n <Dialog.Title className=\"sr-only\">{title}</Dialog.Title>\n {children}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n )\n}\n","import { EmptyState } from '@tangle-network/sandbox-ui/primitives'\nimport { Film, Sparkles } from 'lucide-react'\nimport { type Generation, isGenerationType } from '../studio'\nimport { TYPE_CONFIG } from './type-config'\nimport { GenerationCard } from './generation-card'\n\n/** The visible set for the active type tab (all generations when unfiltered). */\nexport function filterGenerations(generations: Generation[], typeFilter: string | null): Generation[] {\n if (!typeFilter || !isGenerationType(typeFilter)) return generations\n return generations.filter((generation) => generation.type === typeFilter)\n}\n\n/**\n * Chrome-less asset grid — the `GenerationCard` grid plus its empty state, with\n * no surrounding tabs/stats/sheet chrome. Composed by both the inline\n * `LibraryPanel` and the `LibraryDrawer`'s list view so the grid and its\n * empty-state copy stay in one place. `generations` is the already-filtered\n * visible set; `typeFilter` only tunes the empty-state message.\n */\nexport function GenerationGrid({\n generations,\n typeFilter,\n onSelect,\n}: {\n generations: Generation[]\n typeFilter: string | null\n onSelect: (generation: Generation) => void\n}) {\n if (generations.length === 0) {\n return (\n <EmptyState\n icon={typeFilter\n ? <Film className=\"h-8 w-8 text-muted-foreground/30\" />\n : <Sparkles className=\"h-10 w-10 text-muted-foreground/30\" />}\n title={typeFilter\n ? `No ${TYPE_CONFIG[typeFilter]?.label ?? typeFilter} generations`\n : 'No generations yet'}\n description={typeFilter\n ? 'Try a different filter or change the type in the composer.'\n : 'Everything you and the agent create lives here.'}\n className=\"py-16\"\n />\n )\n }\n return (\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {generations.map((generation) => (\n <GenerationCard key={generation.id} generation={generation} onSelect={onSelect} />\n ))}\n </div>\n )\n}\n","import { Card, CardContent, Badge } from '@tangle-network/sandbox-ui/primitives'\nimport { Send } from 'lucide-react'\nimport {\n type Generation,\n DESTINATIONS,\n generationError,\n generationStatus,\n isPublishPackage,\n relativeTime,\n} from '../studio'\nimport { typeConfigFor } from './type-config'\n\nexport function GenerationCard({\n generation,\n onSelect,\n}: {\n generation: Generation\n onSelect: (generation: Generation) => void\n}) {\n const cfg = typeConfigFor(generation.type)\n const Icon = cfg.icon\n const status = generationStatus(generation)\n const publishPackage = generation.metadata?.publishPackage\n return (\n <button type=\"button\" onClick={() => onSelect(generation)} className=\"group text-left animate-row-in\">\n <Card className=\"overflow-hidden transition-all group-hover:border-primary/50 group-hover:shadow-md\">\n <div className=\"relative aspect-video bg-secondary\">\n {generation.type === 'image' && generation.result ? (\n <img src={generation.result} alt={generation.prompt} className=\"h-full w-full object-cover\" />\n ) : (generation.type === 'video' || generation.type === 'avatar') && generation.result ? (\n <video src={generation.result} className=\"h-full w-full object-cover\" muted />\n ) : generation.type === 'speech' && generation.result ? (\n <div className=\"flex h-full items-center justify-center\">\n <Icon className=\"h-6 w-6 text-muted-foreground/40\" />\n </div>\n ) : generation.type === 'transcription' && generation.result ? (\n <div className=\"flex h-full items-center justify-center p-4\">\n <p className=\"line-clamp-5 text-xs text-muted-foreground\">{generation.result}</p>\n </div>\n ) : status === 'pending' || status === 'running' ? (\n <div className=\"shimmer h-full w-full\" />\n ) : (\n <div className=\"flex h-full items-center justify-center\">\n <Icon className=\"h-8 w-8 text-muted-foreground/20\" />\n </div>\n )}\n <div className=\"absolute left-2 top-2\">\n <Badge variant=\"outline\" className={`${cfg.color} gap-1 text-xs`}>\n <Icon className=\"h-3 w-3\" />\n {cfg.label}\n </Badge>\n </div>\n <GenerationStatusBadge generation={generation} />\n </div>\n <CardContent className=\"p-3\">\n <p className=\"mb-2 line-clamp-2 text-sm font-medium text-foreground\">{generation.prompt}</p>\n {status === 'failed' && (\n <p className=\"mb-2 line-clamp-2 text-xs text-destructive\">{generationError(generation)}</p>\n )}\n <div className=\"flex items-center justify-between\">\n {generation.model && (\n <span className=\"truncate text-xs text-muted-foreground\">{generation.model}</span>\n )}\n <div className=\"flex shrink-0 items-center gap-2\">\n {generation.cost != null && (\n <span className=\"text-xs text-muted-foreground\">${generation.cost.toFixed(3)}</span>\n )}\n <span className=\"text-xs text-muted-foreground\">{relativeTime(generation.createdAt)}</span>\n </div>\n </div>\n {isPublishPackage(publishPackage) && (\n <div className=\"mt-3 rounded-md border border-border bg-secondary p-2\">\n <div className=\"mb-1 flex items-center gap-1.5 text-xs font-medium text-foreground\">\n <Send className=\"h-3 w-3\" />\n {(publishPackage.destinations ?? [])\n .map((id) => DESTINATIONS.find((destination) => destination.id === id)?.label ?? id)\n .join(', ') || 'Publish package'}\n </div>\n <p className=\"line-clamp-2 text-xs text-muted-foreground\">\n {publishPackage.caption || 'Caption pending'}\n </p>\n </div>\n )}\n </CardContent>\n </Card>\n </button>\n )\n}\n\nexport function GenerationStatusBadge({\n generation,\n inline = false,\n}: {\n generation: Generation\n inline?: boolean\n}) {\n const status = generationStatus(generation)\n if (status === 'succeeded') return null\n\n const label = status === 'failed' ? 'Failed' : status === 'running' ? 'Running' : 'Pending'\n // Solid tint mixed onto the card surface — the badge floats over media, so an\n // alpha fill would let the thumbnail bleed through.\n const className = status === 'failed'\n ? 'border-destructive/30 bg-[color-mix(in_srgb,hsl(var(--destructive))_10%,hsl(var(--card)))] text-destructive'\n : 'border-warning/30 bg-[color-mix(in_srgb,hsl(var(--warning))_10%,hsl(var(--card)))] text-warning'\n\n return (\n <div className={inline ? '' : 'absolute bottom-2 left-2'}>\n <Badge variant=\"outline\" className={`${className} text-xs`}>\n {label}\n </Badge>\n </div>\n )\n}\n","import { Link } from 'react-router'\nimport { Badge, Button } from '@tangle-network/sandbox-ui/primitives'\nimport { FolderOpen } from 'lucide-react'\nimport {\n type Generation,\n generationError,\n generationVaultPath,\n} from '../studio'\nimport { typeConfigFor } from './type-config'\nimport { GenerationStatusBadge } from './generation-card'\n\nexport function GenerationDetail({\n generation,\n vaultHref,\n onNavigate,\n}: {\n generation: Generation\n vaultHref?: (filePath?: string | null) => string\n onNavigate?: () => void\n}) {\n const cfg = typeConfigFor(generation.type)\n const Icon = cfg.icon\n // Only offer the vault link when the generation actually persisted a file.\n // generationVaultPath is null for failed/pending/running and storage-failed\n // generations; without this guard vaultHref(null) falls back to the vault\n // root, rendering a button that opens nothing relevant.\n const vaultPath = generationVaultPath(generation)\n const href = vaultHref && vaultPath ? vaultHref(vaultPath) : null\n\n return (\n <div className=\"space-y-4\">\n <div className=\"overflow-hidden rounded-lg bg-secondary\">\n {generation.type === 'image' && generation.result ? (\n <img src={generation.result} alt={generation.prompt} className=\"max-h-[420px] w-full object-contain\" />\n ) : (generation.type === 'video' || generation.type === 'avatar') && generation.result ? (\n <video src={generation.result} controls className=\"max-h-[420px] w-full\" />\n ) : generation.type === 'speech' && generation.result ? (\n <div className=\"p-6\">\n <audio src={generation.result} controls className=\"w-full\" />\n </div>\n ) : (\n <div className=\"flex h-32 items-center justify-center\">\n <Icon className=\"h-8 w-8 text-muted-foreground/20\" />\n </div>\n )}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\" className={`${cfg.color} gap-1`}>\n <Icon className=\"h-3 w-3\" />\n {cfg.label}\n </Badge>\n <GenerationStatusBadge generation={generation} inline />\n {generationError(generation) && (\n <span className=\"text-xs text-destructive\">{generationError(generation)}</span>\n )}\n </div>\n\n <div>\n <span className=\"mb-1 block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\">Prompt</span>\n <p className=\"text-sm text-foreground\">{generation.prompt}</p>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-4\">\n {generation.model && (\n <div>\n <span className=\"block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\">Model</span>\n <span className=\"text-xs text-foreground\">{generation.model}</span>\n </div>\n )}\n {generation.cost != null && (\n <div>\n <span className=\"block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\">Cost</span>\n <span className=\"text-xs text-foreground\">${generation.cost.toFixed(3)}</span>\n </div>\n )}\n {generation.createdAt && (\n <div>\n <span className=\"block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\">Created</span>\n <span className=\"text-xs text-foreground\">\n {new Date(generation.createdAt).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' })}\n </span>\n </div>\n )}\n </div>\n\n {generation.type === 'transcription' && generation.result && (\n <div>\n <span className=\"mb-1 block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\">Transcription</span>\n <pre className=\"max-h-64 overflow-y-auto whitespace-pre-wrap rounded-lg bg-secondary p-4 font-mono text-[13px] tabular-nums text-foreground\">\n {generation.result}\n </pre>\n </div>\n )}\n\n {href && (\n <div className=\"border-t border-border pt-2\">\n <Link to={href} prefetch=\"intent\" onClick={onNavigate}>\n <Button size=\"sm\" variant=\"outline\">\n <FolderOpen className=\"mr-1.5 h-3.5 w-3.5\" />\n Open in Vault\n </Button>\n </Link>\n </div>\n )}\n </div>\n )\n}\n","import { useMemo } from 'react'\nimport {\n Tabs, TabsList, TabsTrigger,\n} from '@tangle-network/sandbox-ui/primitives'\nimport { DollarSign } from 'lucide-react'\nimport { type Generation } from '../studio'\nimport { TYPE_CONFIG } from './type-config'\nimport { GenerationGrid, filterGenerations } from './generation-grid'\n\n/**\n * Inline asset gallery — the same filter + stats + card grid as the library\n * drawer's list view, but with no sheet chrome so it can sit on the page beside\n * the composer. In-flight generations need no special handling: they arrive at\n * the front of `generations` (via `useStudioGenerations.mergedGenerations`) and\n * `GenerationCard` renders their `pending`/`running` shimmer.\n */\nexport function LibraryPanel({\n generations,\n totalCost,\n typeFilter,\n onFilterChange,\n onSelect,\n}: {\n generations: Generation[]\n totalCost: number\n typeFilter: string | null\n onFilterChange: (type: string | null) => void\n onSelect: (generation: Generation) => void\n}) {\n const visible = useMemo(() => filterGenerations(generations, typeFilter), [generations, typeFilter])\n\n return (\n <div className=\"flex min-w-0 flex-col\">\n <div className=\"mb-4 flex flex-wrap items-center justify-between gap-3\">\n <Tabs value={typeFilter ?? 'all'} onValueChange={(v) => onFilterChange(v === 'all' ? null : v)}>\n <TabsList className=\"h-9 justify-start gap-1 overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-background p-1\">\n <TabsTrigger\n value=\"all\"\n className=\"rounded-md px-3 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground data-[state=active]:bg-primary/10 data-[state=active]:font-semibold data-[state=active]:text-primary data-[state=active]:shadow-none\"\n >\n All\n </TabsTrigger>\n {Object.entries(TYPE_CONFIG).map(([key, cfg]) => (\n <TabsTrigger\n key={key}\n value={key}\n className=\"rounded-md px-3 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground data-[state=active]:bg-primary/10 data-[state=active]:font-semibold data-[state=active]:text-primary data-[state=active]:shadow-none\"\n >\n {cfg.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n <div className=\"flex items-center gap-3 text-xs text-muted-foreground\">\n <span>{visible.length} generation{visible.length !== 1 ? 's' : ''}</span>\n <span className=\"flex items-center gap-0.5\">\n <DollarSign className=\"h-3 w-3\" />\n {totalCost.toFixed(2)} spent\n </span>\n </div>\n </div>\n\n <GenerationGrid generations={visible} typeFilter={typeFilter} onSelect={onSelect} />\n </div>\n )\n}\n","import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@tangle-network/sandbox-ui/primitives'\nimport { type Generation } from '../studio'\nimport { typeConfigFor } from './type-config'\nimport { GenerationDetail } from './generation-detail'\n\n/**\n * Centered detail view for a single generation. Opens when `generation` is set\n * and reports dismissal through `onClose`. GenerationDetail renders the media,\n * type badge, prompt and metadata; the dialog title carries the a11y label.\n */\nexport function GenerationDetailModal({\n generation,\n vaultHref,\n onClose,\n}: {\n generation: Generation | null\n vaultHref?: (filePath?: string | null) => string\n onClose: () => void\n}) {\n const cfg = generation ? typeConfigFor(generation.type) : null\n return (\n <Dialog open={generation != null} onOpenChange={(open) => { if (!open) onClose() }}>\n <DialogContent className=\"max-h-[85vh] max-w-2xl overflow-y-auto border-card-edge bg-popover shadow-[var(--shadow-overlay)]\">\n <DialogHeader>\n <DialogTitle className=\"text-left text-[15px] font-semibold\">{cfg ? `${cfg.label} generation` : 'Generation'}</DialogTitle>\n </DialogHeader>\n {generation && (\n <GenerationDetail generation={generation} vaultHref={vaultHref} onNavigate={onClose} />\n )}\n </DialogContent>\n </Dialog>\n )\n}\n"],"mappings":"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","names":["useRef","useState","Button","Images","useEffect","useMemo","useRef","useState","Badge","Button","Input","Label","Textarea","jsx","jsxs","Input","jsx","jsxs","Input","Input","jsx","Input","Input","jsx","jsxs","Input","Input","jsx","jsxs","Input","Input","jsx","jsxs","Input","Fragment","jsx","jsxs","useState","useRef","useMemo","useEffect","Label","Textarea","Input","Badge","Button","Button","jsx","jsxs","Badge","Sparkles","jsx","jsxs","Sparkles","Badge","useMemo","Link","Button","FolderOpen","jsx","jsxs","Sparkles","Badge","jsx","jsxs","Badge","jsx","Sparkles","Link","Badge","Button","jsx","jsxs","Badge","Link","Button","Fragment","jsx","jsxs","useMemo","Link","Button","FolderOpen","Fragment","jsx","jsxs","useState","useRef","Images","Button","useMemo","Tabs","TabsList","TabsTrigger","DollarSign","jsx","jsxs","useMemo","Tabs","TabsList","TabsTrigger","DollarSign","Dialog","jsx","jsxs","Dialog"]}
|
|
1
|
+
{"version":3,"sources":["../../src/studio-react/studio-workspace.tsx","../../src/studio-react/use-studio-generations.ts","../../src/studio-react/composer-hero.tsx","../../src/studio-react/type-config.ts","../../src/studio-react/composer-shell.tsx","../../src/studio-react/image-composer.tsx","../../src/studio-react/video-composer.tsx","../../src/studio-react/speech-composer.tsx","../../src/studio-react/studio-header.tsx","../../src/studio-react/result-canvas.tsx","../../src/studio-react/library-drawer.tsx","../../src/studio-react/studio-sheet.tsx","../../src/studio-react/generation-grid.tsx","../../src/studio-react/generation-card.tsx","../../src/studio-react/generation-detail.tsx","../../src/studio-react/library-panel.tsx","../../src/studio-react/generation-detail-modal.tsx","../../src/studio-react/avatar-composer.tsx","../../src/studio-react/transcription-composer.tsx"],"sourcesContent":["import { useRef, useState } from 'react'\nimport { useSearchParams } from 'react-router'\nimport { Button } from '@tangle-network/sandbox-ui/primitives'\nimport { Images } from 'lucide-react'\nimport type { Generation } from '../studio'\nimport { useStudioGenerations } from './use-studio-generations'\nimport { ComposerHero } from './composer-hero'\nimport { StudioHeader } from './studio-header'\nimport { ResultCanvas } from './result-canvas'\nimport { LibraryDrawer } from './library-drawer'\n\nexport type StudioRole = 'owner' | 'admin' | 'editor' | 'viewer'\n\nexport interface StudioWorkspaceProps {\n generations: Generation[]\n totalCost: number\n workspaceId?: string\n role: StudioRole\n /** Polling endpoint override (default `/api/generations`). */\n generationsEndpoint?: string\n /** Build a vault link, optionally to a specific file. Defaults to `/app/<workspaceId>/vault`. */\n vaultHref?: (filePath?: string | null) => string\n}\n\n/**\n * The full studio surface: header + composer + result canvas + library drawer,\n * with the generation orchestrator (merge/poll/revalidate) wired in. The host\n * route owns the loader (auth, RBAC, the generation query) and the server\n * endpoints (`/api/generate`, `/api/media-models`, `/api/generations`); this\n * shell renders that data and drives the live UI. Role gates the composer\n * (viewers get a read-only library).\n */\nexport function StudioWorkspace({\n generations,\n totalCost,\n workspaceId,\n role,\n generationsEndpoint,\n vaultHref,\n}: StudioWorkspaceProps) {\n const [searchParams, setSearchParams] = useSearchParams()\n const typeFilter = searchParams.get('type')\n const [drawerOpen, setDrawerOpen] = useState(false)\n const [selected, setSelected] = useState<Generation | null>(null)\n const canvasRef = useRef<HTMLDivElement>(null)\n const canGenerate = role !== 'viewer'\n // Default vault navigation to the conventional /app/<workspaceId>/… route;\n // a host on a different route scheme passes its own builder.\n const resolvedVaultHref = vaultHref ?? (workspaceId\n ? (filePath?: string | null) => (filePath\n ? `/app/${workspaceId}/vault?file=${encodeURIComponent(filePath)}`\n : `/app/${workspaceId}/vault`)\n : undefined)\n\n const { mergedGenerations, latestBatch, onGenerated } = useStudioGenerations(generations, {\n workspaceId,\n generationsEndpoint,\n })\n\n function setFilter(type: string | null) {\n if (type) setSearchParams({ type })\n else setSearchParams({})\n }\n\n function openLibrary() {\n setSelected(null)\n setDrawerOpen(true)\n }\n\n function openDetail(generation: Generation) {\n setSelected(generation)\n setDrawerOpen(true)\n }\n\n return (\n <div className=\"min-h-0 flex-1 overflow-y-auto bg-background\">\n <StudioHeader\n count={mergedGenerations.length}\n canGenerate={canGenerate}\n onOpenLibrary={openLibrary}\n />\n\n <div className=\"mx-auto w-full max-w-3xl space-y-4 px-4 py-6 sm:px-6\">\n {canGenerate ? (\n <>\n <ComposerHero\n workspaceId={workspaceId}\n onGenerated={(generation) => {\n onGenerated(generation)\n requestAnimationFrame(() => {\n canvasRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' })\n })\n }}\n />\n <div ref={canvasRef}>\n <ResultCanvas\n batch={latestBatch}\n onOpenLibrary={openLibrary}\n onSelect={openDetail}\n />\n </div>\n </>\n ) : (\n <section className=\"flex flex-col items-center justify-center gap-3 rounded-xl border border-border bg-card p-10 text-center shadow-sm\">\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <Images className=\"h-6 w-6 text-muted-foreground/40\" />\n </div>\n <p className=\"text-sm font-medium text-foreground\">\n {mergedGenerations.length > 0\n ? `${mergedGenerations.length} asset${mergedGenerations.length !== 1 ? 's' : ''} in this workspace`\n : 'No generations yet'}\n </p>\n <p className=\"max-w-sm text-xs text-muted-foreground\">\n Team generations appear in the library.\n </p>\n <Button size=\"sm\" variant=\"outline\" onClick={openLibrary}>\n <Images className=\"mr-1.5 h-4 w-4\" />\n Open library\n </Button>\n </section>\n )}\n </div>\n\n <LibraryDrawer\n open={drawerOpen}\n onOpenChange={(open) => { setDrawerOpen(open); if (!open) setSelected(null) }}\n generations={mergedGenerations}\n totalCost={totalCost}\n typeFilter={typeFilter}\n onFilterChange={setFilter}\n vaultHref={resolvedVaultHref}\n selected={selected}\n onSelect={(generation) => { setSelected(generation); if (generation) setDrawerOpen(true) }}\n />\n </div>\n )\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react'\nimport { useRevalidator } from 'react-router'\nimport {\n type Generation,\n generationStatus,\n isLocalGeneration,\n latestBatchOf,\n mergeLiveGeneration,\n mergeLoaderAndLive,\n} from '../studio'\n\n/**\n * The generation orchestrator behind a studio surface: it merges the loader's\n * rows with in-flight live generations, computes the latest batch for the\n * canvas, polls running generations until they settle, and revalidates the\n * route loader when a status changes.\n *\n * The merge keeps the canvas, the library, and the polling path looking at the\n * same full list. Polling hits `generationsEndpoint` (default `/api/generations`,\n * the convention both apps already serve); pass an override if a product routes\n * it elsewhere. `onGenerated` is wired to the composer's per-result callback.\n */\nexport function useStudioGenerations(\n loaderGenerations: Generation[],\n options: { workspaceId?: string; generationsEndpoint?: string } = {},\n) {\n const { workspaceId, generationsEndpoint = '/api/generations' } = options\n const revalidator = useRevalidator()\n const [liveGenerations, setLiveGenerations] = useState<Generation[]>([])\n\n const mergedGenerations = useMemo(\n () => mergeLoaderAndLive(loaderGenerations, liveGenerations),\n [loaderGenerations, liveGenerations],\n )\n\n const latestBatch = useMemo(() => latestBatchOf(mergedGenerations), [mergedGenerations])\n\n const runningGenerationIds = useMemo(() => mergedGenerations\n .filter((gen) => {\n const status = generationStatus(gen)\n return status === 'pending' || status === 'running'\n })\n .map((gen) => gen.id)\n .filter((id) => !id.startsWith('local-')), [mergedGenerations])\n\n // The poll loop must not churn the effect. `runningGenerationIds` is a fresh\n // array every render and react-router's `revalidator` identity flips while a\n // revalidation is in flight — depending on either restarts the interval on\n // every tick, collapsing the 4s cadence into a request flood. Key the effect\n // on the STABLE join of the running ids (re-subscribe only when the set\n // actually changes) and reach the live ids / revalidate through refs.\n const runningIdsRef = useRef(runningGenerationIds)\n runningIdsRef.current = runningGenerationIds\n const revalidateRef = useRef(revalidator.revalidate)\n revalidateRef.current = revalidator.revalidate\n const runningKey = runningGenerationIds.join(',')\n\n useEffect(() => {\n if (!workspaceId || !runningKey) return\n let cancelled = false\n const poll = async () => {\n const responses = await Promise.all(runningIdsRef.current.map(async (id) => {\n const res = await fetch(`${generationsEndpoint}?workspaceId=${encodeURIComponent(workspaceId)}&id=${encodeURIComponent(id)}`)\n if (!res.ok) return null\n const data = await res.json() as { generation?: Generation }\n return data.generation ?? null\n }))\n if (cancelled) return\n const refreshed = responses.filter((gen): gen is Generation => Boolean(gen))\n if (refreshed.length > 0) {\n setLiveGenerations((current) => refreshed.reduce(mergeLiveGeneration, current))\n }\n if (refreshed.some((gen) => generationStatus(gen) !== 'running' && generationStatus(gen) !== 'pending')) {\n revalidateRef.current()\n }\n }\n const interval = window.setInterval(() => { void poll() }, 4_000)\n void poll()\n return () => {\n cancelled = true\n window.clearInterval(interval)\n }\n }, [runningKey, workspaceId, generationsEndpoint])\n\n const onGenerated = useCallback((generation: Generation) => {\n setLiveGenerations((current) => mergeLiveGeneration(current, generation))\n if (!isLocalGeneration(generation)) revalidateRef.current()\n }, [])\n\n return { mergedGenerations, latestBatch, onGenerated }\n}\n","import { useEffect, useRef, useState } from 'react'\nimport {\n Button, Input, Label, Textarea,\n Select, SelectContent, SelectItem, SelectTrigger, SelectValue,\n} from '@tangle-network/sandbox-ui/primitives'\nimport { Sparkles } from 'lucide-react'\nimport {\n type Generation,\n type GenerationType,\n type MediaModelCatalogResponse,\n buildGenerationRequestBody,\n failedOptimisticGeneration,\n modelMessage,\n normalizeImageCount,\n optimisticGeneration,\n outputPathFor,\n preferredModelId,\n selectedModelsWithDefaults,\n userSafeGenerationMessage,\n} from '../studio'\nimport { typeConfigFor } from './type-config'\nimport { ProviderLogo } from '../web-react/provider-logo'\nimport { ComposerDisclosure, Field } from './composer-shell'\nimport { ImageComposer } from './image-composer'\nimport { VideoComposer } from './video-composer'\nimport { SpeechComposer } from './speech-composer'\n\n// The lanes the composer currently offers. Avatar and transcription are\n// temporarily disabled as a product decision (#451) — the lane types and\n// the server capability stay intact for re-enable.\nconst COMPOSER_TYPES: readonly GenerationType[] = ['image', 'video', 'speech']\n\nconst SUGGESTIONS: Array<{ label: string; prompt: string; type: GenerationType }> = [\n {\n label: 'Storyboard frame',\n type: 'image',\n prompt: 'A vertical storyboard frame for a product launch teaser — dark cinematic lighting, sleek studio aesthetic, 9:16 composition.',\n },\n {\n label: 'Launch teaser clip',\n type: 'video',\n prompt: 'A 6-second vertical launch teaser: animated product reveal, dynamic camera move, hero music swell.',\n },\n {\n label: 'Scratch voiceover',\n type: 'speech',\n prompt: 'A confident 12-second scratch voiceover for a product launch teaser: warm tone, conversational pace.',\n },\n]\n\nexport function ComposerHero({\n workspaceId,\n align = 'start',\n surfaceClassName = 'bg-card',\n onGenerated,\n}: {\n workspaceId?: string\n /** Heading treatment: `center` (focus mode) vs `start` (composer as a left rail). */\n align?: 'center' | 'start'\n /** Background of the composer card. Host apps pass their own surface token so\n * the card can share a tone with the app shell (e.g. the sidebar). */\n surfaceClassName?: string\n onGenerated: (generation: Generation) => void\n}) {\n const [type, setType] = useState<GenerationType>('image')\n const [prompt, setPrompt] = useState('')\n const [negativePrompt, setNegativePrompt] = useState('')\n const [outputPath, setOutputPath] = useState(outputPathFor('image'))\n const [size, setSize] = useState('1536x1024')\n const [quality, setQuality] = useState('high')\n const [imageCount, setImageCount] = useState(1)\n const [duration, setDuration] = useState('6')\n const [resolution, setResolution] = useState('720p')\n const [aspectRatio, setAspectRatio] = useState('16:9')\n const [referenceImageUrl, setReferenceImageUrl] = useState('')\n const [voice, setVoice] = useState('alloy')\n const [mediaModels, setMediaModels] = useState<MediaModelCatalogResponse | null>(null)\n const [mediaModelsLoading, setMediaModelsLoading] = useState(false)\n const [mediaModelsError, setMediaModelsError] = useState<string | null>(null)\n const [selectedModels, setSelectedModels] = useState<Partial<Record<GenerationType, string>>>({})\n const submitLockRef = useRef(false)\n const [isSubmitting, setIsSubmitting] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const modelsForType = mediaModels?.models[type] ?? []\n const selectedModel = selectedModels[type] ?? preferredModelId(type, mediaModels) ?? ''\n const selectedModelOption = modelsForType.find((model) => model.id === selectedModel)\n const modelReady = Boolean(selectedModelOption)\n && selectedModelOption?.status !== 'unavailable'\n && !mediaModelsLoading\n && !mediaModelsError\n const hasRequiredInput = Boolean(prompt.trim())\n const canSubmit = Boolean(workspaceId)\n && modelReady\n && hasRequiredInput\n && !isSubmitting\n\n useEffect(() => {\n if (!workspaceId) return\n let cancelled = false\n setMediaModelsLoading(true)\n setMediaModelsError(null)\n\n fetch(`/api/media-models?workspaceId=${encodeURIComponent(workspaceId)}`)\n .then(async (res) => {\n const data = await res.json() as MediaModelCatalogResponse\n if (!res.ok) throw new Error(data.error ?? 'Could not load media models')\n return data\n })\n .then((data) => {\n if (cancelled) return\n setMediaModels(data)\n setSelectedModels((current) => selectedModelsWithDefaults(current, data))\n })\n .catch(() => {\n if (cancelled) return\n setMediaModels(null)\n // Never surface the raw fetch/parse error — a non-JSON 404 page reads\n // as `Unexpected token 'N', \"Not Found\" is not valid JSON` to users.\n setMediaModelsError('Could not load media models')\n })\n .finally(() => {\n if (!cancelled) setMediaModelsLoading(false)\n })\n\n return () => {\n cancelled = true\n }\n }, [workspaceId])\n\n function changeType(next: GenerationType) {\n setType(next)\n setOutputPath(outputPathFor(next))\n }\n\n async function generate() {\n if (!workspaceId || submitLockRef.current) return\n const promptText = prompt.trim()\n if (!promptText) {\n setError('prompt is required')\n return\n }\n if (!selectedModelOption || selectedModelOption.status === 'unavailable') {\n setError(`Select an available ${typeConfigFor(type).label} model`)\n return\n }\n submitLockRef.current = true\n setIsSubmitting(true)\n setError(null)\n const clientRequestId = crypto.randomUUID()\n const requestedImageCount = type === 'image' ? normalizeImageCount(imageCount) : 1\n if (type === 'image' && requestedImageCount !== imageCount) setImageCount(requestedImageCount)\n const localGenerations = Array.from({ length: requestedImageCount }, (_, outputIndex) => optimisticGeneration({\n type,\n prompt: promptText,\n model: selectedModel,\n clientRequestId,\n outputIndex: type === 'image' ? outputIndex : undefined,\n outputCount: type === 'image' ? requestedImageCount : undefined,\n }))\n localGenerations.slice().reverse().forEach(onGenerated)\n setPrompt('')\n let receivedServerGeneration = false\n try {\n const body = buildGenerationRequestBody({\n workspaceId,\n clientRequestId,\n type,\n model: selectedModel,\n prompt,\n negativePrompt,\n outputPath,\n image: { size, quality, count: requestedImageCount },\n video: { duration, resolution, aspectRatio, referenceImageUrl },\n speech: { voice },\n })\n\n const res = await fetch('/api/generate', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n })\n const data = await res.json() as { generation?: Generation; generations?: Generation[]; error?: string }\n const serverGenerations = data.generations?.length ? data.generations : data.generation ? [data.generation] : []\n if (serverGenerations.length > 0) {\n receivedServerGeneration = true\n serverGenerations.slice().reverse().forEach(onGenerated)\n }\n if (!res.ok || serverGenerations.length === 0) throw new Error(data.error ?? 'Generation failed')\n } catch (err) {\n if (!receivedServerGeneration) localGenerations.map(failedOptimisticGeneration).forEach(onGenerated)\n setError(err instanceof Error ? userSafeGenerationMessage(err.message) : 'Generation failed')\n } finally {\n submitLockRef.current = false\n setIsSubmitting(false)\n }\n }\n\n const mediaTypes = COMPOSER_TYPES.map((key) => [key, typeConfigFor(key)] as const)\n\n return (\n <section className={`rounded-2xl border border-border p-5 shadow-sm ${surfaceClassName}`}>\n <div className={`mb-5 ${align === 'center' ? 'text-center' : 'text-left'}`}>\n <h2\n className={`font-semibold tracking-tight text-foreground transition-all duration-300 ${\n align === 'center' ? 'text-xl' : 'text-base'\n }`}\n >\n Media Generation\n </h2>\n </div>\n\n <div role=\"tablist\" aria-label=\"Generation type\" className=\"grid grid-cols-3 gap-1.5\">\n {mediaTypes.map(([key, cfg]) => {\n const Icon = cfg.icon\n const active = type === key\n return (\n <button\n key={key}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n onClick={() => changeType(key)}\n className={`flex flex-col items-center gap-1.5 rounded-lg border px-1 pb-2 pt-2.5 text-xs transition-all ${\n active\n ? 'border-primary/30 bg-primary/10 font-semibold text-primary'\n : 'border-border bg-background font-medium text-muted-foreground hover:border-foreground/20 hover:text-foreground'\n }`}\n >\n <Icon className=\"h-[17px] w-[17px] shrink-0\" />\n <span className=\"truncate\">{cfg.label}</span>\n </button>\n )\n })}\n </div>\n\n <div className=\"mt-5\">\n <Label\n htmlFor=\"studio-prompt\"\n className=\"mb-1.5 block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\"\n >\n Prompt\n </Label>\n <div className=\"rounded-xl border border-border bg-background transition-colors focus-within:border-primary/30 focus-within:ring-[3px] focus-within:ring-primary/10\">\n <textarea\n id=\"studio-prompt\"\n value={prompt}\n onChange={(event) => setPrompt(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n void generate()\n }\n }}\n rows={4}\n placeholder=\"A vertical hero frame for a product launch teaser, dark cinematic lighting...\"\n className=\"block min-h-[96px] w-full resize-none border-0 bg-transparent px-3.5 pb-1.5 pt-3 text-sm leading-relaxed outline-none placeholder:text-muted-foreground\"\n />\n <div className=\"flex flex-wrap items-center gap-1.5 px-2.5 pb-2.5\">\n {SUGGESTIONS.map((suggestion) => (\n <button\n key={suggestion.label}\n type=\"button\"\n onClick={() => {\n setPrompt(suggestion.prompt)\n changeType(suggestion.type)\n }}\n className=\"rounded-full border border-border bg-background px-2.5 py-1 text-xs font-medium text-muted-foreground transition-colors hover:border-primary/30 hover:text-primary\"\n >\n {suggestion.label}\n </button>\n ))}\n </div>\n </div>\n </div>\n\n <div className=\"mt-5 space-y-3\">\n <div className=\"space-y-1.5\">\n <Field label=\"Model\" htmlFor=\"studio-media-model\">\n <Select\n value={selectedModel || undefined}\n onValueChange={(value) => setSelectedModels((current) => ({ ...current, [type]: value }))}\n disabled={mediaModelsLoading || Boolean(mediaModelsError) || modelsForType.length === 0}\n >\n <SelectTrigger id=\"studio-media-model\" className=\"h-9 w-full bg-background\">\n {selectedModelOption ? (\n <span className=\"flex min-w-0 items-center gap-2\">\n {selectedModelOption.provider && (\n <ProviderLogo provider={selectedModelOption.provider} size={14} />\n )}\n <span className=\"truncate\">{selectedModelOption.name || selectedModelOption.id}</span>\n {selectedModelOption.provider && (\n <span className=\"shrink-0 text-muted-foreground\">· {selectedModelOption.provider}</span>\n )}\n {selectedModelOption.status !== 'available' && (\n <span className=\"shrink-0 rounded-full bg-warning/10 px-1.5 py-0.5 text-xs font-semibold uppercase tracking-[0.05em] text-warning\">\n {selectedModelOption.status}\n </span>\n )}\n </span>\n ) : (\n <SelectValue placeholder={mediaModelsLoading ? 'Loading models…' : 'Select a model'} />\n )}\n </SelectTrigger>\n <SelectContent className=\"bg-background\">\n {modelsForType.map((model) => (\n <SelectItem key={model.id} value={model.id} disabled={model.status === 'unavailable'}>\n <span className=\"flex w-full items-center justify-between gap-3\">\n <span className=\"flex min-w-0 items-center gap-2\">\n {model.provider && <ProviderLogo provider={model.provider} size={14} />}\n <span className=\"truncate\">\n {model.name || model.id}{model.provider ? ` · ${model.provider}` : ''}\n </span>\n </span>\n {model.status !== 'available' && (\n <span className=\"shrink-0 text-xs capitalize text-muted-foreground\">{model.status}</span>\n )}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </Field>\n {(mediaModelsError || modelMessage(selectedModelOption, mediaModelsLoading, modelsForType.length)) && (\n <p className={`text-xs ${mediaModelsError || selectedModelOption?.status === 'unavailable' ? 'text-destructive' : 'text-muted-foreground'}`}>\n {mediaModelsError ?? modelMessage(selectedModelOption, mediaModelsLoading, modelsForType.length)}\n </p>\n )}\n </div>\n {type === 'image' && (\n <ImageComposer\n size={size}\n quality={quality}\n imageCount={imageCount}\n onSizeChange={setSize}\n onQualityChange={setQuality}\n onImageCountChange={setImageCount}\n />\n )}\n {type === 'video' && (\n <VideoComposer\n duration={duration}\n resolution={resolution}\n aspectRatio={aspectRatio}\n referenceImageUrl={referenceImageUrl}\n onDurationChange={setDuration}\n onResolutionChange={setResolution}\n onAspectRatioChange={setAspectRatio}\n onReferenceImageUrlChange={setReferenceImageUrl}\n />\n )}\n {type === 'speech' && (\n <SpeechComposer voice={voice} onVoiceChange={setVoice} />\n )}\n </div>\n\n <div className=\"mt-4 space-y-2\">\n <ComposerDisclosure summary=\"Advanced options\">\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <Field label=\"Negative prompt\">\n <Textarea\n value={negativePrompt}\n onChange={(event) => setNegativePrompt(event.target.value)}\n rows={2}\n placeholder=\"Avoid artifacts, off-style composition...\"\n className=\"bg-background\"\n />\n </Field>\n <Field label=\"Save to\">\n <Input value={outputPath} onChange={(event) => setOutputPath(event.target.value)} className=\"bg-background\" />\n </Field>\n </div>\n </ComposerDisclosure>\n </div>\n\n {error && (\n <div className=\"mt-4 rounded-md border border-destructive/20 bg-destructive/10 p-3 text-sm text-destructive\">\n {error}\n </div>\n )}\n\n <Button\n onClick={generate}\n disabled={!canSubmit}\n size=\"lg\"\n className=\"mt-5 w-full disabled:bg-muted disabled:text-muted-foreground disabled:opacity-100\"\n >\n <Sparkles className=\"mr-2 h-4 w-4\" />\n Generate\n <span className=\"ml-2 text-xs opacity-60\">⌘↵</span>\n </Button>\n </section>\n )\n}\n","import { FileText, Image, Mic, User, Video } from 'lucide-react'\n\n/** Define configuration options for a type including label, icon, and color properties */\nexport interface TypeConfig {\n label: string\n icon: typeof Image\n color: string\n}\n\n/* Type badges sit on top of media thumbnails, where a per-type hue is\n illegible and off-token — every type gets the same neutral scrim chip\n (no backdrop-blur, so the thumbnail doesn't smear through). The type\n icon inside the badge carries the identity instead of a color. */\nconst MEDIA_SCRIM = 'bg-black/60 text-white border-white/10'\n\nconst IMAGE: TypeConfig = { label: 'Image', icon: Image, color: MEDIA_SCRIM }\n\n// string-keyed so list cards can index by Generation.type\n/** Map type keys to their corresponding configuration objects including labels, icons, and colors */\nexport const TYPE_CONFIG: Record<string, TypeConfig> = {\n image: IMAGE,\n video: { label: 'Video', icon: Video, color: MEDIA_SCRIM },\n avatar: { label: 'Avatar', icon: User, color: MEDIA_SCRIM },\n speech: { label: 'Audio', icon: Mic, color: MEDIA_SCRIM },\n transcription: { label: 'Transcript', icon: FileText, color: MEDIA_SCRIM },\n}\n\n// Safe lookup for an arbitrary `Generation.type` — always defined (the table is\n// declared `Record<string, …>`, so a raw index is `T | undefined`). Falls back\n// to the image config, matching the prior `?? TYPE_CONFIG.image` call sites.\n/** Resolve the configuration object for a given type or return the default image configuration */\nexport function typeConfigFor(type: string): TypeConfig {\n return TYPE_CONFIG[type] ?? IMAGE\n}\n","import type { ReactNode, SelectHTMLAttributes } from 'react'\nimport { Label } from '@tangle-network/sandbox-ui/primitives'\nimport { ChevronRight, Minus, Plus } from 'lucide-react'\n\nexport function Field({\n label,\n htmlFor,\n className = 'space-y-1.5',\n children,\n}: {\n label: string\n htmlFor?: string\n className?: string\n children: ReactNode\n}) {\n return (\n <div className={className}>\n <Label\n htmlFor={htmlFor}\n className=\"text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\"\n >\n {label}\n </Label>\n {children}\n </div>\n )\n}\n\nexport function Stepper({\n value,\n min,\n max,\n onChange,\n}: {\n value: number\n min: number\n max: number\n onChange: (value: number) => void\n}) {\n return (\n <div className=\"flex h-9 items-center justify-between rounded-md border border-input bg-background px-1.5\">\n <button\n type=\"button\"\n aria-label=\"Decrease\"\n onClick={() => onChange(Math.max(min, value - 1))}\n disabled={value <= min}\n className=\"flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-40\"\n >\n <Minus className=\"h-3.5 w-3.5\" />\n </button>\n <span className=\"text-sm font-medium tabular-nums\">{value}</span>\n <button\n type=\"button\"\n aria-label=\"Increase\"\n onClick={() => onChange(Math.min(max, value + 1))}\n disabled={value >= max}\n className=\"flex h-6 w-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-40\"\n >\n <Plus className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n )\n}\n\nexport function ComposerDisclosure({ summary, children }: { summary: ReactNode; children: ReactNode }) {\n return (\n <details className=\"group rounded-lg border border-border bg-background transition-colors\">\n <summary className=\"flex cursor-pointer list-none items-center gap-1.5 px-3 py-2.5 text-xs font-medium text-foreground/80 transition-colors hover:text-foreground [&::-webkit-details-marker]:hidden\">\n <ChevronRight className=\"h-3.5 w-3.5 text-muted-foreground transition-transform group-open:rotate-90\" />\n {summary}\n </summary>\n <div className=\"border-t border-border px-3 py-3\">{children}</div>\n </details>\n )\n}\n\nexport function NativeSelect(props: SelectHTMLAttributes<HTMLSelectElement>) {\n return (\n <select {...props} className=\"h-9 w-full rounded-md border border-input bg-background px-3 text-sm\" />\n )\n}\n","import { Input } from '@tangle-network/sandbox-ui/primitives'\nimport {\n IMAGE_QUALITIES,\n IMAGE_SIZE_HINT,\n IMAGE_SIZE_PATTERN,\n MIN_IMAGE_COUNT,\n MAX_IMAGE_COUNT,\n normalizeImageCount,\n} from '../studio'\nimport { Field, NativeSelect, Stepper } from './composer-shell'\n\nexport function ImageComposer({\n size,\n quality,\n imageCount,\n onSizeChange,\n onQualityChange,\n onImageCountChange,\n}: {\n size: string\n quality: string\n imageCount: number\n onSizeChange: (value: string) => void\n onQualityChange: (value: string) => void\n onImageCountChange: (value: number) => void\n}) {\n return (\n <div className=\"space-y-3\">\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Size\">\n <Input\n value={size}\n onChange={(event) => onSizeChange(event.target.value)}\n pattern={IMAGE_SIZE_PATTERN}\n placeholder={IMAGE_SIZE_HINT}\n className=\"bg-background\"\n />\n </Field>\n <Field label=\"Quality\">\n <NativeSelect value={quality} onChange={(event) => onQualityChange(event.target.value)}>\n {IMAGE_QUALITIES.map((option) => (\n <option key={option} value={option}>{option.charAt(0).toUpperCase() + option.slice(1)}</option>\n ))}\n </NativeSelect>\n </Field>\n </div>\n <Field label=\"Images\">\n <Stepper\n value={imageCount}\n min={MIN_IMAGE_COUNT}\n max={MAX_IMAGE_COUNT}\n onChange={(value) => onImageCountChange(normalizeImageCount(value))}\n />\n </Field>\n </div>\n )\n}\n","import { Input } from '@tangle-network/sandbox-ui/primitives'\nimport { VIDEO_ASPECT_RATIOS, VIDEO_DURATIONS, VIDEO_RESOLUTIONS } from '../studio'\nimport { Field, NativeSelect } from './composer-shell'\n\nexport function VideoComposer({\n duration,\n resolution,\n aspectRatio,\n referenceImageUrl,\n onDurationChange,\n onResolutionChange,\n onAspectRatioChange,\n onReferenceImageUrlChange,\n}: {\n duration: string\n resolution: string\n aspectRatio: string\n referenceImageUrl: string\n onDurationChange: (value: string) => void\n onResolutionChange: (value: string) => void\n onAspectRatioChange: (value: string) => void\n onReferenceImageUrlChange: (value: string) => void\n}) {\n return (\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Duration (s)\">\n <NativeSelect value={duration} onChange={(event) => onDurationChange(event.target.value)}>\n {VIDEO_DURATIONS.map((option) => <option key={option} value={option}>{option}</option>)}\n </NativeSelect>\n </Field>\n <Field label=\"Resolution\">\n <NativeSelect value={resolution} onChange={(event) => onResolutionChange(event.target.value)}>\n {VIDEO_RESOLUTIONS.map((option) => <option key={option} value={option}>{option}</option>)}\n </NativeSelect>\n </Field>\n <Field label=\"Aspect ratio\">\n <NativeSelect value={aspectRatio} onChange={(event) => onAspectRatioChange(event.target.value)}>\n {VIDEO_ASPECT_RATIOS.map((option) => <option key={option} value={option}>{option}</option>)}\n </NativeSelect>\n </Field>\n <Field label=\"Reference image URL\"><Input value={referenceImageUrl} onChange={(event) => onReferenceImageUrlChange(event.target.value)} className=\"bg-background\" /></Field>\n </div>\n )\n}\n","import { Input } from '@tangle-network/sandbox-ui/primitives'\nimport { Field } from './composer-shell'\n\nexport function SpeechComposer({\n voice,\n onVoiceChange,\n}: {\n voice: string\n onVoiceChange: (value: string) => void\n}) {\n return (\n <Field label=\"Voice\"><Input value={voice} onChange={(event) => onVoiceChange(event.target.value)} className=\"bg-background\" /></Field>\n )\n}\n","import { Button } from '@tangle-network/sandbox-ui/primitives'\nimport { Images } from 'lucide-react'\n\nexport function StudioHeader({\n count,\n onOpenLibrary,\n canGenerate,\n}: {\n count: number\n onOpenLibrary: () => void\n canGenerate: boolean\n}) {\n return (\n <header className=\"sticky top-0 z-20 border-b border-border bg-card\">\n <div className=\"mx-auto flex w-full max-w-3xl items-center justify-between gap-3 px-4 py-3 sm:px-6\">\n <div className=\"min-w-0\">\n <h1 className=\"text-lg font-semibold tracking-tight text-foreground\">Studio</h1>\n <p className=\"truncate text-xs text-muted-foreground\">\n {canGenerate\n ? 'Generate images, video, voice, avatars, and transcripts.'\n : \"Browse your team's generations.\"}\n </p>\n </div>\n <Button size=\"sm\" variant=\"outline\" onClick={onOpenLibrary} className=\"shrink-0\">\n <Images className=\"mr-1.5 h-4 w-4\" />\n Library\n {count > 0 && (\n <span className=\"ml-2 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-primary/15 px-1.5 text-xs font-semibold text-primary\">\n {count}\n </span>\n )}\n </Button>\n </div>\n </header>\n )\n}\n","import { Badge } from '@tangle-network/sandbox-ui/primitives'\nimport { ArrowRight, Sparkles } from 'lucide-react'\nimport {\n type Generation,\n generationError,\n generationStatus,\n} from '../studio'\nimport { typeConfigFor } from './type-config'\n\nexport function ResultCanvas({\n batch,\n onOpenLibrary,\n onSelect,\n}: {\n batch: Generation[]\n onOpenLibrary: () => void\n onSelect: (generation: Generation) => void\n}) {\n const cardClass = 'rounded-xl border border-border bg-card shadow-sm'\n\n if (batch.length === 0) {\n return (\n <section className={`${cardClass} flex min-h-[180px] flex-col items-center justify-center gap-2 p-8 text-center`}>\n <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-muted\">\n <Sparkles className=\"h-6 w-6 text-muted-foreground/40\" />\n </div>\n <p className=\"text-sm font-medium text-foreground\">Your creations appear here</p>\n <p className=\"max-w-xs text-xs text-muted-foreground\">\n Generate above — results appear here and are saved to your library.\n </p>\n </section>\n )\n }\n\n const cfg = typeConfigFor(batch[0]?.type ?? 'image')\n const Icon = cfg.icon\n const statuses = batch.map(generationStatus)\n const runLabel = statuses.some((s) => s === 'pending' || s === 'running')\n ? 'Generating…'\n : statuses.every((s) => s === 'failed')\n ? 'Last run failed'\n : 'Latest creation'\n const isWorking = statuses.some((s) => s === 'pending' || s === 'running')\n\n return (\n <section className={`${cardClass} p-5`}>\n <div className=\"mb-3 flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-2\">\n <Badge variant=\"outline\" className={`${cfg.color} gap-1 text-xs`}>\n <Icon className=\"h-3 w-3\" />\n {cfg.label}\n </Badge>\n <span className=\"text-sm font-medium text-foreground\">{runLabel}</span>\n {isWorking && <span className=\"h-2 w-2 animate-pulse rounded-full bg-primary\" />}\n </div>\n <button\n type=\"button\"\n onClick={onOpenLibrary}\n className=\"flex items-center gap-1 text-xs font-medium text-primary transition-colors hover:text-primary/80\"\n >\n View in Library\n <ArrowRight className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n\n <div className={`grid gap-3 ${batch.length === 1 ? 'grid-cols-1' : 'grid-cols-2'}`}>\n {batch.map((generation) => (\n <button\n key={generation.id}\n type=\"button\"\n onClick={() => onSelect(generation)}\n className=\"studio-bloom group relative aspect-video overflow-hidden rounded-lg border border-border bg-secondary transition-colors hover:border-primary/40\"\n >\n <CanvasTile generation={generation} />\n </button>\n ))}\n </div>\n\n {batch.length > 1 && !isWorking && (\n <p className=\"mt-2 text-xs text-muted-foreground\">{batch.length} results from this run</p>\n )}\n </section>\n )\n}\n\nfunction CanvasTile({ generation }: { generation: Generation }) {\n const cfg = typeConfigFor(generation.type)\n const Icon = cfg.icon\n const status = generationStatus(generation)\n\n if (status === 'pending' || status === 'running') {\n return <div className=\"studio-shimmer absolute inset-0 h-full w-full\" />\n }\n if (status === 'failed') {\n return (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center gap-2 p-4 text-center\">\n <Icon className=\"h-6 w-6 text-destructive/50\" />\n <p className=\"line-clamp-3 text-xs text-destructive\">{generationError(generation) ?? 'Generation failed'}</p>\n </div>\n )\n }\n if (generation.type === 'image' && generation.result) {\n return <img src={generation.result} alt={generation.prompt} className=\"absolute inset-0 h-full w-full object-contain\" />\n }\n if ((generation.type === 'video' || generation.type === 'avatar') && generation.result) {\n return <video src={generation.result} controls className=\"absolute inset-0 h-full w-full object-contain\" />\n }\n if (generation.type === 'speech' && generation.result) {\n return (\n <div className=\"absolute inset-0 flex items-center justify-center p-4\">\n <audio src={generation.result} controls className=\"w-full\" />\n </div>\n )\n }\n if (generation.type === 'transcription' && generation.result) {\n return (\n <div className=\"absolute inset-0 overflow-y-auto p-4\">\n <p className=\"whitespace-pre-wrap text-xs text-foreground\">{generation.result}</p>\n </div>\n )\n }\n return (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <Icon className=\"h-8 w-8 text-muted-foreground/20\" />\n </div>\n )\n}\n","import { useMemo } from 'react'\nimport { Link } from 'react-router'\nimport {\n Button,\n Tabs, TabsList, TabsTrigger,\n} from '@tangle-network/sandbox-ui/primitives'\nimport { ArrowLeft, DollarSign, FolderOpen, X } from 'lucide-react'\nimport { type Generation } from '../studio'\nimport { TYPE_CONFIG } from './type-config'\nimport { StudioSheet } from './studio-sheet'\nimport { GenerationGrid, filterGenerations } from './generation-grid'\nimport { GenerationDetail } from './generation-detail'\n\nexport function LibraryDrawer({\n open,\n onOpenChange,\n generations,\n totalCost,\n typeFilter,\n onFilterChange,\n vaultHref,\n selected,\n onSelect,\n}: {\n open: boolean\n onOpenChange: (open: boolean) => void\n generations: Generation[]\n totalCost: number\n typeFilter: string | null\n onFilterChange: (type: string | null) => void\n vaultHref?: (filePath?: string | null) => string\n selected: Generation | null\n onSelect: (generation: Generation | null) => void\n}) {\n const visible = useMemo(() => filterGenerations(generations, typeFilter), [generations, typeFilter])\n\n return (\n <StudioSheet open={open} onOpenChange={onOpenChange} title=\"Asset library\">\n <header className=\"flex shrink-0 items-center justify-between gap-3 border-b border-border px-4 py-3\">\n {selected ? (\n <button\n type=\"button\"\n onClick={() => onSelect(null)}\n className=\"flex items-center gap-1.5 text-sm font-medium text-foreground transition-colors hover:text-primary\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to library\n </button>\n ) : (\n <h2 className=\"text-sm font-semibold text-foreground\">Asset library</h2>\n )}\n <button\n type=\"button\"\n aria-label=\"Close library\"\n onClick={() => onOpenChange(false)}\n className=\"rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </header>\n\n {selected ? (\n <div className=\"flex-1 overflow-y-auto p-4\">\n <GenerationDetail\n generation={selected}\n vaultHref={vaultHref}\n onNavigate={() => onOpenChange(false)}\n />\n </div>\n ) : (\n <>\n <div className=\"shrink-0 border-b border-border px-4 pt-3\">\n <div className=\"mb-2 flex items-center justify-between gap-3\">\n <div className=\"flex items-center gap-3 text-xs text-muted-foreground\">\n <span>{visible.length} generation{visible.length !== 1 ? 's' : ''}</span>\n <span className=\"flex items-center gap-0.5\">\n <DollarSign className=\"h-3 w-3\" />\n {totalCost.toFixed(2)} spent\n </span>\n </div>\n {vaultHref && (\n <Link to={vaultHref()} prefetch=\"intent\" onClick={() => onOpenChange(false)}>\n <Button size=\"sm\" variant=\"outline\">\n <FolderOpen className=\"mr-1.5 h-3.5 w-3.5\" />\n Vault\n </Button>\n </Link>\n )}\n </div>\n <Tabs value={typeFilter ?? 'all'} onValueChange={(v) => onFilterChange(v === 'all' ? null : v)}>\n <TabsList className=\"h-9 w-full justify-start gap-1 overflow-x-auto bg-transparent\">\n <TabsTrigger value=\"all\" className=\"text-xs\">All</TabsTrigger>\n {Object.entries(TYPE_CONFIG).map(([key, cfg]) => (\n <TabsTrigger key={key} value={key} className=\"text-xs\">{cfg.label}</TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n </div>\n\n <div className=\"flex-1 overflow-y-auto p-4\">\n <GenerationGrid generations={visible} typeFilter={typeFilter} onSelect={onSelect} />\n </div>\n </>\n )}\n </StudioSheet>\n )\n}\n","import type { ReactNode } from 'react'\nimport * as Dialog from '@radix-ui/react-dialog'\n\n/**\n * Right-side overlay sheet built on Radix Dialog — gives focus-trap, scroll-lock,\n * and Escape-to-close for free. Slide/fade come from the studio-sheet-* classes in\n * ./studio.css (driven by Radix data-state), not tailwindcss-animate.\n */\nexport function StudioSheet({\n open,\n onOpenChange,\n title,\n children,\n}: {\n open: boolean\n onOpenChange: (open: boolean) => void\n title: string\n children: ReactNode\n}) {\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <Dialog.Overlay className=\"studio-sheet-overlay fixed inset-0 z-50 bg-black/50\" />\n <Dialog.Content\n className=\"studio-sheet-content fixed inset-y-0 right-0 z-50 flex w-[min(92vw,30rem)] flex-col border-l border-card-edge bg-popover shadow-[var(--shadow-overlay)] focus:outline-none\"\n aria-describedby={undefined}\n >\n <Dialog.Title className=\"sr-only\">{title}</Dialog.Title>\n {children}\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n )\n}\n","import { EmptyState } from '@tangle-network/sandbox-ui/primitives'\nimport { Film, Sparkles } from 'lucide-react'\nimport { type Generation, isGenerationType } from '../studio'\nimport { TYPE_CONFIG } from './type-config'\nimport { GenerationCard } from './generation-card'\n\n/** The visible set for the active type tab (all generations when unfiltered). */\nexport function filterGenerations(generations: Generation[], typeFilter: string | null): Generation[] {\n if (!typeFilter || !isGenerationType(typeFilter)) return generations\n return generations.filter((generation) => generation.type === typeFilter)\n}\n\n/**\n * Chrome-less asset grid — the `GenerationCard` grid plus its empty state, with\n * no surrounding tabs/stats/sheet chrome. Composed by both the inline\n * `LibraryPanel` and the `LibraryDrawer`'s list view so the grid and its\n * empty-state copy stay in one place. `generations` is the already-filtered\n * visible set; `typeFilter` only tunes the empty-state message.\n */\nexport function GenerationGrid({\n generations,\n typeFilter,\n onSelect,\n}: {\n generations: Generation[]\n typeFilter: string | null\n onSelect: (generation: Generation) => void\n}) {\n if (generations.length === 0) {\n return (\n <EmptyState\n icon={typeFilter\n ? <Film className=\"h-8 w-8 text-muted-foreground/30\" />\n : <Sparkles className=\"h-10 w-10 text-muted-foreground/30\" />}\n title={typeFilter\n ? `No ${TYPE_CONFIG[typeFilter]?.label ?? typeFilter} generations`\n : 'No generations yet'}\n description={typeFilter\n ? 'Try a different filter or change the type in the composer.'\n : 'Everything you and the agent create lives here.'}\n className=\"py-16\"\n />\n )\n }\n return (\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {generations.map((generation) => (\n <GenerationCard key={generation.id} generation={generation} onSelect={onSelect} />\n ))}\n </div>\n )\n}\n","import { Card, CardContent, Badge } from '@tangle-network/sandbox-ui/primitives'\nimport {\n type Generation,\n generationError,\n generationStatus,\n relativeTime,\n} from '../studio'\nimport { typeConfigFor } from './type-config'\n\nexport function GenerationCard({\n generation,\n onSelect,\n}: {\n generation: Generation\n onSelect: (generation: Generation) => void\n}) {\n const cfg = typeConfigFor(generation.type)\n const Icon = cfg.icon\n const status = generationStatus(generation)\n return (\n <button type=\"button\" onClick={() => onSelect(generation)} className=\"group text-left animate-row-in\">\n <Card className=\"overflow-hidden transition-all group-hover:border-primary/50 group-hover:shadow-md\">\n <div className=\"relative aspect-video bg-secondary\">\n {generation.type === 'image' && generation.result ? (\n <img src={generation.result} alt={generation.prompt} className=\"h-full w-full object-cover\" />\n ) : (generation.type === 'video' || generation.type === 'avatar') && generation.result ? (\n <video src={generation.result} className=\"h-full w-full object-cover\" muted />\n ) : generation.type === 'speech' && generation.result ? (\n <div className=\"flex h-full items-center justify-center\">\n <Icon className=\"h-6 w-6 text-muted-foreground/40\" />\n </div>\n ) : generation.type === 'transcription' && generation.result ? (\n <div className=\"flex h-full items-center justify-center p-4\">\n <p className=\"line-clamp-5 text-xs text-muted-foreground\">{generation.result}</p>\n </div>\n ) : status === 'pending' || status === 'running' ? (\n <div className=\"shimmer h-full w-full\" />\n ) : (\n <div className=\"flex h-full items-center justify-center\">\n <Icon className=\"h-8 w-8 text-muted-foreground/20\" />\n </div>\n )}\n <div className=\"absolute left-2 top-2\">\n <Badge variant=\"outline\" className={`${cfg.color} gap-1 text-xs`}>\n <Icon className=\"h-3 w-3\" />\n {cfg.label}\n </Badge>\n </div>\n <GenerationStatusBadge generation={generation} />\n </div>\n <CardContent className=\"p-3\">\n <p className=\"mb-2 line-clamp-2 text-sm font-medium text-foreground\">{generation.prompt}</p>\n {status === 'failed' && (\n <p className=\"mb-2 line-clamp-2 text-xs text-destructive\">{generationError(generation)}</p>\n )}\n <div className=\"flex items-center justify-between\">\n {generation.model && (\n <span className=\"truncate text-xs text-muted-foreground\">{generation.model}</span>\n )}\n <div className=\"flex shrink-0 items-center gap-2\">\n {generation.cost != null && (\n <span className=\"text-xs text-muted-foreground\">${generation.cost.toFixed(3)}</span>\n )}\n <span className=\"text-xs text-muted-foreground\">{relativeTime(generation.createdAt)}</span>\n </div>\n </div>\n </CardContent>\n </Card>\n </button>\n )\n}\n\nexport function GenerationStatusBadge({\n generation,\n inline = false,\n}: {\n generation: Generation\n inline?: boolean\n}) {\n const status = generationStatus(generation)\n if (status === 'succeeded') return null\n\n const label = status === 'failed' ? 'Failed' : status === 'running' ? 'Running' : 'Pending'\n // Solid tint mixed onto the card surface — the badge floats over media, so an\n // alpha fill would let the thumbnail bleed through.\n const className = status === 'failed'\n ? 'border-destructive/30 bg-[color-mix(in_srgb,hsl(var(--destructive))_10%,hsl(var(--card)))] text-destructive'\n : 'border-warning/30 bg-[color-mix(in_srgb,hsl(var(--warning))_10%,hsl(var(--card)))] text-warning'\n\n return (\n <div className={inline ? '' : 'absolute bottom-2 left-2'}>\n <Badge variant=\"outline\" className={`${className} text-xs`}>\n {label}\n </Badge>\n </div>\n )\n}\n","import { Link } from 'react-router'\nimport { Badge, Button } from '@tangle-network/sandbox-ui/primitives'\nimport { FolderOpen } from 'lucide-react'\nimport {\n type Generation,\n generationError,\n generationVaultPath,\n} from '../studio'\nimport { typeConfigFor } from './type-config'\nimport { GenerationStatusBadge } from './generation-card'\n\nexport function GenerationDetail({\n generation,\n vaultHref,\n onNavigate,\n}: {\n generation: Generation\n vaultHref?: (filePath?: string | null) => string\n onNavigate?: () => void\n}) {\n const cfg = typeConfigFor(generation.type)\n const Icon = cfg.icon\n // Only offer the vault link when the generation actually persisted a file.\n // generationVaultPath is null for failed/pending/running and storage-failed\n // generations; without this guard vaultHref(null) falls back to the vault\n // root, rendering a button that opens nothing relevant.\n const vaultPath = generationVaultPath(generation)\n const href = vaultHref && vaultPath ? vaultHref(vaultPath) : null\n\n return (\n <div className=\"space-y-4\">\n <div className=\"overflow-hidden rounded-lg bg-secondary\">\n {generation.type === 'image' && generation.result ? (\n <img src={generation.result} alt={generation.prompt} className=\"max-h-[420px] w-full object-contain\" />\n ) : (generation.type === 'video' || generation.type === 'avatar') && generation.result ? (\n <video src={generation.result} controls className=\"max-h-[420px] w-full\" />\n ) : generation.type === 'speech' && generation.result ? (\n <div className=\"p-6\">\n <audio src={generation.result} controls className=\"w-full\" />\n </div>\n ) : (\n <div className=\"flex h-32 items-center justify-center\">\n <Icon className=\"h-8 w-8 text-muted-foreground/20\" />\n </div>\n )}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <Badge variant=\"outline\" className={`${cfg.color} gap-1`}>\n <Icon className=\"h-3 w-3\" />\n {cfg.label}\n </Badge>\n <GenerationStatusBadge generation={generation} inline />\n {generationError(generation) && (\n <span className=\"text-xs text-destructive\">{generationError(generation)}</span>\n )}\n </div>\n\n <div>\n <span className=\"mb-1 block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\">Prompt</span>\n <p className=\"text-sm text-foreground\">{generation.prompt}</p>\n </div>\n\n <div className=\"flex flex-wrap items-center gap-4\">\n {generation.model && (\n <div>\n <span className=\"block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\">Model</span>\n <span className=\"text-xs text-foreground\">{generation.model}</span>\n </div>\n )}\n {generation.cost != null && (\n <div>\n <span className=\"block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\">Cost</span>\n <span className=\"text-xs text-foreground\">${generation.cost.toFixed(3)}</span>\n </div>\n )}\n {generation.createdAt && (\n <div>\n <span className=\"block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\">Created</span>\n <span className=\"text-xs text-foreground\">\n {new Date(generation.createdAt).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' })}\n </span>\n </div>\n )}\n </div>\n\n {generation.type === 'transcription' && generation.result && (\n <div>\n <span className=\"mb-1 block text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground\">Transcription</span>\n <pre className=\"max-h-64 overflow-y-auto whitespace-pre-wrap rounded-lg bg-secondary p-4 font-mono text-[13px] tabular-nums text-foreground\">\n {generation.result}\n </pre>\n </div>\n )}\n\n {href && (\n <div className=\"border-t border-border pt-2\">\n <Link to={href} prefetch=\"intent\" onClick={onNavigate}>\n <Button size=\"sm\" variant=\"outline\">\n <FolderOpen className=\"mr-1.5 h-3.5 w-3.5\" />\n Open in Vault\n </Button>\n </Link>\n </div>\n )}\n </div>\n )\n}\n","import { useMemo } from 'react'\nimport {\n Tabs, TabsList, TabsTrigger,\n} from '@tangle-network/sandbox-ui/primitives'\nimport { DollarSign } from 'lucide-react'\nimport { type Generation } from '../studio'\nimport { TYPE_CONFIG } from './type-config'\nimport { GenerationGrid, filterGenerations } from './generation-grid'\n\n/**\n * Inline asset gallery — the same filter + stats + card grid as the library\n * drawer's list view, but with no sheet chrome so it can sit on the page beside\n * the composer. In-flight generations need no special handling: they arrive at\n * the front of `generations` (via `useStudioGenerations.mergedGenerations`) and\n * `GenerationCard` renders their `pending`/`running` shimmer.\n */\nexport function LibraryPanel({\n generations,\n totalCost,\n typeFilter,\n onFilterChange,\n onSelect,\n}: {\n generations: Generation[]\n totalCost: number\n typeFilter: string | null\n onFilterChange: (type: string | null) => void\n onSelect: (generation: Generation) => void\n}) {\n const visible = useMemo(() => filterGenerations(generations, typeFilter), [generations, typeFilter])\n\n return (\n <div className=\"flex min-w-0 flex-col\">\n <div className=\"mb-4 flex flex-wrap items-center justify-between gap-3\">\n <Tabs value={typeFilter ?? 'all'} onValueChange={(v) => onFilterChange(v === 'all' ? null : v)}>\n <TabsList className=\"h-9 justify-start gap-1 overflow-x-auto overflow-y-hidden rounded-lg border border-border bg-background p-1\">\n <TabsTrigger\n value=\"all\"\n className=\"rounded-md px-3 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground data-[state=active]:bg-primary/10 data-[state=active]:font-semibold data-[state=active]:text-primary data-[state=active]:shadow-none\"\n >\n All\n </TabsTrigger>\n {Object.entries(TYPE_CONFIG).map(([key, cfg]) => (\n <TabsTrigger\n key={key}\n value={key}\n className=\"rounded-md px-3 text-xs font-medium text-muted-foreground transition-colors hover:text-foreground data-[state=active]:bg-primary/10 data-[state=active]:font-semibold data-[state=active]:text-primary data-[state=active]:shadow-none\"\n >\n {cfg.label}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n <div className=\"flex items-center gap-3 text-xs text-muted-foreground\">\n <span>{visible.length} generation{visible.length !== 1 ? 's' : ''}</span>\n <span className=\"flex items-center gap-0.5\">\n <DollarSign className=\"h-3 w-3\" />\n {totalCost.toFixed(2)} spent\n </span>\n </div>\n </div>\n\n <GenerationGrid generations={visible} typeFilter={typeFilter} onSelect={onSelect} />\n </div>\n )\n}\n","import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@tangle-network/sandbox-ui/primitives'\nimport { type Generation } from '../studio'\nimport { typeConfigFor } from './type-config'\nimport { GenerationDetail } from './generation-detail'\n\n/**\n * Centered detail view for a single generation. Opens when `generation` is set\n * and reports dismissal through `onClose`. GenerationDetail renders the media,\n * type badge, prompt and metadata; the dialog title carries the a11y label.\n */\nexport function GenerationDetailModal({\n generation,\n vaultHref,\n onClose,\n}: {\n generation: Generation | null\n vaultHref?: (filePath?: string | null) => string\n onClose: () => void\n}) {\n const cfg = generation ? typeConfigFor(generation.type) : null\n return (\n <Dialog open={generation != null} onOpenChange={(open) => { if (!open) onClose() }}>\n <DialogContent className=\"max-h-[85vh] max-w-2xl overflow-y-auto border-card-edge bg-popover shadow-[var(--shadow-overlay)]\">\n <DialogHeader>\n <DialogTitle className=\"text-left text-[15px] font-semibold\">{cfg ? `${cfg.label} generation` : 'Generation'}</DialogTitle>\n </DialogHeader>\n {generation && (\n <GenerationDetail generation={generation} vaultHref={vaultHref} onNavigate={onClose} />\n )}\n </DialogContent>\n </Dialog>\n )\n}\n","import { Input } from '@tangle-network/sandbox-ui/primitives'\nimport { Field } from './composer-shell'\n\nexport function AvatarComposer({\n audioUrl,\n imageUrl,\n avatarId,\n onAudioUrlChange,\n onImageUrlChange,\n onAvatarIdChange,\n}: {\n audioUrl: string\n imageUrl: string\n avatarId: string\n onAudioUrlChange: (value: string) => void\n onImageUrlChange: (value: string) => void\n onAvatarIdChange: (value: string) => void\n}) {\n return (\n <div className=\"mt-4 grid gap-3 sm:grid-cols-2\">\n <Field label=\"Audio URL\" htmlFor=\"studio-audio-url\">\n <Input\n id=\"studio-audio-url\"\n value={audioUrl}\n onChange={(event) => onAudioUrlChange(event.target.value)}\n placeholder=\"https://cdn.example.com/source-audio.mp3\"\n className=\"bg-background\"\n />\n </Field>\n <Field label=\"Image URL\" htmlFor=\"studio-avatar-image-url\">\n <Input\n id=\"studio-avatar-image-url\"\n value={imageUrl}\n onChange={(event) => onImageUrlChange(event.target.value)}\n placeholder=\"https://cdn.example.com/portrait.png\"\n className=\"bg-background\"\n />\n </Field>\n <Field label=\"Avatar ID\" htmlFor=\"studio-avatar-id\">\n <Input\n id=\"studio-avatar-id\"\n value={avatarId}\n onChange={(event) => onAvatarIdChange(event.target.value)}\n placeholder=\"Optional provider avatar id\"\n className=\"bg-background\"\n />\n </Field>\n </div>\n )\n}\n","import { Input } from '@tangle-network/sandbox-ui/primitives'\nimport { Field, NativeSelect } from './composer-shell'\n\nexport function TranscriptionComposer({\n audioUrl,\n language,\n onAudioUrlChange,\n onLanguageChange,\n}: {\n audioUrl: string\n language: string\n onAudioUrlChange: (value: string) => void\n onLanguageChange: (value: string) => void\n}) {\n return (\n <div className=\"mt-4 grid gap-3 sm:grid-cols-2\">\n <Field label=\"Audio URL\" htmlFor=\"studio-audio-url\">\n <Input\n id=\"studio-audio-url\"\n value={audioUrl}\n onChange={(event) => onAudioUrlChange(event.target.value)}\n placeholder=\"https://cdn.example.com/source-audio.mp3\"\n className=\"bg-background\"\n />\n </Field>\n <Field label=\"Language\" htmlFor=\"studio-transcription-language\">\n <Input\n id=\"studio-transcription-language\"\n value={language}\n onChange={(event) => onLanguageChange(event.target.value)}\n placeholder=\"en\"\n className=\"bg-background\"\n />\n </Field>\n </div>\n )\n}\n\nexport function TranscriptionOptions({\n responseFormat,\n temperature,\n onResponseFormatChange,\n onTemperatureChange,\n}: {\n responseFormat: string\n temperature: string\n onResponseFormatChange: (value: string) => void\n onTemperatureChange: (value: string) => void\n}) {\n return (\n <>\n <Field label=\"Response format\">\n <NativeSelect value={responseFormat} onChange={(event) => onResponseFormatChange(event.target.value)}>\n <option value=\"json\">JSON</option>\n <option value=\"text\">Text</option>\n <option value=\"srt\">SRT</option>\n <option value=\"verbose_json\">Verbose JSON</option>\n <option value=\"vtt\">VTT</option>\n </NativeSelect>\n </Field>\n <Field label=\"Temperature\"><Input type=\"number\" min=\"0\" max=\"1\" step=\"0.1\" value={temperature} onChange={(event) => onTemperatureChange(event.target.value)} className=\"bg-background\" /></Field>\n </>\n )\n}\n"],"mappings":"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","names":["useRef","useState","Button","Images","useEffect","useRef","useState","Input","Label","jsx","jsxs","Input","jsx","jsxs","Input","Input","jsx","Input","jsx","jsxs","useState","useRef","useEffect","Label","Input","Button","jsx","jsxs","Sparkles","jsx","jsxs","Sparkles","useMemo","Link","Button","FolderOpen","jsx","jsxs","Sparkles","Badge","jsx","jsxs","Badge","jsx","Sparkles","Badge","Button","jsx","jsxs","Badge","Button","jsx","jsxs","useMemo","Link","Button","FolderOpen","Fragment","jsx","jsxs","useState","useRef","Images","Button","useMemo","Tabs","TabsList","TabsTrigger","DollarSign","jsx","jsxs","useMemo","Tabs","TabsList","TabsTrigger","DollarSign","Dialog","jsx","jsxs","Dialog","Input","jsx","jsxs","Input","Input","Fragment","jsx","jsxs","Input"]}
|
|
@@ -9,8 +9,6 @@ export interface StudioWorkspaceProps {
|
|
|
9
9
|
generationsEndpoint?: string;
|
|
10
10
|
/** Build a vault link, optionally to a specific file. Defaults to `/app/<workspaceId>/vault`. */
|
|
11
11
|
vaultHref?: (filePath?: string | null) => string;
|
|
12
|
-
/** Integrations page href for the publish-package "Connect" link. Defaults to `/app/<workspaceId>/integrations`. */
|
|
13
|
-
integrationsHref?: string;
|
|
14
12
|
}
|
|
15
13
|
/**
|
|
16
14
|
* The full studio surface: header + composer + result canvas + library drawer,
|
|
@@ -18,6 +16,6 @@ export interface StudioWorkspaceProps {
|
|
|
18
16
|
* route owns the loader (auth, RBAC, the generation query) and the server
|
|
19
17
|
* endpoints (`/api/generate`, `/api/media-models`, `/api/generations`); this
|
|
20
18
|
* shell renders that data and drives the live UI. Role gates the composer
|
|
21
|
-
* (viewers get a read-only library)
|
|
19
|
+
* (viewers get a read-only library).
|
|
22
20
|
*/
|
|
23
|
-
export declare function StudioWorkspace({ generations, totalCost, workspaceId, role, generationsEndpoint, vaultHref,
|
|
21
|
+
export declare function StudioWorkspace({ generations, totalCost, workspaceId, role, generationsEndpoint, vaultHref, }: StudioWorkspaceProps): import("react").JSX.Element;
|