@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.
Files changed (82) hide show
  1. package/package.json +30 -6
  2. package/src/domains/content-moderation/domain/entities/moderation.types.ts +84 -0
  3. package/src/domains/content-moderation/domain/interfaces/content-filter.interface.ts +24 -0
  4. package/src/domains/content-moderation/index.ts +67 -0
  5. package/src/domains/content-moderation/infrastructure/rules/default-rules.data.ts +144 -0
  6. package/src/domains/content-moderation/infrastructure/rules/rules-registry.ts +75 -0
  7. package/src/domains/content-moderation/infrastructure/services/content-moderation.service.ts +150 -0
  8. package/src/domains/content-moderation/infrastructure/services/index.ts +8 -0
  9. package/src/domains/content-moderation/infrastructure/services/moderators/base.moderator.ts +62 -0
  10. package/src/domains/content-moderation/infrastructure/services/moderators/image.moderator.ts +64 -0
  11. package/src/domains/content-moderation/infrastructure/services/moderators/index.ts +10 -0
  12. package/src/domains/content-moderation/infrastructure/services/moderators/text.moderator.ts +144 -0
  13. package/src/domains/content-moderation/infrastructure/services/moderators/video.moderator.ts +64 -0
  14. package/src/domains/content-moderation/infrastructure/services/moderators/voice.moderator.ts +74 -0
  15. package/src/domains/content-moderation/infrastructure/services/pattern-matcher.service.ts +51 -0
  16. package/src/domains/content-moderation/presentation/exceptions/content-policy-violation.exception.ts +48 -0
  17. package/src/domains/creations/application/services/CreationsService.ts +71 -0
  18. package/src/domains/creations/domain/entities/Creation.ts +51 -0
  19. package/src/domains/creations/domain/entities/index.ts +6 -0
  20. package/src/domains/creations/domain/repositories/ICreationsRepository.ts +23 -0
  21. package/src/domains/creations/domain/repositories/index.ts +5 -0
  22. package/src/domains/creations/domain/services/ICreationsStorageService.ts +13 -0
  23. package/src/domains/creations/domain/value-objects/CreationsConfig.ts +76 -0
  24. package/src/domains/creations/domain/value-objects/index.ts +12 -0
  25. package/src/domains/creations/index.ts +84 -0
  26. package/src/domains/creations/infrastructure/adapters/createRepository.ts +54 -0
  27. package/src/domains/creations/infrastructure/adapters/index.ts +5 -0
  28. package/src/domains/creations/infrastructure/repositories/CreationsRepository.ts +233 -0
  29. package/src/domains/creations/infrastructure/repositories/index.ts +8 -0
  30. package/src/domains/creations/infrastructure/services/CreationsStorageService.ts +48 -0
  31. package/src/domains/creations/presentation/components/CreationCard.tsx +136 -0
  32. package/src/domains/creations/presentation/components/CreationDetail/DetailActions.tsx +76 -0
  33. package/src/domains/creations/presentation/components/CreationDetail/DetailHeader.tsx +81 -0
  34. package/src/domains/creations/presentation/components/CreationDetail/DetailImage.tsx +41 -0
  35. package/src/domains/creations/presentation/components/CreationDetail/DetailStory.tsx +67 -0
  36. package/src/domains/creations/presentation/components/CreationDetail/index.ts +4 -0
  37. package/src/domains/creations/presentation/components/CreationImageViewer.tsx +43 -0
  38. package/src/domains/creations/presentation/components/CreationThumbnail.tsx +63 -0
  39. package/src/domains/creations/presentation/components/CreationsGrid.tsx +75 -0
  40. package/src/domains/creations/presentation/components/CreationsHomeCard.tsx +176 -0
  41. package/src/domains/creations/presentation/components/EmptyState.tsx +75 -0
  42. package/src/domains/creations/presentation/components/FilterBottomSheet.tsx +158 -0
  43. package/src/domains/creations/presentation/components/FilterChips.tsx +105 -0
  44. package/src/domains/creations/presentation/components/GalleryHeader.tsx +106 -0
  45. package/src/domains/creations/presentation/components/index.ts +19 -0
  46. package/src/domains/creations/presentation/hooks/index.ts +7 -0
  47. package/src/domains/creations/presentation/hooks/useCreations.ts +33 -0
  48. package/src/domains/creations/presentation/hooks/useCreationsFilter.ts +70 -0
  49. package/src/domains/creations/presentation/hooks/useDeleteCreation.ts +51 -0
  50. package/src/domains/creations/presentation/screens/CreationDetailScreen.tsx +71 -0
  51. package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +217 -0
  52. package/src/domains/creations/presentation/screens/index.ts +5 -0
  53. package/src/domains/creations/presentation/utils/filterUtils.ts +52 -0
  54. package/src/domains/creations/types.d.ts +107 -0
  55. package/src/domains/face-detection/domain/constants/faceDetectionConstants.ts +16 -0
  56. package/src/domains/face-detection/domain/entities/FaceDetection.ts +19 -0
  57. package/src/domains/face-detection/index.ts +26 -0
  58. package/src/domains/face-detection/infrastructure/analyzers/faceAnalyzer.ts +36 -0
  59. package/src/domains/face-detection/infrastructure/validators/faceValidator.ts +52 -0
  60. package/src/domains/face-detection/presentation/components/FaceValidationStatus.tsx +111 -0
  61. package/src/domains/face-detection/presentation/hooks/useFaceDetection.ts +58 -0
  62. package/src/domains/feature-background/domain/entities/background.types.ts +77 -0
  63. package/src/domains/feature-background/domain/entities/component.types.ts +96 -0
  64. package/src/domains/feature-background/domain/entities/config.types.ts +41 -0
  65. package/src/domains/feature-background/domain/entities/index.ts +31 -0
  66. package/src/domains/feature-background/index.ts +72 -0
  67. package/src/domains/feature-background/infrastructure/constants/index.ts +5 -0
  68. package/src/domains/feature-background/infrastructure/constants/prompts.constants.ts +15 -0
  69. package/src/domains/feature-background/presentation/components/BackgroundFeature.tsx +145 -0
  70. package/src/domains/feature-background/presentation/components/ComparisonSlider.tsx +199 -0
  71. package/src/domains/feature-background/presentation/components/ErrorDisplay.tsx +58 -0
  72. package/src/domains/feature-background/presentation/components/FeatureHeader.tsx +80 -0
  73. package/src/domains/feature-background/presentation/components/GenerateButton.tsx +86 -0
  74. package/src/domains/feature-background/presentation/components/ImagePicker.tsx +136 -0
  75. package/src/domains/feature-background/presentation/components/ModeSelector.tsx +78 -0
  76. package/src/domains/feature-background/presentation/components/ProcessingModal.tsx +113 -0
  77. package/src/domains/feature-background/presentation/components/PromptInput.tsx +142 -0
  78. package/src/domains/feature-background/presentation/components/ResultDisplay.tsx +123 -0
  79. package/src/domains/feature-background/presentation/components/index.ts +16 -0
  80. package/src/domains/feature-background/presentation/hooks/index.ts +7 -0
  81. package/src/domains/feature-background/presentation/hooks/useBackgroundFeature.ts +118 -0
  82. 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,5 @@
1
+ /**
2
+ * Infrastructure Constants Export
3
+ */
4
+
5
+ export { DEFAULT_SAMPLE_PROMPTS } from "./prompts.constants";
@@ -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
+ });