@umituz/react-native-ai-generation-content 1.17.144 → 1.17.146

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.
Files changed (29) hide show
  1. package/package.json +1 -1
  2. package/src/features/photo-restoration/presentation/components/PhotoRestoreResultView.tsx +1 -1
  3. package/src/features/replace-background/index.ts +5 -50
  4. package/src/features/replace-background/presentation/components/index.ts +0 -12
  5. package/src/features/replace-background/presentation/hooks/index.ts +0 -3
  6. package/src/infrastructure/utils/index.ts +1 -0
  7. package/src/infrastructure/utils/result-validator.util.ts +0 -214
  8. package/src/infrastructure/utils/url-extractor.util.ts +209 -0
  9. package/src/presentation/hooks/flow-state.utils.ts +101 -0
  10. package/src/presentation/hooks/useGenerationFlow.ts +47 -178
  11. package/src/presentation/types/flow-config.types.ts +5 -99
  12. package/src/presentation/types/flow-default-configs.ts +106 -0
  13. package/src/features/replace-background/domain/entities/background.types.ts +0 -77
  14. package/src/features/replace-background/domain/entities/component.types.ts +0 -87
  15. package/src/features/replace-background/domain/entities/config.types.ts +0 -41
  16. package/src/features/replace-background/domain/entities/index.ts +0 -30
  17. package/src/features/replace-background/infrastructure/constants/index.ts +0 -5
  18. package/src/features/replace-background/infrastructure/constants/prompts.constants.ts +0 -15
  19. package/src/features/replace-background/infrastructure/index.ts +0 -5
  20. package/src/features/replace-background/presentation/components/BackgroundFeature.tsx +0 -143
  21. package/src/features/replace-background/presentation/components/ComparisonSlider.tsx +0 -187
  22. package/src/features/replace-background/presentation/components/ErrorDisplay.tsx +0 -60
  23. package/src/features/replace-background/presentation/components/FeatureHeader.tsx +0 -80
  24. package/src/features/replace-background/presentation/components/GenerateButton.tsx +0 -85
  25. package/src/features/replace-background/presentation/components/ImagePicker.tsx +0 -136
  26. package/src/features/replace-background/presentation/components/ModeSelector.tsx +0 -78
  27. package/src/features/replace-background/presentation/components/PromptInput.tsx +0 -142
  28. package/src/features/replace-background/presentation/components/ResultDisplay.tsx +0 -122
  29. package/src/features/replace-background/presentation/hooks/useBackgroundFeature.ts +0 -119
@@ -1,136 +0,0 @@
1
- /**
2
- * Image Picker Component
3
- * @description Image selection component with placeholder state
4
- */
5
-
6
- import React, { memo } from "react";
7
- import { View, StyleSheet, TouchableOpacity, Image } from "react-native";
8
- import {
9
- AtomicText,
10
- AtomicIcon,
11
- useAppDesignTokens,
12
- } from "@umituz/react-native-design-system";
13
- import type { ImagePickerProps } from "../../domain/entities";
14
-
15
- export const ImagePicker: React.FC<ImagePickerProps> = memo(
16
- function ImagePicker({
17
- imageUri,
18
- isProcessing,
19
- onSelectImage,
20
- placeholderText,
21
- }) {
22
- const tokens = useAppDesignTokens();
23
-
24
- return (
25
- <View style={styles.container}>
26
- <TouchableOpacity
27
- style={[
28
- styles.imagePickerBox,
29
- { backgroundColor: tokens.colors.surface },
30
- ]}
31
- onPress={onSelectImage}
32
- disabled={isProcessing}
33
- activeOpacity={0.8}
34
- >
35
- {imageUri ? (
36
- <View style={styles.imageContainer}>
37
- <Image source={{ uri: imageUri }} style={styles.image} />
38
- <View style={styles.imageOverlay}>
39
- <View
40
- style={[
41
- styles.editBadge,
42
- { backgroundColor: tokens.colors.primary },
43
- ]}
44
- >
45
- <AtomicIcon
46
- name="image-plus"
47
- size="md"
48
-
49
- />
50
- </View>
51
- </View>
52
- </View>
53
- ) : (
54
- <View
55
- style={[
56
- styles.placeholderContainer,
57
- { backgroundColor: tokens.colors.surface },
58
- ]}
59
- >
60
- <View
61
- style={[
62
- styles.uploadIconContainer,
63
- { backgroundColor: tokens.colors.surfaceSecondary },
64
- ]}
65
- >
66
- <AtomicIcon
67
- name="upload"
68
- size="lg"
69
-
70
- />
71
- </View>
72
- <AtomicText
73
-
74
- style={[
75
- styles.placeholderText,
76
- { color: tokens.colors.primary },
77
- ]}
78
- >
79
- {placeholderText}
80
- </AtomicText>
81
- </View>
82
- )}
83
- </TouchableOpacity>
84
- </View>
85
- );
86
- }
87
- );
88
-
89
- const styles = StyleSheet.create({
90
- container: {
91
- marginVertical: 16,
92
- alignItems: "center",
93
- },
94
- imagePickerBox: {
95
- width: "100%",
96
- aspectRatio: 1,
97
- borderRadius: 20,
98
- overflow: "hidden",
99
- },
100
- imageContainer: {
101
- flex: 1,
102
- position: "relative",
103
- },
104
- image: {
105
- width: "100%",
106
- height: "100%",
107
- },
108
- imageOverlay: {
109
- position: "absolute",
110
- bottom: 0,
111
- left: 0,
112
- right: 0,
113
- height: "25%",
114
- justifyContent: "flex-end",
115
- alignItems: "flex-end",
116
- padding: 16,
117
- },
118
- editBadge: {
119
- borderRadius: 20,
120
- padding: 10,
121
- },
122
- placeholderContainer: {
123
- flex: 1,
124
- justifyContent: "center",
125
- alignItems: "center",
126
- },
127
- uploadIconContainer: {
128
- borderRadius: 50,
129
- padding: 24,
130
- marginBottom: 16,
131
- },
132
- placeholderText: {
133
- textAlign: "center",
134
- fontWeight: "600",
135
- },
136
- });
@@ -1,78 +0,0 @@
1
- /**
2
- * Mode Selector Component
3
- * @description Horizontal scrollable mode selection toolbar
4
- */
5
-
6
- import * as React from "react";
7
- import { memo } from "react";
8
- import { View, StyleSheet, ScrollView, TouchableOpacity } from "react-native";
9
- import {
10
- AtomicIcon,
11
- useAppDesignTokens,
12
- } from "@umituz/react-native-design-system";
13
- import type { ModeSelectorProps } from "../../domain/entities";
14
-
15
- export const ModeSelector: React.FC<ModeSelectorProps> = memo(
16
- function ModeSelector({ activeMode, onModeChange, isProcessing, modes }) {
17
- const tokens = useAppDesignTokens();
18
-
19
- return (
20
- <View
21
- style={[
22
- styles.container,
23
- { backgroundColor: tokens.colors.surface },
24
- ]}
25
- >
26
- <ScrollView
27
- horizontal
28
- showsHorizontalScrollIndicator={false}
29
- contentContainerStyle={styles.scrollContent}
30
- >
31
- {modes.map((mode) => {
32
- const isActive = activeMode === mode.id;
33
- return (
34
- <TouchableOpacity
35
- key={mode.id}
36
- style={[
37
- styles.modeButton,
38
- isActive && {
39
- backgroundColor: tokens.colors.primary,
40
- },
41
- ]}
42
- onPress={() => !isProcessing && onModeChange(mode.id)}
43
- disabled={isProcessing}
44
- activeOpacity={0.7}
45
- >
46
- <AtomicIcon
47
- name={mode.icon}
48
- size="md"
49
- color={isActive ? "onPrimary" : "onSurface"}
50
- />
51
- </TouchableOpacity>
52
- );
53
- })}
54
- </ScrollView>
55
- </View>
56
- );
57
- }
58
- );
59
-
60
- const styles = StyleSheet.create({
61
- container: {
62
- borderRadius: 24,
63
- paddingVertical: 8,
64
- paddingHorizontal: 4,
65
- },
66
- scrollContent: {
67
- flexDirection: "row",
68
- gap: 8,
69
- paddingHorizontal: 8,
70
- },
71
- modeButton: {
72
- width: 48,
73
- height: 48,
74
- borderRadius: 16,
75
- justifyContent: "center",
76
- alignItems: "center",
77
- },
78
- });
@@ -1,142 +0,0 @@
1
- /**
2
- * Prompt Input Component
3
- * @description Text input with sample prompt chips
4
- */
5
-
6
- import React, { memo } from "react";
7
- import { View, TextInput, StyleSheet, TouchableOpacity } from "react-native";
8
- import {
9
- AtomicText,
10
- useAppDesignTokens,
11
- } from "@umituz/react-native-design-system";
12
- import type { PromptInputProps } from "../../domain/entities";
13
- import { DEFAULT_SAMPLE_PROMPTS } from "../../infrastructure/constants";
14
-
15
- export const PromptInput: React.FC<PromptInputProps> = memo(
16
- function PromptInput({
17
- value,
18
- onChangeText,
19
- isProcessing,
20
- label,
21
- placeholder,
22
- samplePrompts = DEFAULT_SAMPLE_PROMPTS,
23
- samplePromptsLabel,
24
- }) {
25
- const tokens = useAppDesignTokens();
26
-
27
- return (
28
- <View style={styles.container}>
29
- {label && (
30
- <AtomicText
31
-
32
- style={[
33
- styles.label,
34
- {
35
- color: tokens.colors.textPrimary,
36
- marginBottom: tokens.spacing.sm,
37
- },
38
- ]}
39
- >
40
- {label}
41
- </AtomicText>
42
- )}
43
-
44
- <TextInput
45
- value={value}
46
- onChangeText={onChangeText}
47
- placeholder={placeholder}
48
- placeholderTextColor={tokens.colors.textTertiary}
49
- multiline
50
-
51
- editable={!isProcessing}
52
- style={[
53
- styles.input,
54
- {
55
- backgroundColor: tokens.colors.surface,
56
- borderColor: tokens.colors.border,
57
- color: tokens.colors.textPrimary,
58
- },
59
- ]}
60
- />
61
-
62
- {samplePrompts.length > 0 && (
63
- <>
64
- {samplePromptsLabel && (
65
- <AtomicText
66
-
67
- style={[
68
- styles.sampleLabel,
69
- {
70
- color: tokens.colors.textSecondary,
71
- marginTop: tokens.spacing.md,
72
- marginBottom: tokens.spacing.sm,
73
- },
74
- ]}
75
- >
76
- {samplePromptsLabel}
77
- </AtomicText>
78
- )}
79
-
80
- <View style={styles.sampleContainer}>
81
- {samplePrompts.map((prompt) => (
82
- <TouchableOpacity
83
- key={prompt.id}
84
- style={[
85
- styles.sampleChip,
86
- {
87
- backgroundColor: tokens.colors.surfaceSecondary,
88
- borderColor: tokens.colors.border,
89
- },
90
- ]}
91
- onPress={() => onChangeText(prompt.text)}
92
- disabled={isProcessing}
93
- >
94
- <AtomicText
95
-
96
- style={{ color: tokens.colors.textSecondary }}
97
-
98
- >
99
- {prompt.text}
100
- </AtomicText>
101
- </TouchableOpacity>
102
- ))}
103
- </View>
104
- </>
105
- )}
106
- </View>
107
- );
108
- }
109
- );
110
-
111
- const styles = StyleSheet.create({
112
- container: {
113
- marginVertical: 16,
114
- },
115
- label: {
116
- fontWeight: "600",
117
- },
118
- input: {
119
- minHeight: 120,
120
- borderWidth: 1,
121
- borderRadius: 16,
122
- paddingHorizontal: 16,
123
- paddingVertical: 14,
124
- fontSize: 16,
125
- textAlignVertical: "top",
126
- lineHeight: 24,
127
- },
128
- sampleLabel: {
129
- fontWeight: "500",
130
- },
131
- sampleContainer: {
132
- flexDirection: "row",
133
- flexWrap: "wrap",
134
- gap: 8,
135
- },
136
- sampleChip: {
137
- paddingHorizontal: 12,
138
- paddingVertical: 8,
139
- borderRadius: 20,
140
- borderWidth: 1,
141
- },
142
- });
@@ -1,122 +0,0 @@
1
- /**
2
- * Result Display Component
3
- * @description Displays processed image with save/reset actions
4
- */
5
-
6
- import React, { memo } from "react";
7
- import { View, StyleSheet, Image, TouchableOpacity } from "react-native";
8
- import {
9
- AtomicText,
10
- AtomicIcon,
11
- useAppDesignTokens,
12
- } from "@umituz/react-native-design-system";
13
- import type { ResultDisplayProps } from "../../domain/entities";
14
-
15
- export const ResultDisplay: React.FC<ResultDisplayProps> = memo(
16
- function ResultDisplay({
17
- imageUrl,
18
- isProcessing,
19
- onSave,
20
- onReset,
21
- saveButtonText,
22
- resetButtonText,
23
- }) {
24
- const tokens = useAppDesignTokens();
25
-
26
- if (!imageUrl || isProcessing) {
27
- return null;
28
- }
29
-
30
- return (
31
- <View style={styles.container}>
32
- <View style={[styles.resultContainer, { borderColor: tokens.colors.borderLight }]}>
33
- <Image
34
- source={{ uri: imageUrl }}
35
- style={styles.resultImage}
36
- resizeMode="cover"
37
- />
38
- </View>
39
-
40
- <View style={styles.actionsContainer}>
41
- <TouchableOpacity
42
- style={[
43
- styles.actionButton,
44
- { backgroundColor: tokens.colors.backgroundSecondary },
45
- ]}
46
- onPress={onReset}
47
- >
48
- <AtomicIcon
49
- name="refresh-cw"
50
- size="md"
51
-
52
- />
53
- <AtomicText
54
-
55
- style={[styles.actionText, { color: tokens.colors.textPrimary }]}
56
- >
57
- {resetButtonText}
58
- </AtomicText>
59
- </TouchableOpacity>
60
-
61
- <TouchableOpacity
62
- style={[
63
- styles.actionButton,
64
- { backgroundColor: tokens.colors.success },
65
- ]}
66
- onPress={onSave}
67
- >
68
- <AtomicIcon
69
- name="download"
70
- size="md"
71
-
72
- />
73
- <AtomicText
74
-
75
- style={[
76
- styles.actionText,
77
- { color: tokens.colors.backgroundPrimary },
78
- ]}
79
- >
80
- {saveButtonText}
81
- </AtomicText>
82
- </TouchableOpacity>
83
- </View>
84
- </View>
85
- );
86
- }
87
- );
88
-
89
- const styles = StyleSheet.create({
90
- container: {
91
- marginTop: 24,
92
- marginBottom: 16,
93
- },
94
- resultContainer: {
95
- width: "100%",
96
- aspectRatio: 1,
97
- borderRadius: 24,
98
- overflow: "hidden",
99
- marginBottom: 16,
100
- borderWidth: 1,
101
- },
102
- resultImage: {
103
- width: "100%",
104
- height: "100%",
105
- },
106
- actionsContainer: {
107
- flexDirection: "row",
108
- gap: 12,
109
- },
110
- actionButton: {
111
- flex: 1,
112
- flexDirection: "row",
113
- alignItems: "center",
114
- justifyContent: "center",
115
- paddingVertical: 14,
116
- borderRadius: 16,
117
- gap: 8,
118
- },
119
- actionText: {
120
- fontWeight: "600",
121
- },
122
- });
@@ -1,119 +0,0 @@
1
- /**
2
- * useBackgroundFeature Hook
3
- * @description Main hook for background feature state and actions
4
- */
5
-
6
- import { useCallback, useState } from "react";
7
- import type {
8
- BackgroundFeatureState,
9
- BackgroundProcessResult,
10
- UseBackgroundFeatureConfig,
11
- StudioMode,
12
- } from "../../domain/entities";
13
-
14
- export interface UseBackgroundFeatureReturn extends BackgroundFeatureState {
15
- readonly selectImage: () => Promise<void>;
16
- readonly process: (prompt?: string) => Promise<void>;
17
- readonly save: () => Promise<void>;
18
- readonly reset: () => void;
19
- readonly setPrompt: (prompt: string) => void;
20
- readonly setMode: (mode: StudioMode) => void;
21
- }
22
-
23
- export function useBackgroundFeature(
24
- config: UseBackgroundFeatureConfig
25
- ): UseBackgroundFeatureReturn {
26
- const [imageUri, setImageUri] = useState<string | null>(null);
27
- const [prompt, setPrompt] = useState<string>("");
28
- const [processedUrl, setProcessedUrl] = useState<string | null>(null);
29
- const [isProcessing, setIsProcessing] = useState(false);
30
- const [progress, setProgress] = useState(0);
31
- const [error, setError] = useState<string | null>(null);
32
- const [mode, setMode] = useState<StudioMode>(
33
- config.defaultMode ?? "transparent"
34
- );
35
-
36
- const selectImage = useCallback(async (): Promise<void> => {
37
- if (!config.onSelectImage) {
38
- return;
39
- }
40
-
41
- try {
42
- const uri = await config.onSelectImage();
43
- if (uri) {
44
- setImageUri(uri);
45
- setError(null);
46
- setProcessedUrl(null);
47
- }
48
- } catch (err) {
49
- setError(err instanceof Error ? err.message : "Failed to select image");
50
- }
51
- }, [config]);
52
-
53
- const process = useCallback(
54
- async (newPrompt?: string): Promise<void> => {
55
- if (!imageUri) {
56
- setError("Please select an image first");
57
- return;
58
- }
59
-
60
- const currentPrompt = newPrompt ?? prompt;
61
- setIsProcessing(true);
62
- setProgress(0);
63
- setError(null);
64
-
65
- try {
66
- const result: BackgroundProcessResult = await config.processRequest({
67
- imageUri,
68
- prompt: currentPrompt,
69
- mode,
70
- onProgress: setProgress,
71
- });
72
-
73
- if (result.success && result.imageUrl) {
74
- setProcessedUrl(result.imageUrl);
75
- } else {
76
- setError(result.error || "Processing failed");
77
- }
78
- } catch (err) {
79
- setError(err instanceof Error ? err.message : "Processing failed");
80
- } finally {
81
- setIsProcessing(false);
82
- setProgress(0);
83
- }
84
- },
85
- [imageUri, prompt, mode, config]
86
- );
87
-
88
- const save = useCallback((): Promise<void> => {
89
- if (!processedUrl) {
90
- return Promise.resolve();
91
- }
92
- return Promise.resolve();
93
- }, [processedUrl]);
94
-
95
- const reset = useCallback((): void => {
96
- setImageUri(null);
97
- setPrompt("");
98
- setProcessedUrl(null);
99
- setIsProcessing(false);
100
- setProgress(0);
101
- setError(null);
102
- }, []);
103
-
104
- return {
105
- imageUri,
106
- prompt,
107
- processedUrl,
108
- isProcessing,
109
- progress,
110
- error,
111
- mode,
112
- selectImage,
113
- process,
114
- save,
115
- reset,
116
- setPrompt,
117
- setMode,
118
- };
119
- }