@umituz/react-native-ai-feature-background 1.0.0
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/README.md +152 -0
- package/package.json +50 -0
- package/src/domain/entities/background.types.ts +47 -0
- package/src/domain/entities/component.types.ts +76 -0
- package/src/domain/entities/config.types.ts +31 -0
- package/src/domain/entities/index.ts +27 -0
- package/src/index.ts +65 -0
- package/src/infrastructure/constants/index.ts +5 -0
- package/src/infrastructure/constants/prompts.constants.ts +15 -0
- package/src/presentation/components/BackgroundFeature.tsx +145 -0
- package/src/presentation/components/ErrorDisplay.tsx +58 -0
- package/src/presentation/components/FeatureHeader.tsx +80 -0
- package/src/presentation/components/GenerateButton.tsx +86 -0
- package/src/presentation/components/ImagePicker.tsx +136 -0
- package/src/presentation/components/ProcessingModal.tsx +113 -0
- package/src/presentation/components/PromptInput.tsx +142 -0
- package/src/presentation/components/ResultDisplay.tsx +123 -0
- package/src/presentation/components/index.ts +14 -0
- package/src/presentation/hooks/index.ts +7 -0
- package/src/presentation/hooks/useBackgroundFeature.ts +111 -0
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# @umituz/react-native-ai-feature-background
|
|
2
|
+
|
|
3
|
+
AI-powered background replacement and removal feature for React Native applications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🖼️ **Background Replacement** - Replace image backgrounds with AI-generated content
|
|
8
|
+
- ✂️ **Background Removal** - Remove backgrounds from images
|
|
9
|
+
- 🎨 **Customizable UI** - Theme-aware components using design system
|
|
10
|
+
- 🌐 **Localization Support** - Multi-language support via localization package
|
|
11
|
+
- ⚡ **Flexible Architecture** - Configurable services for different AI providers
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @umituz/react-native-ai-feature-background
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Peer Dependencies
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @umituz/react-native-design-system @umituz/react-native-localization
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Basic Usage with Feature Component
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { BackgroundFeature } from '@umituz/react-native-ai-feature-background';
|
|
31
|
+
|
|
32
|
+
function App() {
|
|
33
|
+
return (
|
|
34
|
+
<BackgroundFeature
|
|
35
|
+
config={{
|
|
36
|
+
onProcess: async (imageUri, prompt) => {
|
|
37
|
+
// Your AI processing logic here
|
|
38
|
+
const result = await yourAIService.replaceBackground(imageUri, prompt);
|
|
39
|
+
return { success: true, imageUrl: result.url };
|
|
40
|
+
},
|
|
41
|
+
onSave: async (imageUrl) => {
|
|
42
|
+
await saveToGallery(imageUrl);
|
|
43
|
+
},
|
|
44
|
+
}}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Using Individual Components
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
import {
|
|
54
|
+
ImagePicker,
|
|
55
|
+
PromptInput,
|
|
56
|
+
GenerateButton,
|
|
57
|
+
ResultDisplay,
|
|
58
|
+
ErrorDisplay,
|
|
59
|
+
} from '@umituz/react-native-ai-feature-background';
|
|
60
|
+
|
|
61
|
+
function CustomFeature() {
|
|
62
|
+
const [imageUri, setImageUri] = useState<string | null>(null);
|
|
63
|
+
const [prompt, setPrompt] = useState('');
|
|
64
|
+
const [result, setResult] = useState<string | null>(null);
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<View>
|
|
68
|
+
<ImagePicker
|
|
69
|
+
imageUri={imageUri}
|
|
70
|
+
onSelectImage={handleSelectImage}
|
|
71
|
+
isProcessing={false}
|
|
72
|
+
/>
|
|
73
|
+
<PromptInput
|
|
74
|
+
value={prompt}
|
|
75
|
+
onChangeText={setPrompt}
|
|
76
|
+
samplePrompts={['Beach sunset', 'Mountain view']}
|
|
77
|
+
/>
|
|
78
|
+
<GenerateButton
|
|
79
|
+
isDisabled={!imageUri || !prompt}
|
|
80
|
+
onPress={handleGenerate}
|
|
81
|
+
/>
|
|
82
|
+
<ResultDisplay
|
|
83
|
+
imageUrl={result}
|
|
84
|
+
onSave={handleSave}
|
|
85
|
+
onReset={handleReset}
|
|
86
|
+
/>
|
|
87
|
+
</View>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Using the Hook
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
import { useBackgroundFeature } from '@umituz/react-native-ai-feature-background';
|
|
96
|
+
|
|
97
|
+
function FeatureScreen() {
|
|
98
|
+
const feature = useBackgroundFeature({
|
|
99
|
+
processRequest: async ({ imageUri, prompt }) => {
|
|
100
|
+
return await myAIService.process(imageUri, prompt);
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<View>
|
|
106
|
+
<Button onPress={feature.selectImage} title="Select Image" />
|
|
107
|
+
<Button onPress={() => feature.process('beach sunset')} title="Process" />
|
|
108
|
+
{feature.processedUrl && (
|
|
109
|
+
<Image source={{ uri: feature.processedUrl }} />
|
|
110
|
+
)}
|
|
111
|
+
</View>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## API Reference
|
|
117
|
+
|
|
118
|
+
### Components
|
|
119
|
+
|
|
120
|
+
#### `BackgroundFeature`
|
|
121
|
+
Main feature component that composes all sub-components.
|
|
122
|
+
|
|
123
|
+
#### `ImagePicker`
|
|
124
|
+
Image selection component with camera/gallery support.
|
|
125
|
+
|
|
126
|
+
#### `PromptInput`
|
|
127
|
+
Text input with sample prompt chips.
|
|
128
|
+
|
|
129
|
+
#### `GenerateButton`
|
|
130
|
+
Action button to trigger processing.
|
|
131
|
+
|
|
132
|
+
#### `ResultDisplay`
|
|
133
|
+
Displays processed image with save/reset actions.
|
|
134
|
+
|
|
135
|
+
#### `ErrorDisplay`
|
|
136
|
+
Error message display component.
|
|
137
|
+
|
|
138
|
+
#### `ProcessingModal`
|
|
139
|
+
Modal shown during processing.
|
|
140
|
+
|
|
141
|
+
### Hooks
|
|
142
|
+
|
|
143
|
+
#### `useBackgroundFeature`
|
|
144
|
+
Main hook for background feature state and actions.
|
|
145
|
+
|
|
146
|
+
### Types
|
|
147
|
+
|
|
148
|
+
See `src/domain/entities` for full type definitions.
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@umituz/react-native-ai-feature-background",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "AI-powered background replacement and removal feature for React Native applications",
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"types": "./src/index.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"typecheck": "tsc --noEmit",
|
|
9
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
10
|
+
"version:patch": "npm version patch -m 'chore: release v%s'",
|
|
11
|
+
"version:minor": "npm version minor -m 'chore: release v%s'",
|
|
12
|
+
"version:major": "npm version major -m 'chore: release v%s'"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"react-native",
|
|
16
|
+
"ai",
|
|
17
|
+
"background",
|
|
18
|
+
"image-processing",
|
|
19
|
+
"background-replacement",
|
|
20
|
+
"background-removal"
|
|
21
|
+
],
|
|
22
|
+
"author": "umituz",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/umituz/react-native-ai-feature-background"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=18.2.0",
|
|
30
|
+
"react-native": ">=0.74.0",
|
|
31
|
+
"@umituz/react-native-design-system": ">=1.0.0",
|
|
32
|
+
"@umituz/react-native-localization": ">=1.0.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/react": "~19.1.10",
|
|
36
|
+
"@umituz/react-native-design-system": "latest",
|
|
37
|
+
"@umituz/react-native-localization": "latest",
|
|
38
|
+
"react": "19.1.0",
|
|
39
|
+
"react-native": "0.81.5",
|
|
40
|
+
"typescript": "~5.9.2"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"src",
|
|
47
|
+
"README.md",
|
|
48
|
+
"LICENSE"
|
|
49
|
+
]
|
|
50
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background Feature Types
|
|
3
|
+
* @description Core type definitions for background feature
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Background processing request input
|
|
8
|
+
*/
|
|
9
|
+
export interface BackgroundProcessRequest {
|
|
10
|
+
readonly imageUri: string;
|
|
11
|
+
readonly prompt?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Background processing result
|
|
16
|
+
*/
|
|
17
|
+
export interface BackgroundProcessResult {
|
|
18
|
+
readonly success: boolean;
|
|
19
|
+
readonly imageUrl?: string;
|
|
20
|
+
readonly error?: string;
|
|
21
|
+
readonly requestId?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Background feature state
|
|
26
|
+
*/
|
|
27
|
+
export interface BackgroundFeatureState {
|
|
28
|
+
readonly imageUri: string | null;
|
|
29
|
+
readonly prompt: string;
|
|
30
|
+
readonly processedUrl: string | null;
|
|
31
|
+
readonly isProcessing: boolean;
|
|
32
|
+
readonly progress: number;
|
|
33
|
+
readonly error: string | null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Sample prompt configuration
|
|
38
|
+
*/
|
|
39
|
+
export interface SamplePrompt {
|
|
40
|
+
readonly id: string;
|
|
41
|
+
readonly text: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Background feature mode
|
|
46
|
+
*/
|
|
47
|
+
export type BackgroundFeatureMode = "replace" | "remove";
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component Props Types
|
|
3
|
+
* @description Props definitions for background feature components
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ImageSourcePropType } from "react-native";
|
|
7
|
+
import type { SamplePrompt } from "./background.types";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Image picker component props
|
|
11
|
+
*/
|
|
12
|
+
export interface ImagePickerProps {
|
|
13
|
+
readonly imageUri: string | null;
|
|
14
|
+
readonly isProcessing: boolean;
|
|
15
|
+
readonly onSelectImage: () => void;
|
|
16
|
+
readonly placeholderText?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Prompt input component props
|
|
21
|
+
*/
|
|
22
|
+
export interface PromptInputProps {
|
|
23
|
+
readonly value: string;
|
|
24
|
+
readonly onChangeText: (text: string) => void;
|
|
25
|
+
readonly isProcessing: boolean;
|
|
26
|
+
readonly label?: string;
|
|
27
|
+
readonly placeholder?: string;
|
|
28
|
+
readonly samplePrompts?: readonly SamplePrompt[];
|
|
29
|
+
readonly samplePromptsLabel?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Generate button component props
|
|
34
|
+
*/
|
|
35
|
+
export interface GenerateButtonProps {
|
|
36
|
+
readonly isDisabled: boolean;
|
|
37
|
+
readonly isProcessing: boolean;
|
|
38
|
+
readonly onPress: () => void;
|
|
39
|
+
readonly buttonText?: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Result display component props
|
|
44
|
+
*/
|
|
45
|
+
export interface ResultDisplayProps {
|
|
46
|
+
readonly imageUrl: string | null;
|
|
47
|
+
readonly isProcessing: boolean;
|
|
48
|
+
readonly onSave: () => void;
|
|
49
|
+
readonly onReset: () => void;
|
|
50
|
+
readonly saveButtonText?: string;
|
|
51
|
+
readonly resetButtonText?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Error display component props
|
|
56
|
+
*/
|
|
57
|
+
export interface ErrorDisplayProps {
|
|
58
|
+
readonly error: string | null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Processing modal component props
|
|
63
|
+
*/
|
|
64
|
+
export interface ProcessingModalProps {
|
|
65
|
+
readonly visible: boolean;
|
|
66
|
+
readonly progress?: number;
|
|
67
|
+
readonly title?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Feature header component props
|
|
72
|
+
*/
|
|
73
|
+
export interface FeatureHeaderProps {
|
|
74
|
+
readonly heroImage?: ImageSourcePropType;
|
|
75
|
+
readonly description?: string;
|
|
76
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Types
|
|
3
|
+
* @description Configuration interfaces for background feature
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { BackgroundProcessRequest, BackgroundProcessResult } from "./background.types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Process request callback parameters
|
|
10
|
+
*/
|
|
11
|
+
export interface ProcessRequestParams extends BackgroundProcessRequest {
|
|
12
|
+
readonly onProgress?: (progress: number) => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Background feature configuration
|
|
17
|
+
*/
|
|
18
|
+
export interface BackgroundFeatureConfig {
|
|
19
|
+
readonly onProcess: (params: ProcessRequestParams) => Promise<BackgroundProcessResult>;
|
|
20
|
+
readonly onSave?: (imageUrl: string) => Promise<void>;
|
|
21
|
+
readonly onError?: (error: Error) => void;
|
|
22
|
+
readonly onSuccess?: (result: BackgroundProcessResult) => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Hook configuration
|
|
27
|
+
*/
|
|
28
|
+
export interface UseBackgroundFeatureConfig {
|
|
29
|
+
readonly processRequest: (params: ProcessRequestParams) => Promise<BackgroundProcessResult>;
|
|
30
|
+
readonly onSelectImage?: () => Promise<string | null>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain Entities Export
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
BackgroundProcessRequest,
|
|
7
|
+
BackgroundProcessResult,
|
|
8
|
+
BackgroundFeatureState,
|
|
9
|
+
SamplePrompt,
|
|
10
|
+
BackgroundFeatureMode,
|
|
11
|
+
} from "./background.types";
|
|
12
|
+
|
|
13
|
+
export type {
|
|
14
|
+
ImagePickerProps,
|
|
15
|
+
PromptInputProps,
|
|
16
|
+
GenerateButtonProps,
|
|
17
|
+
ResultDisplayProps,
|
|
18
|
+
ErrorDisplayProps,
|
|
19
|
+
ProcessingModalProps,
|
|
20
|
+
FeatureHeaderProps,
|
|
21
|
+
} from "./component.types";
|
|
22
|
+
|
|
23
|
+
export type {
|
|
24
|
+
ProcessRequestParams,
|
|
25
|
+
BackgroundFeatureConfig,
|
|
26
|
+
UseBackgroundFeatureConfig,
|
|
27
|
+
} from "./config.types";
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @umituz/react-native-ai-feature-background
|
|
3
|
+
* AI-powered background replacement and removal feature for React Native
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* import {
|
|
7
|
+
* BackgroundFeature,
|
|
8
|
+
* useBackgroundFeature,
|
|
9
|
+
* ImagePicker,
|
|
10
|
+
* PromptInput,
|
|
11
|
+
* } from '@umituz/react-native-ai-feature-background';
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// DOMAIN LAYER - Types & Interfaces
|
|
16
|
+
// =============================================================================
|
|
17
|
+
|
|
18
|
+
export type {
|
|
19
|
+
BackgroundProcessRequest,
|
|
20
|
+
BackgroundProcessResult,
|
|
21
|
+
BackgroundFeatureState,
|
|
22
|
+
SamplePrompt,
|
|
23
|
+
BackgroundFeatureMode,
|
|
24
|
+
ImagePickerProps,
|
|
25
|
+
PromptInputProps,
|
|
26
|
+
GenerateButtonProps,
|
|
27
|
+
ResultDisplayProps,
|
|
28
|
+
ErrorDisplayProps,
|
|
29
|
+
ProcessingModalProps,
|
|
30
|
+
FeatureHeaderProps,
|
|
31
|
+
ProcessRequestParams,
|
|
32
|
+
BackgroundFeatureConfig,
|
|
33
|
+
UseBackgroundFeatureConfig,
|
|
34
|
+
} from "./domain/entities";
|
|
35
|
+
|
|
36
|
+
// =============================================================================
|
|
37
|
+
// INFRASTRUCTURE LAYER - Constants
|
|
38
|
+
// =============================================================================
|
|
39
|
+
|
|
40
|
+
export { DEFAULT_SAMPLE_PROMPTS } from "./infrastructure/constants";
|
|
41
|
+
|
|
42
|
+
// =============================================================================
|
|
43
|
+
// PRESENTATION LAYER - Components
|
|
44
|
+
// =============================================================================
|
|
45
|
+
|
|
46
|
+
export {
|
|
47
|
+
BackgroundFeature,
|
|
48
|
+
ImagePicker,
|
|
49
|
+
PromptInput,
|
|
50
|
+
GenerateButton,
|
|
51
|
+
ResultDisplay,
|
|
52
|
+
ErrorDisplay,
|
|
53
|
+
ProcessingModal,
|
|
54
|
+
FeatureHeader,
|
|
55
|
+
} from "./presentation/components";
|
|
56
|
+
|
|
57
|
+
export type { BackgroundFeatureProps } from "./presentation/components";
|
|
58
|
+
|
|
59
|
+
// =============================================================================
|
|
60
|
+
// PRESENTATION LAYER - Hooks
|
|
61
|
+
// =============================================================================
|
|
62
|
+
|
|
63
|
+
export { useBackgroundFeature } from "./presentation/hooks";
|
|
64
|
+
|
|
65
|
+
export type { UseBackgroundFeatureReturn } from "./presentation/hooks";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default Sample Prompts
|
|
3
|
+
* @description Default prompt suggestions for background replacement
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { SamplePrompt } from "../../domain/entities";
|
|
7
|
+
|
|
8
|
+
export const DEFAULT_SAMPLE_PROMPTS: readonly SamplePrompt[] = [
|
|
9
|
+
{ id: "beach", text: "Beach sunset with palm trees" },
|
|
10
|
+
{ id: "office", text: "Modern office with city view" },
|
|
11
|
+
{ id: "mountain", text: "Mountain landscape with snow" },
|
|
12
|
+
{ id: "living-room", text: "Cozy living room interior" },
|
|
13
|
+
{ id: "garden", text: "Japanese garden with cherry blossoms" },
|
|
14
|
+
{ id: "cityscape", text: "Futuristic cityscape at night" },
|
|
15
|
+
] as const;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background Feature Component
|
|
3
|
+
* @description Main feature component composing all sub-components
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { useCallback, useState } from "react";
|
|
7
|
+
import { ScrollView, StyleSheet } from "react-native";
|
|
8
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
9
|
+
import type {
|
|
10
|
+
BackgroundFeatureConfig,
|
|
11
|
+
SamplePrompt,
|
|
12
|
+
} from "../../domain/entities";
|
|
13
|
+
import { ImagePicker } from "./ImagePicker";
|
|
14
|
+
import { PromptInput } from "./PromptInput";
|
|
15
|
+
import { GenerateButton } from "./GenerateButton";
|
|
16
|
+
import { ResultDisplay } from "./ResultDisplay";
|
|
17
|
+
import { ErrorDisplay } from "./ErrorDisplay";
|
|
18
|
+
import { ProcessingModal } from "./ProcessingModal";
|
|
19
|
+
import { FeatureHeader } from "./FeatureHeader";
|
|
20
|
+
import { useBackgroundFeature } from "../hooks";
|
|
21
|
+
import type { ImageSourcePropType } from "react-native";
|
|
22
|
+
|
|
23
|
+
export interface BackgroundFeatureProps {
|
|
24
|
+
readonly config: BackgroundFeatureConfig;
|
|
25
|
+
readonly onSelectImage: () => Promise<string | null>;
|
|
26
|
+
readonly heroImage?: ImageSourcePropType;
|
|
27
|
+
readonly description?: string;
|
|
28
|
+
readonly promptLabel?: string;
|
|
29
|
+
readonly promptPlaceholder?: string;
|
|
30
|
+
readonly samplePrompts?: readonly SamplePrompt[];
|
|
31
|
+
readonly samplePromptsLabel?: string;
|
|
32
|
+
readonly generateButtonText?: string;
|
|
33
|
+
readonly saveButtonText?: string;
|
|
34
|
+
readonly resetButtonText?: string;
|
|
35
|
+
readonly processingText?: string;
|
|
36
|
+
readonly placeholderText?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const BackgroundFeature: React.FC<BackgroundFeatureProps> = ({
|
|
40
|
+
config,
|
|
41
|
+
onSelectImage,
|
|
42
|
+
heroImage,
|
|
43
|
+
description,
|
|
44
|
+
promptLabel,
|
|
45
|
+
promptPlaceholder,
|
|
46
|
+
samplePrompts,
|
|
47
|
+
samplePromptsLabel,
|
|
48
|
+
generateButtonText,
|
|
49
|
+
saveButtonText,
|
|
50
|
+
resetButtonText,
|
|
51
|
+
processingText,
|
|
52
|
+
placeholderText,
|
|
53
|
+
}) => {
|
|
54
|
+
const tokens = useAppDesignTokens();
|
|
55
|
+
const [prompt, setPrompt] = useState("");
|
|
56
|
+
|
|
57
|
+
const feature = useBackgroundFeature({
|
|
58
|
+
processRequest: config.onProcess,
|
|
59
|
+
onSelectImage,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const handleProcess = useCallback(async () => {
|
|
63
|
+
await feature.process(prompt);
|
|
64
|
+
if (feature.processedUrl && config.onSuccess) {
|
|
65
|
+
config.onSuccess({
|
|
66
|
+
success: true,
|
|
67
|
+
imageUrl: feature.processedUrl,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}, [feature, prompt, config]);
|
|
71
|
+
|
|
72
|
+
const handleSave = useCallback(async () => {
|
|
73
|
+
if (feature.processedUrl && config.onSave) {
|
|
74
|
+
await config.onSave(feature.processedUrl);
|
|
75
|
+
}
|
|
76
|
+
}, [feature.processedUrl, config]);
|
|
77
|
+
|
|
78
|
+
const handleReset = useCallback(() => {
|
|
79
|
+
feature.reset();
|
|
80
|
+
setPrompt("");
|
|
81
|
+
}, [feature]);
|
|
82
|
+
|
|
83
|
+
const isDisabled = !feature.imageUri || !prompt.trim();
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<>
|
|
87
|
+
<ScrollView
|
|
88
|
+
style={[styles.container, { padding: tokens.spacing.lg }]}
|
|
89
|
+
showsVerticalScrollIndicator={false}
|
|
90
|
+
>
|
|
91
|
+
<FeatureHeader
|
|
92
|
+
heroImage={heroImage}
|
|
93
|
+
description={description}
|
|
94
|
+
/>
|
|
95
|
+
|
|
96
|
+
<ImagePicker
|
|
97
|
+
imageUri={feature.imageUri}
|
|
98
|
+
isProcessing={feature.isProcessing}
|
|
99
|
+
onSelectImage={feature.selectImage}
|
|
100
|
+
placeholderText={placeholderText}
|
|
101
|
+
/>
|
|
102
|
+
|
|
103
|
+
<PromptInput
|
|
104
|
+
value={prompt}
|
|
105
|
+
onChangeText={setPrompt}
|
|
106
|
+
isProcessing={feature.isProcessing}
|
|
107
|
+
label={promptLabel}
|
|
108
|
+
placeholder={promptPlaceholder}
|
|
109
|
+
samplePrompts={samplePrompts}
|
|
110
|
+
samplePromptsLabel={samplePromptsLabel}
|
|
111
|
+
/>
|
|
112
|
+
|
|
113
|
+
<ErrorDisplay error={feature.error} />
|
|
114
|
+
|
|
115
|
+
<ResultDisplay
|
|
116
|
+
imageUrl={feature.processedUrl}
|
|
117
|
+
isProcessing={feature.isProcessing}
|
|
118
|
+
onSave={handleSave}
|
|
119
|
+
onReset={handleReset}
|
|
120
|
+
saveButtonText={saveButtonText}
|
|
121
|
+
resetButtonText={resetButtonText}
|
|
122
|
+
/>
|
|
123
|
+
|
|
124
|
+
<GenerateButton
|
|
125
|
+
isDisabled={isDisabled}
|
|
126
|
+
isProcessing={feature.isProcessing}
|
|
127
|
+
onPress={handleProcess}
|
|
128
|
+
buttonText={generateButtonText}
|
|
129
|
+
/>
|
|
130
|
+
</ScrollView>
|
|
131
|
+
|
|
132
|
+
<ProcessingModal
|
|
133
|
+
visible={feature.isProcessing}
|
|
134
|
+
progress={feature.progress}
|
|
135
|
+
title={processingText}
|
|
136
|
+
/>
|
|
137
|
+
</>
|
|
138
|
+
);
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const styles = StyleSheet.create({
|
|
142
|
+
container: {
|
|
143
|
+
flex: 1,
|
|
144
|
+
},
|
|
145
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Display Component
|
|
3
|
+
* @description Displays error messages
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { memo } from "react";
|
|
7
|
+
import { View, StyleSheet } from "react-native";
|
|
8
|
+
import {
|
|
9
|
+
AtomicText,
|
|
10
|
+
AtomicIcon,
|
|
11
|
+
useAppDesignTokens,
|
|
12
|
+
} from "@umituz/react-native-design-system";
|
|
13
|
+
import type { ErrorDisplayProps } from "../../domain/entities";
|
|
14
|
+
|
|
15
|
+
export const ErrorDisplay: React.FC<ErrorDisplayProps> = memo(
|
|
16
|
+
function ErrorDisplay({ error }) {
|
|
17
|
+
const tokens = useAppDesignTokens();
|
|
18
|
+
|
|
19
|
+
if (!error) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<View
|
|
25
|
+
style={[
|
|
26
|
+
styles.container,
|
|
27
|
+
{ backgroundColor: tokens.colors.errorContainer },
|
|
28
|
+
]}
|
|
29
|
+
>
|
|
30
|
+
<AtomicIcon
|
|
31
|
+
name="alert-circle"
|
|
32
|
+
size={20}
|
|
33
|
+
color="error"
|
|
34
|
+
/>
|
|
35
|
+
<AtomicText
|
|
36
|
+
type="bodyMedium"
|
|
37
|
+
style={[styles.errorText, { color: tokens.colors.error }]}
|
|
38
|
+
>
|
|
39
|
+
{error}
|
|
40
|
+
</AtomicText>
|
|
41
|
+
</View>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const styles = StyleSheet.create({
|
|
47
|
+
container: {
|
|
48
|
+
flexDirection: "row",
|
|
49
|
+
alignItems: "center",
|
|
50
|
+
gap: 12,
|
|
51
|
+
padding: 16,
|
|
52
|
+
borderRadius: 12,
|
|
53
|
+
marginVertical: 12,
|
|
54
|
+
},
|
|
55
|
+
errorText: {
|
|
56
|
+
flex: 1,
|
|
57
|
+
},
|
|
58
|
+
});
|