@umituz/react-native-ai-generation-content 1.27.7 → 1.27.9
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/package.json +1 -1
- package/src/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts +3 -30
- package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts +3 -30
- package/src/domains/generation/wizard/infrastructure/strategies/wizard-strategy.constants.ts +0 -2
- package/src/domains/scenarios/configs/wizard-configs.ts +28 -28
- package/src/domains/scenarios/index.ts +3 -3
- package/src/features/image-to-video/README.md +414 -0
- package/src/features/image-to-video/domain/constants/animation.constants.ts +47 -0
- package/src/features/image-to-video/domain/constants/duration.constants.ts +13 -0
- package/src/features/image-to-video/domain/constants/form.constants.ts +22 -0
- package/src/features/image-to-video/domain/constants/index.ts +23 -0
- package/src/features/image-to-video/domain/constants/music.constants.ts +53 -0
- package/src/features/image-to-video/domain/index.ts +5 -0
- package/src/features/image-to-video/domain/types/animation.types.ts +20 -0
- package/src/features/image-to-video/domain/types/config.types.ts +56 -0
- package/src/features/image-to-video/domain/types/duration.types.ts +11 -0
- package/src/features/image-to-video/domain/types/form.types.ts +35 -0
- package/src/features/image-to-video/domain/types/image-to-video.types.ts +122 -0
- package/src/features/image-to-video/domain/types/index.ts +39 -0
- package/src/features/image-to-video/domain/types/music.types.ts +21 -0
- package/src/features/image-to-video/index.ts +116 -0
- package/src/features/image-to-video/infrastructure/index.ts +1 -0
- package/src/features/image-to-video/infrastructure/services/image-to-video-executor.ts +165 -0
- package/src/features/image-to-video/infrastructure/services/index.ts +5 -0
- package/src/features/image-to-video/presentation/components/AddMoreCard.tsx +52 -0
- package/src/features/image-to-video/presentation/components/AnimationStyleSelector.tsx +135 -0
- package/src/features/image-to-video/presentation/components/DurationSelector.tsx +110 -0
- package/src/features/image-to-video/presentation/components/EmptyGridState.tsx +69 -0
- package/src/features/image-to-video/presentation/components/GridImageItem.tsx +64 -0
- package/src/features/image-to-video/presentation/components/ImageSelectionGrid.styles.ts +84 -0
- package/src/features/image-to-video/presentation/components/ImageSelectionGrid.tsx +77 -0
- package/src/features/image-to-video/presentation/components/ImageSelectionGrid.types.ts +18 -0
- package/src/features/image-to-video/presentation/components/MusicMoodSelector.tsx +181 -0
- package/src/features/image-to-video/presentation/components/index.ts +30 -0
- package/src/features/image-to-video/presentation/hooks/index.ts +27 -0
- package/src/features/image-to-video/presentation/hooks/useFormState.ts +116 -0
- package/src/features/image-to-video/presentation/hooks/useGeneration.ts +85 -0
- package/src/features/image-to-video/presentation/hooks/useGenerationExecution.ts +143 -0
- package/src/features/image-to-video/presentation/hooks/useImageToVideoFeature.ts +107 -0
- package/src/features/image-to-video/presentation/hooks/useImageToVideoForm.ts +119 -0
- package/src/features/image-to-video/presentation/hooks/useImageToVideoValidation.ts +46 -0
- package/src/features/image-to-video/presentation/index.ts +5 -0
- package/src/features/text-to-image/README.md +394 -0
- package/src/features/text-to-image/domain/constants/index.ts +25 -0
- package/src/features/text-to-image/domain/constants/options.constants.ts +39 -0
- package/src/features/text-to-image/domain/constants/styles.constants.ts +34 -0
- package/src/features/text-to-image/domain/index.ts +7 -0
- package/src/features/text-to-image/domain/types/config.types.ts +75 -0
- package/src/features/text-to-image/domain/types/form.types.ts +58 -0
- package/src/features/text-to-image/domain/types/index.ts +38 -0
- package/src/features/text-to-image/domain/types/text-to-image.types.ts +58 -0
- package/src/features/text-to-image/index.ts +116 -0
- package/src/features/text-to-image/infrastructure/index.ts +1 -0
- package/src/features/text-to-image/infrastructure/services/index.ts +5 -0
- package/src/features/text-to-image/infrastructure/services/text-to-image-executor.ts +147 -0
- package/src/features/text-to-image/presentation/components/index.ts +30 -0
- package/src/features/text-to-image/presentation/hooks/index.ts +30 -0
- package/src/features/text-to-image/presentation/hooks/useFormState.ts +103 -0
- package/src/features/text-to-image/presentation/hooks/useGeneration.ts +134 -0
- package/src/features/text-to-image/presentation/hooks/useTextToImageFeature.ts +111 -0
- package/src/features/text-to-image/presentation/hooks/useTextToImageForm.ts +58 -0
- package/src/features/text-to-image/presentation/index.ts +7 -0
- package/src/features/text-to-video/README.md +412 -0
- package/src/features/text-to-video/domain/index.ts +1 -0
- package/src/features/text-to-video/domain/types/callback.types.ts +69 -0
- package/src/features/text-to-video/domain/types/component.types.ts +106 -0
- package/src/features/text-to-video/domain/types/config.types.ts +61 -0
- package/src/features/text-to-video/domain/types/index.ts +56 -0
- package/src/features/text-to-video/domain/types/request.types.ts +36 -0
- package/src/features/text-to-video/domain/types/state.types.ts +53 -0
- package/src/features/text-to-video/index.ts +68 -0
- package/src/features/text-to-video/infrastructure/index.ts +1 -0
- package/src/features/text-to-video/infrastructure/services/index.ts +5 -0
- package/src/features/text-to-video/infrastructure/services/text-to-video-executor.ts +141 -0
- package/src/features/text-to-video/presentation/components/FrameSelector.tsx +153 -0
- package/src/features/text-to-video/presentation/components/GenerationTabs.tsx +73 -0
- package/src/features/text-to-video/presentation/components/HeroSection.tsx +61 -0
- package/src/features/text-to-video/presentation/components/HintCarousel.tsx +96 -0
- package/src/features/text-to-video/presentation/components/OptionsPanel.tsx +121 -0
- package/src/features/text-to-video/presentation/components/index.ts +10 -0
- package/src/features/text-to-video/presentation/hooks/index.ts +17 -0
- package/src/features/text-to-video/presentation/hooks/useTextToVideoFeature.ts +187 -0
- package/src/features/text-to-video/presentation/hooks/useTextToVideoForm.ts +134 -0
- package/src/features/text-to-video/presentation/index.ts +7 -0
- package/src/index.ts +5 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Image Form State Hook
|
|
3
|
+
* Manages form state for text-to-image generation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useState, useCallback, useMemo } from "react";
|
|
7
|
+
import type {
|
|
8
|
+
AspectRatio,
|
|
9
|
+
ImageSize,
|
|
10
|
+
NumImages,
|
|
11
|
+
OutputFormat,
|
|
12
|
+
TextToImageFormState,
|
|
13
|
+
TextToImageFormActions,
|
|
14
|
+
TextToImageFormDefaults,
|
|
15
|
+
} from "../../domain/types/form.types";
|
|
16
|
+
import { DEFAULT_FORM_VALUES } from "../../domain/constants/options.constants";
|
|
17
|
+
|
|
18
|
+
export interface UseFormStateOptions {
|
|
19
|
+
defaults?: TextToImageFormDefaults;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface UseFormStateReturn {
|
|
23
|
+
state: TextToImageFormState;
|
|
24
|
+
actions: TextToImageFormActions;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function useFormState(options?: UseFormStateOptions): UseFormStateReturn {
|
|
28
|
+
const defaults = useMemo(
|
|
29
|
+
() => ({ ...DEFAULT_FORM_VALUES, ...options?.defaults }),
|
|
30
|
+
[options?.defaults]
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const [prompt, setPrompt] = useState("");
|
|
34
|
+
const [aspectRatio, setAspectRatio] = useState<AspectRatio>(
|
|
35
|
+
defaults.aspectRatio ?? "9:16"
|
|
36
|
+
);
|
|
37
|
+
const [size, setSize] = useState<ImageSize>(defaults.size ?? "512x512");
|
|
38
|
+
const [numImages, setNumImages] = useState<NumImages>(defaults.numImages ?? 1);
|
|
39
|
+
const [negativePrompt, setNegativePrompt] = useState("");
|
|
40
|
+
const [guidanceScale, setGuidanceScale] = useState(defaults.guidanceScale ?? 7.5);
|
|
41
|
+
const [selectedModel, setSelectedModel] = useState<string | null>(null);
|
|
42
|
+
const [outputFormat, setOutputFormat] = useState<OutputFormat>(
|
|
43
|
+
defaults.outputFormat ?? "png"
|
|
44
|
+
);
|
|
45
|
+
const [selectedStyle, setSelectedStyle] = useState(
|
|
46
|
+
defaults.selectedStyle ?? "realistic"
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const reset = useCallback(() => {
|
|
50
|
+
setPrompt("");
|
|
51
|
+
setAspectRatio(defaults.aspectRatio ?? "9:16");
|
|
52
|
+
setSize(defaults.size ?? "512x512");
|
|
53
|
+
setNumImages(defaults.numImages ?? 1);
|
|
54
|
+
setNegativePrompt("");
|
|
55
|
+
setGuidanceScale(defaults.guidanceScale ?? 7.5);
|
|
56
|
+
setSelectedModel(null);
|
|
57
|
+
setOutputFormat(defaults.outputFormat ?? "png");
|
|
58
|
+
setSelectedStyle(defaults.selectedStyle ?? "realistic");
|
|
59
|
+
}, [defaults]);
|
|
60
|
+
|
|
61
|
+
const state: TextToImageFormState = useMemo(
|
|
62
|
+
() => ({
|
|
63
|
+
prompt,
|
|
64
|
+
aspectRatio,
|
|
65
|
+
size,
|
|
66
|
+
numImages,
|
|
67
|
+
negativePrompt,
|
|
68
|
+
guidanceScale,
|
|
69
|
+
selectedModel,
|
|
70
|
+
outputFormat,
|
|
71
|
+
selectedStyle,
|
|
72
|
+
}),
|
|
73
|
+
[
|
|
74
|
+
prompt,
|
|
75
|
+
aspectRatio,
|
|
76
|
+
size,
|
|
77
|
+
numImages,
|
|
78
|
+
negativePrompt,
|
|
79
|
+
guidanceScale,
|
|
80
|
+
selectedModel,
|
|
81
|
+
outputFormat,
|
|
82
|
+
selectedStyle,
|
|
83
|
+
]
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const actions: TextToImageFormActions = useMemo(
|
|
87
|
+
() => ({
|
|
88
|
+
setPrompt,
|
|
89
|
+
setAspectRatio,
|
|
90
|
+
setSize,
|
|
91
|
+
setNumImages,
|
|
92
|
+
setNegativePrompt,
|
|
93
|
+
setGuidanceScale,
|
|
94
|
+
setSelectedModel,
|
|
95
|
+
setOutputFormat,
|
|
96
|
+
setSelectedStyle,
|
|
97
|
+
reset,
|
|
98
|
+
}),
|
|
99
|
+
[reset]
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
return { state, actions };
|
|
103
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Image Generation Hook
|
|
3
|
+
* Uses centralized orchestrator for auth, credits, and error handling
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useCallback, useMemo } from "react";
|
|
7
|
+
import {
|
|
8
|
+
useGenerationOrchestrator,
|
|
9
|
+
type GenerationStrategy,
|
|
10
|
+
type AlertMessages,
|
|
11
|
+
} from "../../../../presentation/hooks/generation";
|
|
12
|
+
import type {
|
|
13
|
+
TextToImageFormState,
|
|
14
|
+
TextToImageCallbacks,
|
|
15
|
+
TextToImageGenerationResult,
|
|
16
|
+
TextToImageGenerationRequest,
|
|
17
|
+
} from "../../domain/types";
|
|
18
|
+
|
|
19
|
+
declare const __DEV__: boolean;
|
|
20
|
+
|
|
21
|
+
export interface UseGenerationOptions {
|
|
22
|
+
formState: TextToImageFormState;
|
|
23
|
+
callbacks: TextToImageCallbacks;
|
|
24
|
+
userId?: string;
|
|
25
|
+
onPromptCleared?: () => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface TextToImageGenerationState {
|
|
29
|
+
isGenerating: boolean;
|
|
30
|
+
progress: number;
|
|
31
|
+
error: string | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface UseGenerationReturn {
|
|
35
|
+
generationState: TextToImageGenerationState;
|
|
36
|
+
totalCost: number;
|
|
37
|
+
handleGenerate: () => Promise<TextToImageGenerationResult | null>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const DEFAULT_ALERT_MESSAGES: AlertMessages = {
|
|
41
|
+
networkError: "No internet connection. Please check your network.",
|
|
42
|
+
policyViolation: "Content not allowed. Please try again.",
|
|
43
|
+
saveFailed: "Failed to save. Please try again.",
|
|
44
|
+
creditFailed: "Credit operation failed. Please try again.",
|
|
45
|
+
unknown: "An error occurred. Please try again.",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export function useGeneration(options: UseGenerationOptions): UseGenerationReturn {
|
|
49
|
+
const { formState, callbacks, userId, onPromptCleared } = options;
|
|
50
|
+
|
|
51
|
+
const totalCost = callbacks.calculateCost(formState.numImages, formState.selectedModel);
|
|
52
|
+
|
|
53
|
+
// Build strategy for orchestrator
|
|
54
|
+
const strategy: GenerationStrategy<TextToImageGenerationRequest, string[]> = useMemo(
|
|
55
|
+
() => ({
|
|
56
|
+
execute: async (request) => {
|
|
57
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
58
|
+
console.log("[TextToImage] Executing generation:", JSON.stringify(request, null, 2));
|
|
59
|
+
}
|
|
60
|
+
const result = await callbacks.executeGeneration(request);
|
|
61
|
+
if (result.success === false) {
|
|
62
|
+
throw new Error(result.error);
|
|
63
|
+
}
|
|
64
|
+
return result.imageUrls;
|
|
65
|
+
},
|
|
66
|
+
getCreditCost: () => totalCost,
|
|
67
|
+
}),
|
|
68
|
+
[callbacks, totalCost],
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// Use orchestrator
|
|
72
|
+
const { generate, isGenerating, progress, error } = useGenerationOrchestrator(strategy, {
|
|
73
|
+
userId,
|
|
74
|
+
alertMessages: DEFAULT_ALERT_MESSAGES,
|
|
75
|
+
onCreditsExhausted: () => callbacks.onCreditsRequired?.(totalCost),
|
|
76
|
+
onSuccess: (result) => {
|
|
77
|
+
const imageUrls = result as string[];
|
|
78
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
79
|
+
console.log("[TextToImage] Success! Generated", imageUrls.length, "image(s)");
|
|
80
|
+
}
|
|
81
|
+
callbacks.onSuccess?.(imageUrls);
|
|
82
|
+
onPromptCleared?.();
|
|
83
|
+
},
|
|
84
|
+
onError: (err) => {
|
|
85
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
86
|
+
console.log("[TextToImage] Error:", err.message);
|
|
87
|
+
}
|
|
88
|
+
callbacks.onError?.(err.message);
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const handleGenerate = useCallback(async (): Promise<TextToImageGenerationResult | null> => {
|
|
93
|
+
const trimmedPrompt = formState.prompt.trim();
|
|
94
|
+
|
|
95
|
+
if (!trimmedPrompt) {
|
|
96
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
97
|
+
console.log("[TextToImage] No prompt provided");
|
|
98
|
+
}
|
|
99
|
+
callbacks.onError?.("Prompt is required");
|
|
100
|
+
return { success: false, error: "Prompt is required" };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const request: TextToImageGenerationRequest = {
|
|
104
|
+
prompt: trimmedPrompt,
|
|
105
|
+
model: formState.selectedModel ?? undefined,
|
|
106
|
+
aspectRatio: formState.aspectRatio,
|
|
107
|
+
size: formState.size,
|
|
108
|
+
negativePrompt: formState.negativePrompt.trim() || undefined,
|
|
109
|
+
guidanceScale: formState.guidanceScale,
|
|
110
|
+
numImages: formState.numImages,
|
|
111
|
+
style: formState.selectedStyle,
|
|
112
|
+
outputFormat: formState.outputFormat,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
if (typeof __DEV__ !== "undefined" && __DEV__) {
|
|
116
|
+
console.log("[TextToImage] Starting generation...");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
await generate(request);
|
|
120
|
+
|
|
121
|
+
// Return result based on orchestrator state
|
|
122
|
+
return null; // Result handled via callbacks
|
|
123
|
+
}, [formState, generate, callbacks]);
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
generationState: {
|
|
127
|
+
isGenerating,
|
|
128
|
+
progress,
|
|
129
|
+
error: error?.message || null,
|
|
130
|
+
},
|
|
131
|
+
totalCost,
|
|
132
|
+
handleGenerate,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Image Feature Hook
|
|
3
|
+
* Provider-agnostic hook for text-to-image generation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useState, useCallback } from "react";
|
|
7
|
+
import { executeTextToImage } from "../../infrastructure/services";
|
|
8
|
+
import type {
|
|
9
|
+
TextToImageFeatureState,
|
|
10
|
+
TextToImageFeatureConfig,
|
|
11
|
+
TextToImageResult,
|
|
12
|
+
TextToImageOptions,
|
|
13
|
+
} from "../../domain/types";
|
|
14
|
+
|
|
15
|
+
export interface UseTextToImageFeatureProps {
|
|
16
|
+
config: TextToImageFeatureConfig;
|
|
17
|
+
userId: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface UseTextToImageFeatureReturn {
|
|
21
|
+
state: TextToImageFeatureState;
|
|
22
|
+
setPrompt: (prompt: string) => void;
|
|
23
|
+
generate: (options?: TextToImageOptions) => Promise<TextToImageResult>;
|
|
24
|
+
reset: () => void;
|
|
25
|
+
isReady: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const initialState: TextToImageFeatureState = {
|
|
29
|
+
prompt: "",
|
|
30
|
+
imageUrl: null,
|
|
31
|
+
imageUrls: [],
|
|
32
|
+
isProcessing: false,
|
|
33
|
+
progress: 0,
|
|
34
|
+
error: null,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export function useTextToImageFeature(
|
|
38
|
+
props: UseTextToImageFeatureProps,
|
|
39
|
+
): UseTextToImageFeatureReturn {
|
|
40
|
+
const { config, userId } = props;
|
|
41
|
+
const [state, setState] = useState<TextToImageFeatureState>(initialState);
|
|
42
|
+
|
|
43
|
+
const setPrompt = useCallback(
|
|
44
|
+
(prompt: string) => {
|
|
45
|
+
setState((prev) => ({ ...prev, prompt, error: null }));
|
|
46
|
+
config.onPromptChange?.(prompt);
|
|
47
|
+
},
|
|
48
|
+
[config],
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const generate = useCallback(
|
|
52
|
+
async (options?: TextToImageOptions): Promise<TextToImageResult> => {
|
|
53
|
+
if (!state.prompt) {
|
|
54
|
+
const error = "Prompt is required";
|
|
55
|
+
setState((prev) => ({ ...prev, error }));
|
|
56
|
+
return { success: false, error };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setState((prev) => ({
|
|
60
|
+
...prev,
|
|
61
|
+
isProcessing: true,
|
|
62
|
+
progress: 0,
|
|
63
|
+
error: null,
|
|
64
|
+
}));
|
|
65
|
+
|
|
66
|
+
config.onProcessingStart?.();
|
|
67
|
+
|
|
68
|
+
const result = await executeTextToImage(
|
|
69
|
+
{ prompt: state.prompt, userId, options },
|
|
70
|
+
{
|
|
71
|
+
model: config.model,
|
|
72
|
+
buildInput: config.buildInput,
|
|
73
|
+
extractResult: config.extractResult,
|
|
74
|
+
onProgress: (progress) => {
|
|
75
|
+
setState((prev) => ({ ...prev, progress }));
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
if (result.success && result.imageUrl) {
|
|
81
|
+
setState((prev) => ({
|
|
82
|
+
...prev,
|
|
83
|
+
imageUrl: result.imageUrl ?? null,
|
|
84
|
+
imageUrls: result.imageUrls ?? [],
|
|
85
|
+
isProcessing: false,
|
|
86
|
+
progress: 100,
|
|
87
|
+
}));
|
|
88
|
+
} else {
|
|
89
|
+
const error = result.error || "Generation failed";
|
|
90
|
+
setState((prev) => ({
|
|
91
|
+
...prev,
|
|
92
|
+
isProcessing: false,
|
|
93
|
+
error,
|
|
94
|
+
}));
|
|
95
|
+
config.onError?.(error);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
config.onProcessingComplete?.(result);
|
|
99
|
+
return result;
|
|
100
|
+
},
|
|
101
|
+
[state.prompt, userId, config],
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const reset = useCallback(() => {
|
|
105
|
+
setState(initialState);
|
|
106
|
+
}, []);
|
|
107
|
+
|
|
108
|
+
const isReady = state.prompt.length > 0 && !state.isProcessing;
|
|
109
|
+
|
|
110
|
+
return { state, setPrompt, generate, reset, isReady };
|
|
111
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Image Form Hook
|
|
3
|
+
* Composes form state and generation for complete form management
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useMemo } from "react";
|
|
7
|
+
import { useFormState, type UseFormStateOptions } from "./useFormState";
|
|
8
|
+
import { useGeneration, type TextToImageGenerationState } from "./useGeneration";
|
|
9
|
+
import type {
|
|
10
|
+
TextToImageFormState,
|
|
11
|
+
TextToImageFormActions,
|
|
12
|
+
TextToImageCallbacks,
|
|
13
|
+
} from "../../domain/types";
|
|
14
|
+
|
|
15
|
+
export interface UseTextToImageFormOptions extends UseFormStateOptions {
|
|
16
|
+
callbacks: TextToImageCallbacks;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface UseTextToImageFormReturn {
|
|
20
|
+
state: TextToImageFormState;
|
|
21
|
+
actions: TextToImageFormActions;
|
|
22
|
+
generationState: TextToImageGenerationState;
|
|
23
|
+
totalCost: number;
|
|
24
|
+
handleGenerate: () => Promise<void>;
|
|
25
|
+
isReady: boolean;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function useTextToImageForm(
|
|
29
|
+
options: UseTextToImageFormOptions
|
|
30
|
+
): UseTextToImageFormReturn {
|
|
31
|
+
const { callbacks, defaults } = options;
|
|
32
|
+
|
|
33
|
+
const { state, actions } = useFormState({ defaults });
|
|
34
|
+
|
|
35
|
+
const { generationState, totalCost, handleGenerate } = useGeneration({
|
|
36
|
+
formState: state,
|
|
37
|
+
callbacks,
|
|
38
|
+
onPromptCleared: actions.reset,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const isReady = useMemo(
|
|
42
|
+
() => state.prompt.trim().length > 0 && !generationState.isGenerating,
|
|
43
|
+
[state.prompt, generationState.isGenerating]
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const wrappedHandleGenerate = async () => {
|
|
47
|
+
await handleGenerate();
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
state,
|
|
52
|
+
actions,
|
|
53
|
+
generationState,
|
|
54
|
+
totalCost,
|
|
55
|
+
handleGenerate: wrappedHandleGenerate,
|
|
56
|
+
isReady,
|
|
57
|
+
};
|
|
58
|
+
}
|