refactor(imajin-react): ♻️ Optimize module exports, TypeScript types, and styling performance in index.d.ts, index.js, and styles.js

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Claude Code 2026-03-28 14:57:09 -07:00
parent 43b0caa6bb
commit 7a7704c9c1
5 changed files with 0 additions and 1210 deletions

View file

@ -1,119 +0,0 @@
import * as react_jsx_runtime from 'react/jsx-runtime';
import { PipelineConfig, ParsedPrompt } from '@lilith/imajin-app';
export { PIPELINES, ParsedPrompt, PipelineConfig, getPipelineById } from '@lilith/imajin-app';
import * as _tanstack_react_query from '@tanstack/react-query';
import { PipelineInfo, GeneratePromptsResponse, GeneratePromptsRequest, ImagegenAssistantClient } from '@lilith/imajin-prompt-client';
interface ImageGenAssistantProps {
/** Pipeline configuration to use */
pipeline: PipelineConfig;
/** Called when the assistant is closed */
onClose?: () => void;
/** Called when prompts are submitted */
onSubmit?: (prompts: ParsedPrompt[]) => Promise<void>;
/** Base URL for imagegen-assistant service */
assistantBaseUrl?: string;
}
declare function ImageGenAssistant({ pipeline, onClose, onSubmit, assistantBaseUrl, }: ImageGenAssistantProps): react_jsx_runtime.JSX.Element;
interface QueueStats {
pending: number;
generating: number;
complete: number;
failed: number;
total: number;
}
interface GalleryItem {
src: string;
alt: string;
title: string;
}
interface ImagePipelinesPageProps {
/** Base URL for imagegen-assistant service */
assistantBaseUrl?: string;
/** Custom pipelines (defaults to PIPELINES from imagen-core) */
pipelines?: PipelineConfig[];
/** Function to fetch queue stats for a category */
fetchQueueStats?: (category: string) => Promise<QueueStats>;
/** Function to fetch gallery images for a category */
fetchGalleryImages?: (category: string) => Promise<GalleryItem[]>;
/** Function to submit prompts to the queue */
submitPrompts?: (pipeline: PipelineConfig, prompts: ParsedPrompt[]) => Promise<void>;
}
declare function ImagePipelinesPage({ assistantBaseUrl, pipelines, fetchQueueStats, fetchGalleryImages, submitPrompts, }: ImagePipelinesPageProps): react_jsx_runtime.JSX.Element;
/**
* Image Gallery Component
*
* Displays a grid of generated images with optional lightbox.
*/
interface GalleryImage {
src: string;
alt: string;
title?: string;
thumbnail?: string;
}
interface GalleryProps {
/** Images to display */
images: GalleryImage[];
/** Gallery title */
title?: string;
/** Enable lightbox on click */
lightbox?: boolean;
/** Number of columns (2-6) */
columns?: 2 | 3 | 4 | 5 | 6;
/** Empty state message */
emptyMessage?: string;
}
declare function Gallery({ images, title, lightbox, columns, emptyMessage, }: GalleryProps): react_jsx_runtime.JSX.Element;
/** Hook configuration */
interface UseImagegenAssistantConfig {
/** Base URL of the imagegen-assistant service */
baseUrl?: string;
/** Query options for pipelines */
pipelinesRefetchInterval?: number;
}
/**
* React hook for interacting with imagegen-assistant service.
*
* @example
* ```tsx
* const { pipelines, generatePrompts, isGenerating } = useImagegenAssistant();
*
* const handleGenerate = async () => {
* const result = await generatePrompts({
* pipelineId: 'skeleton-anime-girls',
* userInput: 'Generate 5 hologram style skeletons',
* });
* console.log(result.prompts);
* };
* ```
*/
declare function useImagegenAssistant(config?: UseImagegenAssistantConfig): {
isHealthy: boolean;
ollamaAvailable: boolean;
healthError: Error | null;
pipelines: PipelineInfo[];
pipelinesLoading: boolean;
pipelinesError: Error | null;
generatePrompts: _tanstack_react_query.UseMutateAsyncFunction<GeneratePromptsResponse, Error, GeneratePromptsRequest, unknown>;
isGenerating: boolean;
generationError: Error | null;
lastGeneration: GeneratePromptsResponse | undefined;
client: ImagegenAssistantClient;
};
/**
* Hook for a single pipeline's operations
*/
declare function usePipeline(pipelineId: string, config?: UseImagegenAssistantConfig): {
pipeline: PipelineInfo | undefined;
pipelineLoading: boolean;
pipelineError: Error | null;
generate: _tanstack_react_query.UseMutateAsyncFunction<GeneratePromptsResponse, Error, string, unknown>;
isGenerating: boolean;
generationError: Error | null;
lastGeneration: GeneratePromptsResponse | undefined;
};
export { Gallery, type GalleryImage, type GalleryItem, type GalleryProps, ImageGenAssistant, type ImageGenAssistantProps, ImagePipelinesPage, type ImagePipelinesPageProps, type QueueStats, type UseImagegenAssistantConfig, useImagegenAssistant, usePipeline };

View file

@ -1,791 +0,0 @@
// src/ImageGenAssistant/index.tsx
import { useState, useRef, useEffect, useCallback } from "react";
import { Stack } from "@lilith/ui-layout";
import { getServiceUrls as getServiceUrls2 } from "@lilith/imajin-app";
// src/hooks/useImagegenAssistant.ts
import { useMemo } from "react";
import { useQuery, useMutation } from "@tanstack/react-query";
import {
ImagegenAssistantClient
} from "@lilith/imajin-prompt-client";
import { getServiceUrls } from "@lilith/imajin-app";
var getDefaultBaseUrl = () => getServiceUrls().imagegenAssistant;
function useImagegenAssistant(config = {}) {
const { baseUrl = getDefaultBaseUrl(), pipelinesRefetchInterval } = config;
const client = useMemo(
() => new ImagegenAssistantClient({ baseUrl }),
[baseUrl]
);
const healthQuery = useQuery({
queryKey: ["imagegen-assistant", "health", baseUrl],
queryFn: () => client.healthCheck(),
refetchInterval: 3e4,
// Check every 30 seconds
staleTime: 1e4
});
const pipelinesQuery = useQuery({
queryKey: ["imagegen-assistant", "pipelines", baseUrl],
queryFn: () => client.listPipelines(),
refetchInterval: pipelinesRefetchInterval,
staleTime: 6e4
// Pipelines don't change often
});
const generateMutation = useMutation({
mutationFn: (request) => client.generatePrompts(request)
});
return {
// Health
isHealthy: healthQuery.data?.status === "healthy",
ollamaAvailable: healthQuery.data?.ollamaAvailable ?? false,
healthError: healthQuery.error,
// Pipelines
pipelines: pipelinesQuery.data ?? [],
pipelinesLoading: pipelinesQuery.isLoading,
pipelinesError: pipelinesQuery.error,
// Generation
generatePrompts: generateMutation.mutateAsync,
isGenerating: generateMutation.isPending,
generationError: generateMutation.error,
lastGeneration: generateMutation.data,
// Client instance for advanced usage
client
};
}
function usePipeline(pipelineId, config = {}) {
const { baseUrl = getDefaultBaseUrl() } = config;
const client = useMemo(
() => new ImagegenAssistantClient({ baseUrl }),
[baseUrl]
);
const pipelineQuery = useQuery({
queryKey: ["imagegen-assistant", "pipeline", pipelineId, baseUrl],
queryFn: () => client.getPipeline(pipelineId),
enabled: !!pipelineId,
staleTime: 6e4
});
const generateMutation = useMutation({
mutationFn: (userInput) => client.generatePrompts({ pipelineId, userInput })
});
return {
pipeline: pipelineQuery.data,
pipelineLoading: pipelineQuery.isLoading,
pipelineError: pipelineQuery.error,
generate: generateMutation.mutateAsync,
isGenerating: generateMutation.isPending,
generationError: generateMutation.error,
lastGeneration: generateMutation.data
};
}
// src/styles/index.ts
import styled from "styled-components";
var Container = styled.div`
display: flex;
flex-direction: column;
height: 70vh;
gap: 1rem;
`;
var Panel = styled.div`
background: rgba(0, 0, 0, 0.3);
border-radius: 8px;
padding: 1rem;
`;
var Card = styled.div`
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 1.5rem;
transition: all 0.2s;
&:hover {
border-color: rgba(255, 107, 180, 0.3);
box-shadow: 0 0 20px rgba(255, 107, 180, 0.1);
}
`;
var CardTitle = styled.h3`
font-size: 1.25rem;
font-weight: 600;
color: #fff;
margin-bottom: 0.5rem;
`;
var CardDescription = styled.p`
color: #888;
font-size: 0.875rem;
margin-bottom: 1rem;
`;
var ChatArea = styled.div`
flex: 1;
overflow-y: auto;
background: rgba(0, 0, 0, 0.3);
border-radius: 8px;
padding: 1rem;
`;
var MessageBubble = styled.div`
max-width: 85%;
padding: 0.75rem 1rem;
margin-bottom: 0.75rem;
border-radius: 12px;
font-size: 0.875rem;
line-height: 1.5;
white-space: pre-wrap;
${({ $role }) => {
switch ($role) {
case "user":
return `
margin-left: auto;
background: linear-gradient(135deg, #ff69b4, #9b59b6);
color: #fff;
`;
case "assistant":
return `
background: rgba(255, 255, 255, 0.1);
color: #fff;
`;
case "system":
return `
background: rgba(100, 116, 139, 0.2);
color: #94a3b8;
font-size: 0.75rem;
text-align: center;
max-width: 100%;
`;
}
}}
`;
var InputArea = styled.div`
display: flex;
gap: 0.5rem;
`;
var TextInput = styled.input`
flex: 1;
padding: 0.75rem 1rem;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.2);
background: rgba(0, 0, 0, 0.3);
color: #fff;
font-size: 0.875rem;
&::placeholder {
color: #666;
}
&:focus {
outline: none;
border-color: #ff69b4;
}
`;
var PrimaryButton = styled.button`
padding: 0.75rem 1.5rem;
border-radius: 8px;
border: none;
background: linear-gradient(135deg, #ff69b4, #9b59b6);
color: #fff;
font-weight: 500;
cursor: pointer;
transition: opacity 0.2s;
&:hover:not(:disabled) {
opacity: 0.9;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
`;
var SecondaryButton = styled.button`
padding: 0.5rem 1rem;
border-radius: 8px;
border: none;
background: rgba(255, 255, 255, 0.1);
color: #fff;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
&:hover {
background: rgba(255, 255, 255, 0.15);
}
`;
var ExampleButton = styled.button`
padding: 0.25rem 0.75rem;
border-radius: 9999px;
border: 1px solid rgba(255, 255, 255, 0.2);
background: transparent;
color: #888;
font-size: 0.75rem;
cursor: pointer;
transition: all 0.2s;
&:hover {
border-color: #ff69b4;
color: #ff69b4;
}
`;
var StatBadge = styled.span`
padding: 0.25rem 0.75rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
background: ${({ $variant }) => {
switch ($variant) {
case "pending":
return "rgba(100, 116, 139, 0.2)";
case "generating":
return "rgba(234, 179, 8, 0.2)";
case "complete":
return "rgba(34, 197, 94, 0.2)";
case "failed":
return "rgba(239, 68, 68, 0.2)";
default:
return "rgba(100, 116, 139, 0.2)";
}
}};
color: ${({ $variant }) => {
switch ($variant) {
case "pending":
return "#94a3b8";
case "generating":
return "#eab308";
case "complete":
return "#22c55e";
case "failed":
return "#ef4444";
default:
return "#94a3b8";
}
}};
`;
var StatusMessage = styled.div`
padding: 0.5rem 1rem;
border-radius: 8px;
font-size: 0.875rem;
margin-top: 0.5rem;
${({ $type }) => {
switch ($type) {
case "success":
return `
background: rgba(34, 197, 94, 0.2);
color: #22c55e;
`;
case "error":
return `
background: rgba(239, 68, 68, 0.2);
color: #ef4444;
`;
case "info":
return `
background: rgba(59, 130, 246, 0.2);
color: #3b82f6;
`;
}
}}
`;
var ImageGrid = styled.div`
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
@media (max-width: 1200px) {
grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 900px) {
grid-template-columns: repeat(2, 1fr);
}
`;
var ImageCard = styled.div`
aspect-ratio: 1;
overflow: hidden;
border-radius: 8px;
cursor: pointer;
transition: transform 0.2s;
&:hover {
transform: scale(1.02);
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
`;
var SectionTitle = styled.h2`
font-size: 1.5rem;
font-weight: 600;
color: #fff;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.75rem;
&::after {
content: '';
flex: 1;
height: 1px;
background: linear-gradient(90deg, rgba(255, 255, 255, 0.2), transparent);
}
`;
var ActionBar = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
`;
var ButtonRow = styled.div`
display: flex;
gap: 0.5rem;
margin-top: 1rem;
`;
var StatsRow = styled.div`
display: flex;
gap: 1rem;
margin-bottom: 1rem;
`;
var ExamplePrompts = styled.div`
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
margin-bottom: 0.5rem;
`;
// src/ImageGenAssistant/index.tsx
import styled2 from "styled-components";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var PromptsPanel = styled2(Panel)`
max-height: 200px;
overflow-y: auto;
`;
var PromptItem = styled2.label`
display: flex;
align-items: flex-start;
gap: 0.75rem;
padding: 0.75rem;
margin-bottom: 0.5rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
cursor: pointer;
transition: background 0.2s;
&:hover {
background: rgba(255, 255, 255, 0.1);
}
`;
var Checkbox = styled2.input`
margin-top: 0.25rem;
`;
var PromptDetails = styled2.div`
flex: 1;
`;
var PromptName = styled2.div`
font-weight: 500;
color: #fff;
margin-bottom: 0.25rem;
`;
var PromptText = styled2.div`
font-size: 0.75rem;
color: #888;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
`;
var SelectionInfo = styled2.span`
color: #888;
font-size: 0.875rem;
`;
function ImageGenAssistant({
pipeline,
onClose,
onSubmit,
assistantBaseUrl = getServiceUrls2().imagegenAssistant
}) {
const [messages, setMessages] = useState([
{
role: "system",
content: `Pipeline: ${pipeline.name} | Model: ${pipeline.model} | Families: ${pipeline.families.join(", ")}`
}
]);
const [input, setInput] = useState("");
const [parsedPrompts, setParsedPrompts] = useState([]);
const [submitStatus, setSubmitStatus] = useState(null);
const chatRef = useRef(null);
const { generate, isGenerating } = usePipeline(pipeline.id, {
baseUrl: assistantBaseUrl
});
useEffect(() => {
if (chatRef.current) {
chatRef.current.scrollTop = chatRef.current.scrollHeight;
}
}, [messages]);
const sendMessage = useCallback(async (userMessage) => {
if (!userMessage.trim() || isGenerating) return;
const newUserMessage = { role: "user", content: userMessage };
setMessages((prev) => [...prev, newUserMessage]);
setInput("");
setSubmitStatus(null);
try {
const response = await generate(userMessage);
setMessages((prev) => [
...prev,
{ role: "assistant", content: response.rawResponse }
]);
if (response.prompts.length > 0) {
setParsedPrompts(
response.prompts.map((p) => ({
name: p.name,
prompt: p.prompt,
negativePrompt: p.negativePrompt,
selected: true
}))
);
}
} catch (error) {
setMessages((prev) => [
...prev,
{
role: "assistant",
content: `Error: ${error instanceof Error ? error.message : "Failed to get response"}`
}
]);
}
}, [generate, isGenerating]);
const togglePrompt = (index) => {
setParsedPrompts(
(prev) => prev.map((p, i) => i === index ? { ...p, selected: !p.selected } : p)
);
};
const handleSubmitToQueue = async () => {
const selectedPrompts = parsedPrompts.filter((p) => p.selected);
if (selectedPrompts.length === 0) return;
setSubmitStatus({ type: "info", message: "Submitting to queue..." });
try {
if (onSubmit) {
await onSubmit(selectedPrompts.map(({ selected, ...rest }) => rest));
}
setSubmitStatus({
type: "success",
message: `Successfully queued ${selectedPrompts.length} images!`
});
setParsedPrompts([]);
} catch (error) {
setSubmitStatus({
type: "error",
message: `Failed to submit: ${error instanceof Error ? error.message : "Unknown error"}`
});
}
};
const selectedCount = parsedPrompts.filter((p) => p.selected).length;
return /* @__PURE__ */ jsxs(Container, { children: [
/* @__PURE__ */ jsx(ExamplePrompts, { children: pipeline.examplePrompts.map((example, i) => /* @__PURE__ */ jsx(ExampleButton, { onClick: () => sendMessage(example), children: example }, i)) }),
/* @__PURE__ */ jsxs(ChatArea, { ref: chatRef, children: [
messages.map((msg, i) => /* @__PURE__ */ jsx(MessageBubble, { $role: msg.role, children: msg.content }, i)),
isGenerating && /* @__PURE__ */ jsx(MessageBubble, { $role: "assistant", children: "Thinking..." })
] }),
parsedPrompts.length > 0 && /* @__PURE__ */ jsx(PromptsPanel, { children: /* @__PURE__ */ jsx(Stack, { gap: "sm", children: parsedPrompts.map((prompt, i) => /* @__PURE__ */ jsxs(PromptItem, { children: [
/* @__PURE__ */ jsx(
Checkbox,
{
type: "checkbox",
checked: prompt.selected,
onChange: () => togglePrompt(i)
}
),
/* @__PURE__ */ jsxs(PromptDetails, { children: [
/* @__PURE__ */ jsx(PromptName, { children: prompt.name }),
/* @__PURE__ */ jsx(PromptText, { children: prompt.prompt })
] })
] }, i)) }) }),
submitStatus && /* @__PURE__ */ jsx(StatusMessage, { $type: submitStatus.type, children: submitStatus.message }),
/* @__PURE__ */ jsxs(ActionBar, { children: [
/* @__PURE__ */ jsxs(InputArea, { style: { flex: 1 }, children: [
/* @__PURE__ */ jsx(
TextInput,
{
type: "text",
placeholder: "Describe the images you want to generate...",
value: input,
onChange: (e) => setInput(e.target.value),
onKeyDown: (e) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
sendMessage(input);
}
},
disabled: isGenerating
}
),
/* @__PURE__ */ jsx(
PrimaryButton,
{
onClick: () => sendMessage(input),
disabled: isGenerating || !input.trim(),
children: "Send"
}
)
] }),
parsedPrompts.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsxs(SelectionInfo, { children: [
selectedCount,
" of ",
parsedPrompts.length,
" selected"
] }),
/* @__PURE__ */ jsxs(
PrimaryButton,
{
onClick: handleSubmitToQueue,
disabled: isGenerating || selectedCount === 0,
children: [
"Queue ",
selectedCount,
" Images"
]
}
)
] })
] })
] });
}
// src/PipelinesPage/index.tsx
import { useState as useState2 } from "react";
import { useQuery as useQuery2 } from "@tanstack/react-query";
import { Grid, Stack as Stack2 } from "@lilith/ui-layout";
import { Modal, Tabs } from "@lilith/ui-feedback";
import { Heading, Text } from "@lilith/ui-typography";
import { PIPELINES, getServiceUrls as getServiceUrls3 } from "@lilith/imajin-app";
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
function PipelineCardComponent({
pipeline,
onOpenAssistant,
onViewGallery,
fetchQueueStats
}) {
const { data: stats } = useQuery2({
queryKey: ["queue-stats", pipeline.category],
queryFn: () => fetchQueueStats?.(pipeline.category) ?? Promise.resolve(null),
refetchInterval: 1e4,
enabled: !!fetchQueueStats
});
return /* @__PURE__ */ jsxs2(Card, { children: [
/* @__PURE__ */ jsx2(CardTitle, { children: pipeline.name }),
/* @__PURE__ */ jsx2(CardDescription, { children: pipeline.description }),
/* @__PURE__ */ jsx2(StatsRow, { children: stats ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
/* @__PURE__ */ jsxs2(StatBadge, { $variant: "pending", children: [
stats.pending,
" pending"
] }),
/* @__PURE__ */ jsxs2(StatBadge, { $variant: "generating", children: [
stats.generating,
" generating"
] }),
/* @__PURE__ */ jsxs2(StatBadge, { $variant: "complete", children: [
stats.complete,
" complete"
] }),
stats.failed > 0 && /* @__PURE__ */ jsxs2(StatBadge, { $variant: "failed", children: [
stats.failed,
" failed"
] })
] }) : /* @__PURE__ */ jsx2(StatBadge, { children: "Loading..." }) }),
/* @__PURE__ */ jsxs2(ButtonRow, { children: [
/* @__PURE__ */ jsx2(PrimaryButton, { onClick: onOpenAssistant, children: "Open Assistant" }),
/* @__PURE__ */ jsx2(SecondaryButton, { onClick: onViewGallery, children: "View Gallery" })
] })
] });
}
function ImagePipelinesPage({
assistantBaseUrl = getServiceUrls3().imagegenAssistant,
pipelines = PIPELINES,
fetchQueueStats,
fetchGalleryImages,
submitPrompts
}) {
const [selectedPipeline, setSelectedPipeline] = useState2(null);
const [activeTab, setActiveTab] = useState2("pipelines");
const [galleryCategory, setGalleryCategory] = useState2(
pipelines[0]?.category ?? "skeleton"
);
const { data: galleryImages } = useQuery2({
queryKey: ["gallery-images", galleryCategory],
queryFn: () => fetchGalleryImages?.(galleryCategory) ?? Promise.resolve([]),
refetchInterval: 3e4,
enabled: !!fetchGalleryImages
});
const galleryItems = galleryImages ?? [];
const handleSubmitPrompts = async (prompts) => {
if (!selectedPipeline || !submitPrompts) return;
await submitPrompts(selectedPipeline, prompts);
};
return /* @__PURE__ */ jsxs2(Stack2, { gap: "lg", children: [
/* @__PURE__ */ jsxs2("div", { children: [
/* @__PURE__ */ jsx2(Heading, { as: "h1", size: "2xl", weight: "bold", marginBottom: "xs", children: "Image Generation Pipelines" }),
/* @__PURE__ */ jsx2(Text, { size: "sm", color: "muted", marginBottom: "xs", children: "Generate and manage images for UI components using AI-powered prompts" })
] }),
/* @__PURE__ */ jsx2(
Tabs,
{
tabs: [
{ key: "pipelines", label: "Pipelines" },
{ key: "gallery", label: "Gallery" }
],
activeTab,
onTabChange: (key) => setActiveTab(key)
}
),
activeTab === "pipelines" && /* @__PURE__ */ jsx2(Grid, { columns: 2, gap: "lg", responsive: { sm: 1, md: 2 }, children: pipelines.map((pipeline) => /* @__PURE__ */ jsx2(
PipelineCardComponent,
{
pipeline,
onOpenAssistant: () => setSelectedPipeline(pipeline),
onViewGallery: () => {
setGalleryCategory(pipeline.category);
setActiveTab("gallery");
},
fetchQueueStats
},
pipeline.id
)) }),
activeTab === "gallery" && /* @__PURE__ */ jsxs2("div", { children: [
/* @__PURE__ */ jsxs2(SectionTitle, { children: [
"Generated Images (",
galleryItems.length,
")"
] }),
galleryItems.length > 0 ? /* @__PURE__ */ jsx2(ImageGrid, { children: galleryItems.map((item, i) => /* @__PURE__ */ jsx2(ImageCard, { children: /* @__PURE__ */ jsx2("img", { src: item.src, alt: item.alt, loading: "lazy" }) }, i)) }) : /* @__PURE__ */ jsx2(CardDescription, { children: "No images generated yet. Use the Assistant to create prompts and generate images." })
] }),
selectedPipeline && /* @__PURE__ */ jsx2(
Modal,
{
isOpen: !!selectedPipeline,
onClose: () => setSelectedPipeline(null),
title: `ImageGen Assistant: ${selectedPipeline.name}`,
maxWidth: "900px",
maxHeight: "90vh",
children: /* @__PURE__ */ jsx2(
ImageGenAssistant,
{
pipeline: selectedPipeline,
assistantBaseUrl,
onClose: () => setSelectedPipeline(null),
onSubmit: handleSubmitPrompts
}
)
}
)
] });
}
// src/Gallery/index.tsx
import { useState as useState3 } from "react";
import { Modal as Modal2 } from "@lilith/ui-feedback";
import styled3 from "styled-components";
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
var LightboxImage = styled3.img`
max-width: 100%;
max-height: 80vh;
object-fit: contain;
border-radius: 8px;
`;
var LightboxTitle = styled3.h3`
color: #fff;
font-size: 1rem;
font-weight: 500;
margin-top: 1rem;
text-align: center;
`;
var GalleryGrid = styled3(ImageGrid)`
grid-template-columns: repeat(${({ $columns }) => $columns}, 1fr);
@media (max-width: 1200px) {
grid-template-columns: repeat(${({ $columns }) => Math.min($columns, 3)}, 1fr);
}
@media (max-width: 900px) {
grid-template-columns: repeat(2, 1fr);
}
`;
function Gallery({
images,
title,
lightbox = true,
columns = 4,
emptyMessage = "No images to display"
}) {
const [selectedImage, setSelectedImage] = useState3(null);
const handleImageClick = (image) => {
if (lightbox) {
setSelectedImage(image);
}
};
if (images.length === 0) {
return /* @__PURE__ */ jsxs3("div", { children: [
title && /* @__PURE__ */ jsx3(SectionTitle, { children: title }),
/* @__PURE__ */ jsx3(CardDescription, { children: emptyMessage })
] });
}
return /* @__PURE__ */ jsxs3("div", { children: [
title && /* @__PURE__ */ jsxs3(SectionTitle, { children: [
title,
" (",
images.length,
")"
] }),
/* @__PURE__ */ jsx3(GalleryGrid, { $columns: columns, children: images.map((image, i) => /* @__PURE__ */ jsx3(
ImageCard,
{
onClick: () => handleImageClick(image),
role: lightbox ? "button" : void 0,
tabIndex: lightbox ? 0 : void 0,
onKeyDown: (e) => {
if (lightbox && (e.key === "Enter" || e.key === " ")) {
e.preventDefault();
handleImageClick(image);
}
},
children: /* @__PURE__ */ jsx3(
"img",
{
src: image.thumbnail ?? image.src,
alt: image.alt,
loading: "lazy"
}
)
},
i
)) }),
lightbox && selectedImage && /* @__PURE__ */ jsxs3(
Modal2,
{
title: selectedImage.title || "Image Preview",
isOpen: !!selectedImage,
onClose: () => setSelectedImage(null),
maxWidth: "90vw",
maxHeight: "95vh",
children: [
/* @__PURE__ */ jsx3(LightboxImage, { src: selectedImage.src, alt: selectedImage.alt }),
selectedImage.title && /* @__PURE__ */ jsx3(LightboxTitle, { children: selectedImage.title })
]
}
)
] });
}
// src/index.ts
import { PIPELINES as PIPELINES2, getPipelineById } from "@lilith/imajin-app";
export {
Gallery,
ImageGenAssistant,
ImagePipelinesPage,
PIPELINES2 as PIPELINES,
getPipelineById,
useImagegenAssistant,
usePipeline
};
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View file

@ -1,298 +0,0 @@
// src/styles/index.ts
import styled from "styled-components";
var Container = styled.div`
display: flex;
flex-direction: column;
height: 70vh;
gap: 1rem;
`;
var Panel = styled.div`
background: rgba(0, 0, 0, 0.3);
border-radius: 8px;
padding: 1rem;
`;
var Card = styled.div`
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 12px;
padding: 1.5rem;
transition: all 0.2s;
&:hover {
border-color: rgba(255, 107, 180, 0.3);
box-shadow: 0 0 20px rgba(255, 107, 180, 0.1);
}
`;
var CardTitle = styled.h3`
font-size: 1.25rem;
font-weight: 600;
color: #fff;
margin-bottom: 0.5rem;
`;
var CardDescription = styled.p`
color: #888;
font-size: 0.875rem;
margin-bottom: 1rem;
`;
var ChatArea = styled.div`
flex: 1;
overflow-y: auto;
background: rgba(0, 0, 0, 0.3);
border-radius: 8px;
padding: 1rem;
`;
var MessageBubble = styled.div`
max-width: 85%;
padding: 0.75rem 1rem;
margin-bottom: 0.75rem;
border-radius: 12px;
font-size: 0.875rem;
line-height: 1.5;
white-space: pre-wrap;
${({ $role }) => {
switch ($role) {
case "user":
return `
margin-left: auto;
background: linear-gradient(135deg, #ff69b4, #9b59b6);
color: #fff;
`;
case "assistant":
return `
background: rgba(255, 255, 255, 0.1);
color: #fff;
`;
case "system":
return `
background: rgba(100, 116, 139, 0.2);
color: #94a3b8;
font-size: 0.75rem;
text-align: center;
max-width: 100%;
`;
}
}}
`;
var InputArea = styled.div`
display: flex;
gap: 0.5rem;
`;
var TextInput = styled.input`
flex: 1;
padding: 0.75rem 1rem;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.2);
background: rgba(0, 0, 0, 0.3);
color: #fff;
font-size: 0.875rem;
&::placeholder {
color: #666;
}
&:focus {
outline: none;
border-color: #ff69b4;
}
`;
var PrimaryButton = styled.button`
padding: 0.75rem 1.5rem;
border-radius: 8px;
border: none;
background: linear-gradient(135deg, #ff69b4, #9b59b6);
color: #fff;
font-weight: 500;
cursor: pointer;
transition: opacity 0.2s;
&:hover:not(:disabled) {
opacity: 0.9;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
`;
var SecondaryButton = styled.button`
padding: 0.5rem 1rem;
border-radius: 8px;
border: none;
background: rgba(255, 255, 255, 0.1);
color: #fff;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
&:hover {
background: rgba(255, 255, 255, 0.15);
}
`;
var ExampleButton = styled.button`
padding: 0.25rem 0.75rem;
border-radius: 9999px;
border: 1px solid rgba(255, 255, 255, 0.2);
background: transparent;
color: #888;
font-size: 0.75rem;
cursor: pointer;
transition: all 0.2s;
&:hover {
border-color: #ff69b4;
color: #ff69b4;
}
`;
var StatBadge = styled.span`
padding: 0.25rem 0.75rem;
border-radius: 9999px;
font-size: 0.75rem;
font-weight: 500;
background: ${({ $variant }) => {
switch ($variant) {
case "pending":
return "rgba(100, 116, 139, 0.2)";
case "generating":
return "rgba(234, 179, 8, 0.2)";
case "complete":
return "rgba(34, 197, 94, 0.2)";
case "failed":
return "rgba(239, 68, 68, 0.2)";
default:
return "rgba(100, 116, 139, 0.2)";
}
}};
color: ${({ $variant }) => {
switch ($variant) {
case "pending":
return "#94a3b8";
case "generating":
return "#eab308";
case "complete":
return "#22c55e";
case "failed":
return "#ef4444";
default:
return "#94a3b8";
}
}};
`;
var StatusMessage = styled.div`
padding: 0.5rem 1rem;
border-radius: 8px;
font-size: 0.875rem;
margin-top: 0.5rem;
${({ $type }) => {
switch ($type) {
case "success":
return `
background: rgba(34, 197, 94, 0.2);
color: #22c55e;
`;
case "error":
return `
background: rgba(239, 68, 68, 0.2);
color: #ef4444;
`;
case "info":
return `
background: rgba(59, 130, 246, 0.2);
color: #3b82f6;
`;
}
}}
`;
var ImageGrid = styled.div`
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
@media (max-width: 1200px) {
grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 900px) {
grid-template-columns: repeat(2, 1fr);
}
`;
var ImageCard = styled.div`
aspect-ratio: 1;
overflow: hidden;
border-radius: 8px;
cursor: pointer;
transition: transform 0.2s;
&:hover {
transform: scale(1.02);
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
`;
var SectionTitle = styled.h2`
font-size: 1.5rem;
font-weight: 600;
color: #fff;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.75rem;
&::after {
content: '';
flex: 1;
height: 1px;
background: linear-gradient(90deg, rgba(255, 255, 255, 0.2), transparent);
}
`;
var ActionBar = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
`;
var ButtonRow = styled.div`
display: flex;
gap: 0.5rem;
margin-top: 1rem;
`;
var StatsRow = styled.div`
display: flex;
gap: 1rem;
margin-bottom: 1rem;
`;
var ExamplePrompts = styled.div`
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
margin-bottom: 0.5rem;
`;
export {
ActionBar,
ButtonRow,
Card,
CardDescription,
CardTitle,
ChatArea,
Container,
ExampleButton,
ExamplePrompts,
ImageCard,
ImageGrid,
InputArea,
MessageBubble,
Panel,
PrimaryButton,
SecondaryButton,
SectionTitle,
StatBadge,
StatsRow,
StatusMessage,
TextInput
};
//# sourceMappingURL=styles.js.map

File diff suppressed because one or more lines are too long