@umituz/react-native-ai-generation-content 1.16.0 → 1.17.1

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 (116) hide show
  1. package/package.json +13 -14
  2. package/src/domains/creations/domain/entities/Creation.ts +33 -2
  3. package/src/domains/creations/domain/entities/index.ts +1 -1
  4. package/src/domains/creations/domain/types/creation-categories.ts +133 -0
  5. package/src/domains/creations/domain/types/creation-filter.ts +131 -0
  6. package/src/domains/creations/domain/types/creation-types.ts +63 -0
  7. package/src/domains/creations/domain/types/index.ts +44 -0
  8. package/src/domains/creations/domain/utils/creation-helpers.ts +134 -0
  9. package/src/domains/creations/domain/utils/index.ts +8 -0
  10. package/src/domains/creations/domain/utils/preview-helpers.ts +84 -0
  11. package/src/domains/creations/domain/utils/status-helpers.ts +90 -0
  12. package/src/domains/creations/index.ts +95 -21
  13. package/src/domains/creations/infrastructure/repositories/CreationsRepository.ts +14 -1
  14. package/src/domains/creations/presentation/components/CreationActions.tsx +120 -0
  15. package/src/domains/creations/presentation/components/CreationBadges.tsx +111 -0
  16. package/src/domains/creations/presentation/components/CreationCard.tsx +201 -102
  17. package/src/domains/creations/presentation/components/CreationPreview.tsx +117 -0
  18. package/src/domains/creations/presentation/components/CreationsFilterBar.tsx +254 -0
  19. package/src/domains/creations/presentation/components/CreationsGrid.tsx +121 -68
  20. package/src/domains/creations/presentation/components/index.ts +23 -3
  21. package/src/domains/creations/presentation/hooks/index.ts +1 -0
  22. package/src/domains/creations/presentation/hooks/useAdvancedFilter.ts +262 -0
  23. package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +5 -6
  24. package/src/features/ai-hug/domain/index.ts +5 -0
  25. package/src/features/ai-hug/domain/types/ai-hug.types.ts +72 -0
  26. package/src/features/ai-hug/domain/types/index.ts +14 -0
  27. package/src/features/ai-hug/index.ts +27 -0
  28. package/src/features/ai-hug/infrastructure/index.ts +5 -0
  29. package/src/features/ai-hug/infrastructure/services/ai-hug-executor.ts +96 -0
  30. package/src/features/ai-hug/infrastructure/services/index.ts +6 -0
  31. package/src/features/ai-hug/presentation/hooks/index.ts +9 -0
  32. package/src/features/ai-hug/presentation/hooks/useAIHugFeature.ts +157 -0
  33. package/src/features/ai-hug/presentation/index.ts +5 -0
  34. package/src/features/ai-kiss/domain/index.ts +5 -0
  35. package/src/features/ai-kiss/domain/types/ai-kiss.types.ts +72 -0
  36. package/src/features/ai-kiss/domain/types/index.ts +14 -0
  37. package/src/features/ai-kiss/index.ts +27 -0
  38. package/src/features/ai-kiss/infrastructure/index.ts +5 -0
  39. package/src/features/ai-kiss/infrastructure/services/ai-kiss-executor.ts +96 -0
  40. package/src/features/ai-kiss/infrastructure/services/index.ts +6 -0
  41. package/src/features/ai-kiss/presentation/hooks/index.ts +9 -0
  42. package/src/features/ai-kiss/presentation/hooks/useAIKissFeature.ts +157 -0
  43. package/src/features/ai-kiss/presentation/index.ts +5 -0
  44. package/src/features/anime-selfie/domain/index.ts +5 -0
  45. package/src/features/anime-selfie/domain/types/anime-selfie.types.ts +72 -0
  46. package/src/features/anime-selfie/domain/types/index.ts +15 -0
  47. package/src/features/anime-selfie/index.ts +28 -0
  48. package/src/features/anime-selfie/infrastructure/index.ts +5 -0
  49. package/src/features/anime-selfie/infrastructure/services/anime-selfie-executor.ts +95 -0
  50. package/src/features/anime-selfie/infrastructure/services/index.ts +6 -0
  51. package/src/features/anime-selfie/presentation/hooks/index.ts +9 -0
  52. package/src/features/anime-selfie/presentation/hooks/useAnimeSelfieFeature.ts +138 -0
  53. package/src/features/anime-selfie/presentation/index.ts +5 -0
  54. package/src/features/background/domain/types/index.ts +15 -0
  55. package/src/features/background/domain/types/replace-background.types.ts +82 -0
  56. package/src/features/background/index.ts +31 -3
  57. package/src/features/background/infrastructure/index.ts +5 -0
  58. package/src/features/background/infrastructure/services/index.ts +6 -0
  59. package/src/features/background/infrastructure/services/replace-background-executor.ts +95 -0
  60. package/src/features/background/presentation/hooks/index.ts +6 -1
  61. package/src/features/background/presentation/hooks/useReplaceBackgroundFeature.ts +160 -0
  62. package/src/features/face-swap/domain/index.ts +5 -0
  63. package/src/features/face-swap/domain/types/face-swap.types.ts +72 -0
  64. package/src/features/face-swap/domain/types/index.ts +14 -0
  65. package/src/features/face-swap/index.ts +27 -1
  66. package/src/features/face-swap/infrastructure/index.ts +5 -0
  67. package/src/features/face-swap/infrastructure/services/face-swap-executor.ts +96 -0
  68. package/src/features/face-swap/infrastructure/services/index.ts +6 -0
  69. package/src/features/face-swap/presentation/hooks/index.ts +9 -0
  70. package/src/features/face-swap/presentation/hooks/useFaceSwapFeature.ts +157 -0
  71. package/src/features/face-swap/presentation/index.ts +5 -0
  72. package/src/features/photo-restoration/domain/index.ts +1 -0
  73. package/src/features/photo-restoration/domain/types/index.ts +10 -0
  74. package/src/features/photo-restoration/domain/types/photo-restore.types.ts +71 -0
  75. package/src/features/photo-restoration/index.ts +34 -1
  76. package/src/features/photo-restoration/infrastructure/index.ts +1 -0
  77. package/src/features/photo-restoration/infrastructure/services/index.ts +2 -0
  78. package/src/features/photo-restoration/infrastructure/services/photo-restore-executor.ts +98 -0
  79. package/src/features/photo-restoration/presentation/components/PhotoRestoreFeature.tsx +175 -0
  80. package/src/features/photo-restoration/presentation/components/PhotoRestoreResultView.tsx +98 -0
  81. package/src/features/photo-restoration/presentation/components/index.ts +4 -0
  82. package/src/features/photo-restoration/presentation/hooks/index.ts +5 -0
  83. package/src/features/photo-restoration/presentation/hooks/usePhotoRestoreFeature.ts +137 -0
  84. package/src/features/photo-restoration/presentation/index.ts +2 -0
  85. package/src/features/remove-background/domain/index.ts +5 -0
  86. package/src/features/remove-background/domain/types/index.ts +14 -0
  87. package/src/features/remove-background/domain/types/remove-background.types.ts +69 -0
  88. package/src/features/remove-background/index.ts +27 -0
  89. package/src/features/remove-background/infrastructure/index.ts +5 -0
  90. package/src/features/remove-background/infrastructure/services/index.ts +6 -0
  91. package/src/features/remove-background/infrastructure/services/remove-background-executor.ts +95 -0
  92. package/src/features/remove-background/presentation/hooks/index.ts +9 -0
  93. package/src/features/remove-background/presentation/hooks/useRemoveBackgroundFeature.ts +137 -0
  94. package/src/features/remove-background/presentation/index.ts +5 -0
  95. package/src/features/remove-object/domain/index.ts +5 -0
  96. package/src/features/remove-object/domain/types/index.ts +14 -0
  97. package/src/features/remove-object/domain/types/remove-object.types.ts +77 -0
  98. package/src/features/remove-object/index.ts +27 -0
  99. package/src/features/remove-object/infrastructure/index.ts +5 -0
  100. package/src/features/remove-object/infrastructure/services/index.ts +6 -0
  101. package/src/features/remove-object/infrastructure/services/remove-object-executor.ts +99 -0
  102. package/src/features/remove-object/presentation/hooks/index.ts +9 -0
  103. package/src/features/remove-object/presentation/hooks/useRemoveObjectFeature.ts +168 -0
  104. package/src/features/remove-object/presentation/index.ts +5 -0
  105. package/src/features/upscaling/domain/types/index.ts +0 -1
  106. package/src/features/upscaling/domain/types/upscale.types.ts +14 -0
  107. package/src/features/upscaling/index.ts +3 -11
  108. package/src/features/upscaling/infrastructure/services/index.ts +1 -6
  109. package/src/features/upscaling/infrastructure/services/upscale-executor.ts +64 -30
  110. package/src/features/upscaling/presentation/hooks/useUpscaleFeature.ts +12 -7
  111. package/src/index.ts +45 -0
  112. package/src/types/jsx.d.ts +19 -0
  113. package/src/features/face-swap/domain/entities.ts +0 -48
  114. package/src/features/photo-restoration/domain/entities.ts +0 -48
  115. package/src/features/upscaling/domain/types/provider.types.ts +0 -23
  116. package/src/features/upscaling/infrastructure/services/upscale-provider-registry.ts +0 -77
@@ -0,0 +1,175 @@
1
+ /**
2
+ * PhotoRestoreFeature Component
3
+ * Main photo restore feature UI component
4
+ */
5
+
6
+ import React, { useCallback, useMemo } from "react";
7
+ import { View, ScrollView, StyleSheet } from "react-native";
8
+ import {
9
+ useAppDesignTokens,
10
+ PhotoUploadCard,
11
+ AtomicText,
12
+ AtomicButton,
13
+ } from "@umituz/react-native-design-system";
14
+ import { PhotoRestoreResultView } from "./PhotoRestoreResultView";
15
+ import type {
16
+ PhotoRestoreTranslations,
17
+ PhotoRestoreFeatureConfig,
18
+ } from "../../domain/types";
19
+
20
+ export interface PhotoRestoreFeatureProps {
21
+ imageUri: string | null;
22
+ processedUrl: string | null;
23
+ isProcessing: boolean;
24
+ progress: number;
25
+ error: string | null;
26
+ translations: PhotoRestoreTranslations;
27
+ config?: PhotoRestoreFeatureConfig;
28
+ onSelectImage: () => void;
29
+ onProcess: () => void;
30
+ onSave: () => void;
31
+ onReset: () => void;
32
+ renderProcessingModal?: (props: {
33
+ visible: boolean;
34
+ progress: number;
35
+ }) => React.ReactNode;
36
+ }
37
+
38
+ export const PhotoRestoreFeature: React.FC<PhotoRestoreFeatureProps> = ({
39
+ imageUri,
40
+ processedUrl,
41
+ isProcessing,
42
+ progress,
43
+ error,
44
+ translations,
45
+ onSelectImage,
46
+ onProcess,
47
+ onSave,
48
+ onReset,
49
+ renderProcessingModal,
50
+ }) => {
51
+ const tokens = useAppDesignTokens();
52
+
53
+ const photoTranslations = useMemo(
54
+ () => ({
55
+ tapToUpload: translations.uploadTitle,
56
+ selectPhoto: translations.uploadSubtitle,
57
+ change: translations.uploadChange,
58
+ analyzing: translations.uploadAnalyzing,
59
+ }),
60
+ [translations],
61
+ );
62
+
63
+ const handleProcess = useCallback(() => {
64
+ onProcess();
65
+ }, [onProcess]);
66
+
67
+ if (processedUrl && imageUri) {
68
+ return (
69
+ <ScrollView
70
+ style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}
71
+ contentContainerStyle={styles.content}
72
+ showsVerticalScrollIndicator={false}
73
+ >
74
+ <PhotoRestoreResultView
75
+ originalUri={imageUri}
76
+ processedUri={processedUrl}
77
+ translations={{
78
+ successText: translations.successText,
79
+ saveButtonText: translations.saveButtonText,
80
+ tryAnotherText: translations.tryAnotherText,
81
+ beforeLabel: translations.beforeLabel,
82
+ afterLabel: translations.afterLabel,
83
+ }}
84
+ onSave={onSave}
85
+ onReset={onReset}
86
+ />
87
+ </ScrollView>
88
+ );
89
+ }
90
+
91
+ return (
92
+ <>
93
+ <ScrollView
94
+ style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}
95
+ contentContainerStyle={styles.content}
96
+ showsVerticalScrollIndicator={false}
97
+ >
98
+ <AtomicText
99
+ type="bodyLarge"
100
+ style={[styles.description, { color: tokens.colors.textSecondary }]}
101
+ >
102
+ {translations.description}
103
+ </AtomicText>
104
+
105
+ <PhotoUploadCard
106
+ imageUri={imageUri}
107
+ onPress={onSelectImage}
108
+ isValidating={isProcessing}
109
+ disabled={isProcessing}
110
+ translations={photoTranslations}
111
+ config={{
112
+ aspectRatio: 1,
113
+ borderRadius: 24,
114
+ showValidationStatus: false,
115
+ allowChange: true,
116
+ }}
117
+ />
118
+
119
+ {error && (
120
+ <View
121
+ style={[
122
+ styles.errorContainer,
123
+ { backgroundColor: `${tokens.colors.error}15` },
124
+ ]}
125
+ >
126
+ <AtomicText type="bodyMedium" style={{ color: tokens.colors.error }}>
127
+ {error}
128
+ </AtomicText>
129
+ </View>
130
+ )}
131
+
132
+ <View style={styles.buttonContainer}>
133
+ <AtomicButton
134
+ title={
135
+ isProcessing
136
+ ? translations.processingText
137
+ : translations.processButtonText
138
+ }
139
+ onPress={handleProcess}
140
+ disabled={!imageUri || isProcessing}
141
+ variant="primary"
142
+ size="lg"
143
+ />
144
+ </View>
145
+ </ScrollView>
146
+
147
+ {renderProcessingModal?.({ visible: isProcessing, progress })}
148
+ </>
149
+ );
150
+ };
151
+
152
+ const styles = StyleSheet.create({
153
+ container: {
154
+ flex: 1,
155
+ },
156
+ content: {
157
+ paddingVertical: 16,
158
+ },
159
+ description: {
160
+ textAlign: "center",
161
+ marginHorizontal: 24,
162
+ marginBottom: 24,
163
+ lineHeight: 24,
164
+ },
165
+ errorContainer: {
166
+ marginHorizontal: 24,
167
+ marginBottom: 16,
168
+ padding: 16,
169
+ borderRadius: 12,
170
+ },
171
+ buttonContainer: {
172
+ marginHorizontal: 24,
173
+ marginTop: 8,
174
+ },
175
+ });
@@ -0,0 +1,98 @@
1
+ /**
2
+ * PhotoRestoreResultView Component
3
+ * Displays the restored image result with before/after comparison
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, StyleSheet } from "react-native";
8
+ import {
9
+ AtomicText,
10
+ AtomicButton,
11
+ useAppDesignTokens,
12
+ } from "@umituz/react-native-design-system";
13
+ import { ComparisonSlider } from "../../../background/presentation/components/ComparisonSlider";
14
+ import type { PhotoRestoreTranslations } from "../../domain/types";
15
+
16
+ export interface PhotoRestoreResultViewProps {
17
+ originalUri: string;
18
+ processedUri: string;
19
+ translations: Pick<
20
+ PhotoRestoreTranslations,
21
+ | "successText"
22
+ | "saveButtonText"
23
+ | "tryAnotherText"
24
+ | "beforeLabel"
25
+ | "afterLabel"
26
+ >;
27
+ onSave: () => void;
28
+ onReset: () => void;
29
+ }
30
+
31
+ export const PhotoRestoreResultView: React.FC<PhotoRestoreResultViewProps> = ({
32
+ originalUri,
33
+ processedUri,
34
+ translations,
35
+ onSave,
36
+ onReset,
37
+ }) => {
38
+ const tokens = useAppDesignTokens();
39
+
40
+ return (
41
+ <View style={styles.container}>
42
+ <AtomicText
43
+ type="headlineMedium"
44
+ style={[styles.title, { color: tokens.colors.success }]}
45
+ >
46
+ {translations.successText}
47
+ </AtomicText>
48
+
49
+ <ComparisonSlider
50
+ originalUri={originalUri}
51
+ processedUri={processedUri}
52
+ beforeLabel={translations.beforeLabel}
53
+ afterLabel={translations.afterLabel}
54
+ />
55
+
56
+ <AtomicText
57
+ type="bodySmall"
58
+ style={[styles.hint, { color: tokens.colors.textSecondary }]}
59
+ >
60
+ Drag slider to compare
61
+ </AtomicText>
62
+
63
+ <View style={styles.actions}>
64
+ <AtomicButton
65
+ title={translations.saveButtonText}
66
+ onPress={onSave}
67
+ variant="primary"
68
+ size="lg"
69
+ />
70
+ <AtomicButton
71
+ title={translations.tryAnotherText}
72
+ onPress={onReset}
73
+ variant="secondary"
74
+ size="lg"
75
+ />
76
+ </View>
77
+ </View>
78
+ );
79
+ };
80
+
81
+ const styles = StyleSheet.create({
82
+ container: {
83
+ flex: 1,
84
+ paddingHorizontal: 24,
85
+ },
86
+ title: {
87
+ textAlign: "center",
88
+ marginBottom: 24,
89
+ },
90
+ hint: {
91
+ textAlign: "center",
92
+ marginTop: 12,
93
+ marginBottom: 24,
94
+ },
95
+ actions: {
96
+ gap: 12,
97
+ },
98
+ });
@@ -0,0 +1,4 @@
1
+ export { PhotoRestoreFeature } from "./PhotoRestoreFeature";
2
+ export { PhotoRestoreResultView } from "./PhotoRestoreResultView";
3
+ export type { PhotoRestoreFeatureProps } from "./PhotoRestoreFeature";
4
+ export type { PhotoRestoreResultViewProps } from "./PhotoRestoreResultView";
@@ -0,0 +1,5 @@
1
+ export { usePhotoRestoreFeature } from "./usePhotoRestoreFeature";
2
+ export type {
3
+ UsePhotoRestoreFeatureProps,
4
+ UsePhotoRestoreFeatureReturn,
5
+ } from "./usePhotoRestoreFeature";
@@ -0,0 +1,137 @@
1
+ /**
2
+ * usePhotoRestoreFeature Hook
3
+ * Manages photo restore feature state and actions
4
+ */
5
+
6
+ import { useState, useCallback } from "react";
7
+ import { executePhotoRestore } from "../../infrastructure/services";
8
+ import type {
9
+ PhotoRestoreFeatureState,
10
+ PhotoRestoreFeatureConfig,
11
+ PhotoRestoreResult,
12
+ } from "../../domain/types";
13
+
14
+ declare const __DEV__: boolean;
15
+
16
+ export interface UsePhotoRestoreFeatureProps {
17
+ config: PhotoRestoreFeatureConfig;
18
+ userId: string;
19
+ onSelectImage: () => Promise<string | null>;
20
+ onSaveImage: (imageUrl: string) => Promise<void>;
21
+ }
22
+
23
+ export interface UsePhotoRestoreFeatureReturn extends PhotoRestoreFeatureState {
24
+ selectImage: () => Promise<void>;
25
+ process: () => Promise<void>;
26
+ save: () => Promise<void>;
27
+ reset: () => void;
28
+ }
29
+
30
+ const initialState: PhotoRestoreFeatureState = {
31
+ imageUri: null,
32
+ processedUrl: null,
33
+ isProcessing: false,
34
+ progress: 0,
35
+ error: null,
36
+ };
37
+
38
+ export function usePhotoRestoreFeature(
39
+ props: UsePhotoRestoreFeatureProps,
40
+ ): UsePhotoRestoreFeatureReturn {
41
+ const { config, userId, onSelectImage, onSaveImage } = props;
42
+ const [state, setState] = useState<PhotoRestoreFeatureState>(initialState);
43
+
44
+ const selectImage = useCallback(async () => {
45
+ try {
46
+ const uri = await onSelectImage();
47
+ if (uri) {
48
+ setState((prev) => ({ ...prev, imageUri: uri, error: null }));
49
+ config.onImageSelect?.(uri);
50
+ }
51
+ } catch (error) {
52
+ const message = error instanceof Error ? error.message : String(error);
53
+ setState((prev) => ({ ...prev, error: message }));
54
+ }
55
+ }, [onSelectImage, config]);
56
+
57
+ const handleProgress = useCallback((progress: number) => {
58
+ setState((prev) => ({ ...prev, progress }));
59
+ }, []);
60
+
61
+ const process = useCallback(async () => {
62
+ if (!state.imageUri) return;
63
+
64
+ setState((prev) => ({
65
+ ...prev,
66
+ isProcessing: true,
67
+ progress: 0,
68
+ error: null,
69
+ }));
70
+
71
+ config.onProcessingStart?.();
72
+
73
+ if (__DEV__) {
74
+ // eslint-disable-next-line no-console
75
+ console.log("[usePhotoRestoreFeature] Starting photo restore process");
76
+ }
77
+
78
+ const imageBase64 = await config.prepareImage(state.imageUri);
79
+
80
+ const result: PhotoRestoreResult = await executePhotoRestore(
81
+ {
82
+ imageUri: state.imageUri,
83
+ imageBase64,
84
+ userId,
85
+ },
86
+ {
87
+ model: config.model,
88
+ buildInput: config.buildInput,
89
+ extractResult: config.extractResult,
90
+ onProgress: handleProgress,
91
+ },
92
+ );
93
+
94
+ if (result.success && result.imageUrl) {
95
+ const url = result.imageUrl;
96
+ setState((prev) => ({
97
+ ...prev,
98
+ isProcessing: false,
99
+ processedUrl: url,
100
+ progress: 100,
101
+ }));
102
+ config.onProcessingComplete?.(result);
103
+ } else {
104
+ const errorMessage = result.error || "Processing failed";
105
+ setState((prev) => ({
106
+ ...prev,
107
+ isProcessing: false,
108
+ error: errorMessage,
109
+ progress: 0,
110
+ }));
111
+ config.onError?.(errorMessage);
112
+ }
113
+ }, [state.imageUri, userId, config, handleProgress]);
114
+
115
+ const save = useCallback(async () => {
116
+ if (!state.processedUrl) return;
117
+
118
+ try {
119
+ await onSaveImage(state.processedUrl);
120
+ } catch (error) {
121
+ const message = error instanceof Error ? error.message : String(error);
122
+ setState((prev) => ({ ...prev, error: message }));
123
+ }
124
+ }, [state.processedUrl, onSaveImage]);
125
+
126
+ const reset = useCallback(() => {
127
+ setState(initialState);
128
+ }, []);
129
+
130
+ return {
131
+ ...state,
132
+ selectImage,
133
+ process,
134
+ save,
135
+ reset,
136
+ };
137
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./hooks";
2
+ export * from "./components";
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Remove Background Domain Index
3
+ */
4
+
5
+ export * from "./types";
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Remove Background Domain Types Index
3
+ */
4
+
5
+ export type {
6
+ RemoveBackgroundOptions,
7
+ RemoveBackgroundRequest,
8
+ RemoveBackgroundResult,
9
+ RemoveBackgroundFeatureState,
10
+ RemoveBackgroundTranslations,
11
+ RemoveBackgroundInputBuilder,
12
+ RemoveBackgroundResultExtractor,
13
+ RemoveBackgroundFeatureConfig,
14
+ } from "./remove-background.types";
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Remove Background Feature Types
3
+ * Request, Result, Config types for background removal
4
+ */
5
+
6
+ export interface RemoveBackgroundOptions {
7
+ refineEdges?: boolean;
8
+ outputFormat?: "png" | "webp";
9
+ backgroundColor?: string;
10
+ }
11
+
12
+ export interface RemoveBackgroundRequest {
13
+ imageUri: string;
14
+ imageBase64?: string;
15
+ userId: string;
16
+ options?: RemoveBackgroundOptions;
17
+ }
18
+
19
+ export interface RemoveBackgroundResult {
20
+ success: boolean;
21
+ imageUrl?: string;
22
+ imageBase64?: string;
23
+ error?: string;
24
+ requestId?: string;
25
+ }
26
+
27
+ export interface RemoveBackgroundFeatureState {
28
+ imageUri: string | null;
29
+ processedUrl: string | null;
30
+ isProcessing: boolean;
31
+ progress: number;
32
+ error: string | null;
33
+ }
34
+
35
+ export interface RemoveBackgroundTranslations {
36
+ uploadTitle: string;
37
+ uploadSubtitle: string;
38
+ uploadChange: string;
39
+ uploadAnalyzing: string;
40
+ description: string;
41
+ processingText: string;
42
+ processButtonText: string;
43
+ successText: string;
44
+ saveButtonText: string;
45
+ tryAnotherText: string;
46
+ beforeLabel?: string;
47
+ afterLabel?: string;
48
+ compareHint?: string;
49
+ }
50
+
51
+ export type RemoveBackgroundInputBuilder = (
52
+ base64: string,
53
+ options?: RemoveBackgroundOptions,
54
+ ) => Record<string, unknown>;
55
+
56
+ export type RemoveBackgroundResultExtractor = (result: unknown) => string | undefined;
57
+
58
+ export interface RemoveBackgroundFeatureConfig {
59
+ providerId?: string;
60
+ creditCost?: number;
61
+ model: string;
62
+ buildInput: RemoveBackgroundInputBuilder;
63
+ extractResult?: RemoveBackgroundResultExtractor;
64
+ prepareImage: (imageUri: string) => Promise<string>;
65
+ onImageSelect?: (uri: string) => void;
66
+ onProcessingStart?: () => void;
67
+ onProcessingComplete?: (result: RemoveBackgroundResult) => void;
68
+ onError?: (error: string) => void;
69
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Remove Background Feature
3
+ * Provider-agnostic background removal feature
4
+ */
5
+
6
+ // Domain Types
7
+ export type {
8
+ RemoveBackgroundOptions,
9
+ RemoveBackgroundRequest,
10
+ RemoveBackgroundResult,
11
+ RemoveBackgroundFeatureState,
12
+ RemoveBackgroundTranslations,
13
+ RemoveBackgroundFeatureConfig,
14
+ RemoveBackgroundInputBuilder,
15
+ RemoveBackgroundResultExtractor,
16
+ } from "./domain";
17
+
18
+ // Infrastructure Services
19
+ export { executeRemoveBackground, hasRemoveBackgroundSupport } from "./infrastructure";
20
+ export type { ExecuteRemoveBackgroundOptions } from "./infrastructure";
21
+
22
+ // Presentation Hooks
23
+ export { useRemoveBackgroundFeature } from "./presentation";
24
+ export type {
25
+ UseRemoveBackgroundFeatureProps,
26
+ UseRemoveBackgroundFeatureReturn,
27
+ } from "./presentation";
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Remove Background Infrastructure Index
3
+ */
4
+
5
+ export * from "./services";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Remove Background Infrastructure Services Index
3
+ */
4
+
5
+ export { executeRemoveBackground, hasRemoveBackgroundSupport } from "./remove-background-executor";
6
+ export type { ExecuteRemoveBackgroundOptions } from "./remove-background-executor";
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Remove Background Executor
3
+ * Provider-agnostic background removal execution using active AI provider
4
+ * Model and input format are provided via options from app level
5
+ */
6
+
7
+ import { providerRegistry } from "../../../../infrastructure/services";
8
+ import { cleanBase64 } from "../../../../infrastructure/utils";
9
+ import type {
10
+ RemoveBackgroundRequest,
11
+ RemoveBackgroundResult,
12
+ RemoveBackgroundInputBuilder,
13
+ RemoveBackgroundResultExtractor,
14
+ } from "../../domain/types";
15
+
16
+ declare const __DEV__: boolean;
17
+
18
+ export interface ExecuteRemoveBackgroundOptions {
19
+ model: string;
20
+ buildInput: RemoveBackgroundInputBuilder;
21
+ extractResult?: RemoveBackgroundResultExtractor;
22
+ onProgress?: (progress: number) => void;
23
+ }
24
+
25
+ function defaultExtractResult(result: unknown): string | undefined {
26
+ if (typeof result !== "object" || result === null) return undefined;
27
+
28
+ const r = result as Record<string, unknown>;
29
+
30
+ if (typeof r.image === "string") return r.image;
31
+ if (Array.isArray(r.images) && r.images[0]?.url) return r.images[0].url;
32
+
33
+ return undefined;
34
+ }
35
+
36
+ export async function executeRemoveBackground(
37
+ request: RemoveBackgroundRequest,
38
+ options: ExecuteRemoveBackgroundOptions,
39
+ ): Promise<RemoveBackgroundResult> {
40
+ const provider = providerRegistry.getActiveProvider();
41
+
42
+ if (!provider) {
43
+ return { success: false, error: "No AI provider configured" };
44
+ }
45
+
46
+ if (!provider.isInitialized()) {
47
+ return { success: false, error: "AI provider not initialized" };
48
+ }
49
+
50
+ if (!request.imageBase64) {
51
+ return { success: false, error: "Image base64 is required" };
52
+ }
53
+
54
+ const { model, buildInput, extractResult, onProgress } = options;
55
+
56
+ if (__DEV__) {
57
+ // eslint-disable-next-line no-console
58
+ console.log(`[RemoveBackground] Provider: ${provider.providerId}, Model: ${model}`);
59
+ }
60
+
61
+ try {
62
+ onProgress?.(10);
63
+
64
+ const base64 = cleanBase64(request.imageBase64);
65
+ onProgress?.(30);
66
+
67
+ const input = buildInput(base64, request.options);
68
+ onProgress?.(40);
69
+
70
+ const result = await provider.run(model, input);
71
+ onProgress?.(90);
72
+
73
+ const extractor = extractResult || defaultExtractResult;
74
+ const imageUrl = extractor(result);
75
+ onProgress?.(100);
76
+
77
+ if (!imageUrl) {
78
+ return { success: false, error: "No image in response" };
79
+ }
80
+
81
+ return { success: true, imageUrl };
82
+ } catch (error) {
83
+ const message = error instanceof Error ? error.message : String(error);
84
+ if (__DEV__) {
85
+ // eslint-disable-next-line no-console
86
+ console.error("[RemoveBackground] Error:", message);
87
+ }
88
+ return { success: false, error: message };
89
+ }
90
+ }
91
+
92
+ export function hasRemoveBackgroundSupport(): boolean {
93
+ const provider = providerRegistry.getActiveProvider();
94
+ return provider !== null && provider.isInitialized();
95
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Remove Background Presentation Hooks Index
3
+ */
4
+
5
+ export { useRemoveBackgroundFeature } from "./useRemoveBackgroundFeature";
6
+ export type {
7
+ UseRemoveBackgroundFeatureProps,
8
+ UseRemoveBackgroundFeatureReturn,
9
+ } from "./useRemoveBackgroundFeature";