@umituz/react-native-ai-generation-content 1.12.3 → 1.12.5
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 +30 -6
- package/src/domains/content-moderation/domain/entities/moderation.types.ts +84 -0
- package/src/domains/content-moderation/domain/interfaces/content-filter.interface.ts +24 -0
- package/src/domains/content-moderation/index.ts +67 -0
- package/src/domains/content-moderation/infrastructure/rules/default-rules.data.ts +144 -0
- package/src/domains/content-moderation/infrastructure/rules/rules-registry.ts +75 -0
- package/src/domains/content-moderation/infrastructure/services/content-moderation.service.ts +150 -0
- package/src/domains/content-moderation/infrastructure/services/index.ts +8 -0
- package/src/domains/content-moderation/infrastructure/services/moderators/base.moderator.ts +62 -0
- package/src/domains/content-moderation/infrastructure/services/moderators/image.moderator.ts +64 -0
- package/src/domains/content-moderation/infrastructure/services/moderators/index.ts +10 -0
- package/src/domains/content-moderation/infrastructure/services/moderators/text.moderator.ts +144 -0
- package/src/domains/content-moderation/infrastructure/services/moderators/video.moderator.ts +64 -0
- package/src/domains/content-moderation/infrastructure/services/moderators/voice.moderator.ts +74 -0
- package/src/domains/content-moderation/infrastructure/services/pattern-matcher.service.ts +51 -0
- package/src/domains/content-moderation/presentation/exceptions/content-policy-violation.exception.ts +48 -0
- package/src/domains/creations/application/services/CreationsService.ts +71 -0
- package/src/domains/creations/domain/entities/Creation.ts +51 -0
- package/src/domains/creations/domain/entities/index.ts +6 -0
- package/src/domains/creations/domain/repositories/ICreationsRepository.ts +23 -0
- package/src/domains/creations/domain/repositories/index.ts +5 -0
- package/src/domains/creations/domain/services/ICreationsStorageService.ts +13 -0
- package/src/domains/creations/domain/value-objects/CreationsConfig.ts +76 -0
- package/src/domains/creations/domain/value-objects/index.ts +12 -0
- package/src/domains/creations/index.ts +84 -0
- package/src/domains/creations/infrastructure/adapters/createRepository.ts +54 -0
- package/src/domains/creations/infrastructure/adapters/index.ts +5 -0
- package/src/domains/creations/infrastructure/repositories/CreationsRepository.ts +233 -0
- package/src/domains/creations/infrastructure/repositories/index.ts +8 -0
- package/src/domains/creations/infrastructure/services/CreationsStorageService.ts +48 -0
- package/src/domains/creations/presentation/components/CreationCard.tsx +136 -0
- package/src/domains/creations/presentation/components/CreationDetail/DetailActions.tsx +76 -0
- package/src/domains/creations/presentation/components/CreationDetail/DetailHeader.tsx +81 -0
- package/src/domains/creations/presentation/components/CreationDetail/DetailImage.tsx +41 -0
- package/src/domains/creations/presentation/components/CreationDetail/DetailStory.tsx +67 -0
- package/src/domains/creations/presentation/components/CreationDetail/index.ts +4 -0
- package/src/domains/creations/presentation/components/CreationImageViewer.tsx +43 -0
- package/src/domains/creations/presentation/components/CreationThumbnail.tsx +63 -0
- package/src/domains/creations/presentation/components/CreationsGrid.tsx +75 -0
- package/src/domains/creations/presentation/components/CreationsHomeCard.tsx +176 -0
- package/src/domains/creations/presentation/components/EmptyState.tsx +75 -0
- package/src/domains/creations/presentation/components/FilterBottomSheet.tsx +158 -0
- package/src/domains/creations/presentation/components/FilterChips.tsx +105 -0
- package/src/domains/creations/presentation/components/GalleryHeader.tsx +106 -0
- package/src/domains/creations/presentation/components/index.ts +19 -0
- package/src/domains/creations/presentation/hooks/index.ts +7 -0
- package/src/domains/creations/presentation/hooks/useCreations.ts +33 -0
- package/src/domains/creations/presentation/hooks/useCreationsFilter.ts +70 -0
- package/src/domains/creations/presentation/hooks/useDeleteCreation.ts +51 -0
- package/src/domains/creations/presentation/screens/CreationDetailScreen.tsx +71 -0
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +217 -0
- package/src/domains/creations/presentation/screens/index.ts +5 -0
- package/src/domains/creations/presentation/utils/filterUtils.ts +52 -0
- package/src/domains/creations/types.d.ts +107 -0
- package/src/domains/face-detection/domain/constants/faceDetectionConstants.ts +16 -0
- package/src/domains/face-detection/domain/entities/FaceDetection.ts +19 -0
- package/src/domains/face-detection/index.ts +26 -0
- package/src/domains/face-detection/infrastructure/analyzers/faceAnalyzer.ts +36 -0
- package/src/domains/face-detection/infrastructure/validators/faceValidator.ts +52 -0
- package/src/domains/face-detection/presentation/components/FaceValidationStatus.tsx +111 -0
- package/src/domains/face-detection/presentation/hooks/useFaceDetection.ts +58 -0
- package/src/domains/feature-background/domain/entities/background.types.ts +77 -0
- package/src/domains/feature-background/domain/entities/component.types.ts +96 -0
- package/src/domains/feature-background/domain/entities/config.types.ts +41 -0
- package/src/domains/feature-background/domain/entities/index.ts +31 -0
- package/src/domains/feature-background/index.ts +72 -0
- package/src/domains/feature-background/infrastructure/constants/index.ts +5 -0
- package/src/domains/feature-background/infrastructure/constants/prompts.constants.ts +15 -0
- package/src/domains/feature-background/presentation/components/BackgroundFeature.tsx +145 -0
- package/src/domains/feature-background/presentation/components/ComparisonSlider.tsx +199 -0
- package/src/domains/feature-background/presentation/components/ErrorDisplay.tsx +58 -0
- package/src/domains/feature-background/presentation/components/FeatureHeader.tsx +80 -0
- package/src/domains/feature-background/presentation/components/GenerateButton.tsx +86 -0
- package/src/domains/feature-background/presentation/components/ImagePicker.tsx +136 -0
- package/src/domains/feature-background/presentation/components/ModeSelector.tsx +78 -0
- package/src/domains/feature-background/presentation/components/ProcessingModal.tsx +113 -0
- package/src/domains/feature-background/presentation/components/PromptInput.tsx +142 -0
- package/src/domains/feature-background/presentation/components/ResultDisplay.tsx +123 -0
- package/src/domains/feature-background/presentation/components/index.ts +16 -0
- package/src/domains/feature-background/presentation/hooks/index.ts +7 -0
- package/src/domains/feature-background/presentation/hooks/useBackgroundFeature.ts +118 -0
- package/src/index.ts +24 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FaceValidationStatus Component
|
|
3
|
+
*
|
|
4
|
+
* Displays face validation status with appropriate styling.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from "react";
|
|
8
|
+
import { View, StyleSheet, ActivityIndicator } from "react-native";
|
|
9
|
+
import {
|
|
10
|
+
AtomicText,
|
|
11
|
+
AtomicIcon,
|
|
12
|
+
useAppDesignTokens,
|
|
13
|
+
} from "@umituz/react-native-design-system";
|
|
14
|
+
import { useLocalization } from "@umituz/react-native-localization";
|
|
15
|
+
import type { FaceValidationState } from "../../domain/entities/FaceDetection";
|
|
16
|
+
import { isValidFace } from "../../infrastructure/validators/faceValidator";
|
|
17
|
+
|
|
18
|
+
interface FaceValidationStatusProps {
|
|
19
|
+
state: FaceValidationState;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const FaceValidationStatus: React.FC<FaceValidationStatusProps> = ({
|
|
23
|
+
state,
|
|
24
|
+
}) => {
|
|
25
|
+
const tokens = useAppDesignTokens();
|
|
26
|
+
const { t } = useLocalization();
|
|
27
|
+
|
|
28
|
+
if (state.isValidating) {
|
|
29
|
+
return (
|
|
30
|
+
<View
|
|
31
|
+
style={[styles.container, { backgroundColor: tokens.colors.surface }]}
|
|
32
|
+
>
|
|
33
|
+
<ActivityIndicator size="small" color={tokens.colors.primary} />
|
|
34
|
+
<AtomicText
|
|
35
|
+
style={[styles.text, { color: tokens.colors.textSecondary }]}
|
|
36
|
+
>
|
|
37
|
+
{t("faceDetection.analyzing")}
|
|
38
|
+
</AtomicText>
|
|
39
|
+
</View>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (state.error) {
|
|
44
|
+
return (
|
|
45
|
+
<View
|
|
46
|
+
style={[
|
|
47
|
+
styles.container,
|
|
48
|
+
{ backgroundColor: tokens.colors.errorContainer },
|
|
49
|
+
]}
|
|
50
|
+
>
|
|
51
|
+
<AtomicIcon
|
|
52
|
+
name="alert-circle"
|
|
53
|
+
size={16}
|
|
54
|
+
customColor={tokens.colors.error}
|
|
55
|
+
/>
|
|
56
|
+
<AtomicText style={[styles.text, { color: tokens.colors.error }]}>
|
|
57
|
+
{t("faceDetection.error")}
|
|
58
|
+
</AtomicText>
|
|
59
|
+
</View>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!state.result) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const valid = isValidFace(state.result);
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<View
|
|
71
|
+
style={[
|
|
72
|
+
styles.container,
|
|
73
|
+
{
|
|
74
|
+
backgroundColor: valid
|
|
75
|
+
? tokens.colors.successContainer
|
|
76
|
+
: tokens.colors.errorContainer,
|
|
77
|
+
},
|
|
78
|
+
]}
|
|
79
|
+
>
|
|
80
|
+
<AtomicIcon
|
|
81
|
+
name={valid ? "checkmark-circle" : "close-circle"}
|
|
82
|
+
size={16}
|
|
83
|
+
customColor={valid ? tokens.colors.success : tokens.colors.error}
|
|
84
|
+
/>
|
|
85
|
+
<AtomicText
|
|
86
|
+
style={[
|
|
87
|
+
styles.text,
|
|
88
|
+
{ color: valid ? tokens.colors.success : tokens.colors.error },
|
|
89
|
+
]}
|
|
90
|
+
>
|
|
91
|
+
{valid ? t("faceDetection.success") : t("faceDetection.noFace")}
|
|
92
|
+
</AtomicText>
|
|
93
|
+
</View>
|
|
94
|
+
);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const styles = StyleSheet.create({
|
|
98
|
+
container: {
|
|
99
|
+
flexDirection: "row",
|
|
100
|
+
alignItems: "center",
|
|
101
|
+
paddingHorizontal: 12,
|
|
102
|
+
paddingVertical: 6,
|
|
103
|
+
borderRadius: 8,
|
|
104
|
+
gap: 6,
|
|
105
|
+
marginTop: 8,
|
|
106
|
+
},
|
|
107
|
+
text: {
|
|
108
|
+
fontSize: 12,
|
|
109
|
+
fontWeight: "500",
|
|
110
|
+
},
|
|
111
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useFaceDetection Hook
|
|
3
|
+
*
|
|
4
|
+
* React hook for face detection functionality.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { useState, useCallback } from "react";
|
|
8
|
+
import type {
|
|
9
|
+
FaceValidationState,
|
|
10
|
+
FaceDetectionResult,
|
|
11
|
+
} from "../../domain/entities/FaceDetection";
|
|
12
|
+
import { analyzeImageForFace } from "../../infrastructure/analyzers/faceAnalyzer";
|
|
13
|
+
import { isValidFace } from "../../infrastructure/validators/faceValidator";
|
|
14
|
+
|
|
15
|
+
interface UseFaceDetectionReturn {
|
|
16
|
+
state: FaceValidationState;
|
|
17
|
+
validateImage: (base64Image: string) => Promise<FaceDetectionResult>;
|
|
18
|
+
isValid: boolean;
|
|
19
|
+
reset: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const initialState: FaceValidationState = {
|
|
23
|
+
isValidating: false,
|
|
24
|
+
result: null,
|
|
25
|
+
error: null,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const useFaceDetection = (): UseFaceDetectionReturn => {
|
|
29
|
+
const [state, setState] = useState<FaceValidationState>(initialState);
|
|
30
|
+
|
|
31
|
+
const validateImage = useCallback(async (base64Image: string) => {
|
|
32
|
+
setState({ isValidating: true, result: null, error: null });
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const result = await analyzeImageForFace(base64Image);
|
|
36
|
+
setState({ isValidating: false, result, error: null });
|
|
37
|
+
return result;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
const message =
|
|
40
|
+
error instanceof Error ? error.message : "Validation failed";
|
|
41
|
+
setState({ isValidating: false, result: null, error: message });
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}, []);
|
|
45
|
+
|
|
46
|
+
const reset = useCallback(() => {
|
|
47
|
+
setState(initialState);
|
|
48
|
+
}, []);
|
|
49
|
+
|
|
50
|
+
const isValid = state.result ? isValidFace(state.result) : false;
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
state,
|
|
54
|
+
validateImage,
|
|
55
|
+
isValid,
|
|
56
|
+
reset,
|
|
57
|
+
};
|
|
58
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Background Feature Types
|
|
3
|
+
* @description Core type definitions for background feature
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Studio mode for background operations
|
|
8
|
+
*/
|
|
9
|
+
export type StudioMode =
|
|
10
|
+
| "transparent"
|
|
11
|
+
| "remove-object"
|
|
12
|
+
| "replace-object"
|
|
13
|
+
| "relight"
|
|
14
|
+
| "creative-scene"
|
|
15
|
+
| "enhance"
|
|
16
|
+
| "clean-white"
|
|
17
|
+
| "portrait-blur";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Background processing request input
|
|
21
|
+
*/
|
|
22
|
+
export interface BackgroundProcessRequest {
|
|
23
|
+
readonly imageUri: string;
|
|
24
|
+
readonly prompt?: string;
|
|
25
|
+
readonly mode?: StudioMode;
|
|
26
|
+
readonly mask?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Background processing result
|
|
31
|
+
*/
|
|
32
|
+
export interface BackgroundProcessResult {
|
|
33
|
+
readonly success: boolean;
|
|
34
|
+
readonly imageUrl?: string;
|
|
35
|
+
readonly error?: string;
|
|
36
|
+
readonly requestId?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Background feature state
|
|
41
|
+
*/
|
|
42
|
+
export interface BackgroundFeatureState {
|
|
43
|
+
readonly imageUri: string | null;
|
|
44
|
+
readonly prompt: string;
|
|
45
|
+
readonly processedUrl: string | null;
|
|
46
|
+
readonly isProcessing: boolean;
|
|
47
|
+
readonly progress: number;
|
|
48
|
+
readonly error: string | null;
|
|
49
|
+
readonly mode: StudioMode;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Sample prompt configuration
|
|
54
|
+
*/
|
|
55
|
+
export interface SamplePrompt {
|
|
56
|
+
readonly id: string;
|
|
57
|
+
readonly text: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Studio mode configuration
|
|
62
|
+
*/
|
|
63
|
+
export interface StudioModeConfig {
|
|
64
|
+
readonly id: StudioMode;
|
|
65
|
+
readonly icon: string;
|
|
66
|
+
readonly requiresPrompt?: boolean;
|
|
67
|
+
readonly requiresMask?: boolean;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Comparison view state
|
|
72
|
+
*/
|
|
73
|
+
export interface ComparisonState {
|
|
74
|
+
readonly originalUri: string | null;
|
|
75
|
+
readonly processedUri: string | null;
|
|
76
|
+
readonly position: number;
|
|
77
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
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, StudioMode, StudioModeConfig } 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
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Mode selector component props
|
|
80
|
+
*/
|
|
81
|
+
export interface ModeSelectorProps {
|
|
82
|
+
readonly activeMode: StudioMode;
|
|
83
|
+
readonly onModeChange: (mode: StudioMode) => void;
|
|
84
|
+
readonly isProcessing: boolean;
|
|
85
|
+
readonly modes: readonly StudioModeConfig[];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Comparison slider component props
|
|
90
|
+
*/
|
|
91
|
+
export interface ComparisonSliderProps {
|
|
92
|
+
readonly originalUri: string;
|
|
93
|
+
readonly processedUri: string;
|
|
94
|
+
readonly beforeLabel?: string;
|
|
95
|
+
readonly afterLabel?: string;
|
|
96
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Types
|
|
3
|
+
* @description Configuration interfaces for background feature
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type {
|
|
7
|
+
BackgroundProcessRequest,
|
|
8
|
+
BackgroundProcessResult,
|
|
9
|
+
StudioMode,
|
|
10
|
+
} from "./background.types";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Process request callback parameters
|
|
14
|
+
*/
|
|
15
|
+
export interface ProcessRequestParams extends BackgroundProcessRequest {
|
|
16
|
+
readonly onProgress?: (progress: number) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Background feature configuration
|
|
21
|
+
*/
|
|
22
|
+
export interface BackgroundFeatureConfig {
|
|
23
|
+
readonly onProcess: (
|
|
24
|
+
params: ProcessRequestParams
|
|
25
|
+
) => Promise<BackgroundProcessResult>;
|
|
26
|
+
readonly onSave?: (imageUrl: string) => Promise<void>;
|
|
27
|
+
readonly onError?: (error: Error) => void;
|
|
28
|
+
readonly onSuccess?: (result: BackgroundProcessResult) => void;
|
|
29
|
+
readonly defaultMode?: StudioMode;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Hook configuration
|
|
34
|
+
*/
|
|
35
|
+
export interface UseBackgroundFeatureConfig {
|
|
36
|
+
readonly processRequest: (
|
|
37
|
+
params: ProcessRequestParams
|
|
38
|
+
) => Promise<BackgroundProcessResult>;
|
|
39
|
+
readonly onSelectImage?: () => Promise<string | null>;
|
|
40
|
+
readonly defaultMode?: StudioMode;
|
|
41
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain Entities Export
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
BackgroundProcessRequest,
|
|
7
|
+
BackgroundProcessResult,
|
|
8
|
+
BackgroundFeatureState,
|
|
9
|
+
SamplePrompt,
|
|
10
|
+
StudioMode,
|
|
11
|
+
StudioModeConfig,
|
|
12
|
+
ComparisonState,
|
|
13
|
+
} from "./background.types";
|
|
14
|
+
|
|
15
|
+
export type {
|
|
16
|
+
ImagePickerProps,
|
|
17
|
+
PromptInputProps,
|
|
18
|
+
GenerateButtonProps,
|
|
19
|
+
ResultDisplayProps,
|
|
20
|
+
ErrorDisplayProps,
|
|
21
|
+
ProcessingModalProps,
|
|
22
|
+
FeatureHeaderProps,
|
|
23
|
+
ModeSelectorProps,
|
|
24
|
+
ComparisonSliderProps,
|
|
25
|
+
} from "./component.types";
|
|
26
|
+
|
|
27
|
+
export type {
|
|
28
|
+
ProcessRequestParams,
|
|
29
|
+
BackgroundFeatureConfig,
|
|
30
|
+
UseBackgroundFeatureConfig,
|
|
31
|
+
} from "./config.types";
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
* ComparisonSlider,
|
|
11
|
+
* ModeSelector,
|
|
12
|
+
* } from '@umituz/react-native-ai-feature-background';
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// DOMAIN LAYER - Types & Interfaces
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
export type {
|
|
20
|
+
BackgroundProcessRequest,
|
|
21
|
+
BackgroundProcessResult,
|
|
22
|
+
BackgroundFeatureState,
|
|
23
|
+
SamplePrompt,
|
|
24
|
+
StudioMode,
|
|
25
|
+
StudioModeConfig,
|
|
26
|
+
ComparisonState,
|
|
27
|
+
ImagePickerProps,
|
|
28
|
+
PromptInputProps,
|
|
29
|
+
GenerateButtonProps,
|
|
30
|
+
ResultDisplayProps,
|
|
31
|
+
ErrorDisplayProps,
|
|
32
|
+
ProcessingModalProps,
|
|
33
|
+
FeatureHeaderProps,
|
|
34
|
+
ModeSelectorProps,
|
|
35
|
+
ComparisonSliderProps,
|
|
36
|
+
ProcessRequestParams,
|
|
37
|
+
BackgroundFeatureConfig,
|
|
38
|
+
UseBackgroundFeatureConfig,
|
|
39
|
+
} from "./domain/entities";
|
|
40
|
+
|
|
41
|
+
// =============================================================================
|
|
42
|
+
// INFRASTRUCTURE LAYER - Constants
|
|
43
|
+
// =============================================================================
|
|
44
|
+
|
|
45
|
+
export { DEFAULT_SAMPLE_PROMPTS } from "./infrastructure/constants";
|
|
46
|
+
|
|
47
|
+
// =============================================================================
|
|
48
|
+
// PRESENTATION LAYER - Components
|
|
49
|
+
// =============================================================================
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
BackgroundFeature,
|
|
53
|
+
ImagePicker,
|
|
54
|
+
PromptInput,
|
|
55
|
+
GenerateButton,
|
|
56
|
+
ResultDisplay,
|
|
57
|
+
ErrorDisplay,
|
|
58
|
+
ProcessingModal,
|
|
59
|
+
FeatureHeader,
|
|
60
|
+
ComparisonSlider,
|
|
61
|
+
ModeSelector,
|
|
62
|
+
} from "./presentation/components";
|
|
63
|
+
|
|
64
|
+
export type { BackgroundFeatureProps } from "./presentation/components";
|
|
65
|
+
|
|
66
|
+
// =============================================================================
|
|
67
|
+
// PRESENTATION LAYER - Hooks
|
|
68
|
+
// =============================================================================
|
|
69
|
+
|
|
70
|
+
export { useBackgroundFeature } from "./presentation/hooks";
|
|
71
|
+
|
|
72
|
+
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
|
+
});
|