@umituz/react-native-ai-generation-content 1.20.41 → 1.20.43

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.20.41",
3
+ "version": "1.20.43",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Couple Future Wizard Types
3
+ * Configuration types for the couple future wizard component
4
+ */
5
+
6
+ import type { StepType, FlowCallbacks, FlowUploadedImageData } from "../../../domain/entities/flow-config.types";
7
+
8
+ /** Scenario data structure */
9
+ export interface WizardScenarioData {
10
+ readonly id: string;
11
+ readonly title: string;
12
+ readonly description?: string;
13
+ readonly image?: string;
14
+ readonly aiPrompt?: string;
15
+ readonly category?: string;
16
+ }
17
+
18
+ /** Visual style option */
19
+ export interface WizardVisualStyleOption {
20
+ readonly id: string;
21
+ readonly icon: string;
22
+ readonly labelKey: string;
23
+ }
24
+
25
+ /** Partner upload config */
26
+ export interface WizardPartnerConfig {
27
+ readonly titleKey: string;
28
+ readonly subtitleKey: string;
29
+ readonly showFaceDetection?: boolean;
30
+ readonly showNameInput?: boolean;
31
+ readonly showPhotoTips?: boolean;
32
+ }
33
+
34
+ /** Wizard step config */
35
+ export interface WizardStepConfig {
36
+ readonly id: string;
37
+ readonly type: StepType;
38
+ readonly enabled?: boolean;
39
+ }
40
+
41
+ /** Wizard configuration */
42
+ export interface CoupleFutureWizardConfig {
43
+ readonly steps: readonly WizardStepConfig[];
44
+ readonly customScenarioId?: string;
45
+ readonly partnerA?: WizardPartnerConfig;
46
+ readonly partnerB?: WizardPartnerConfig;
47
+ }
48
+
49
+ /** Wizard translations */
50
+ export interface CoupleFutureWizardTranslations {
51
+ readonly generator: {
52
+ readonly title: string;
53
+ readonly waitMessage: string;
54
+ readonly hint?: string;
55
+ };
56
+ readonly partnerA: {
57
+ readonly title: string;
58
+ readonly subtitle: string;
59
+ readonly continue: string;
60
+ readonly tapToUpload: string;
61
+ readonly selectPhoto: string;
62
+ readonly change: string;
63
+ };
64
+ readonly partnerB: {
65
+ readonly title: string;
66
+ readonly subtitle: string;
67
+ readonly continue: string;
68
+ readonly tapToUpload: string;
69
+ readonly selectPhoto: string;
70
+ readonly change: string;
71
+ };
72
+ readonly scenarioPreview: {
73
+ readonly continue: string;
74
+ readonly back?: string;
75
+ };
76
+ readonly defaultNames: {
77
+ readonly partnerA: string;
78
+ readonly partnerB: string;
79
+ };
80
+ }
81
+
82
+ /** Wizard data providers */
83
+ export interface CoupleFutureWizardData {
84
+ readonly scenarios: readonly WizardScenarioData[];
85
+ readonly visualStyles?: readonly WizardVisualStyleOption[];
86
+ readonly surprisePrompts?: readonly string[];
87
+ }
88
+
89
+ /** Wizard callbacks */
90
+ export interface CoupleFutureWizardCallbacks extends FlowCallbacks {
91
+ readonly onScenarioSelect?: (scenario: WizardScenarioData) => void;
92
+ readonly onPartnerUpload?: (partnerId: "A" | "B", image: FlowUploadedImageData) => void;
93
+ readonly requireFeature?: (callback: () => void) => boolean;
94
+ }
95
+
96
+ /** Wizard props */
97
+ export interface CoupleFutureWizardProps {
98
+ readonly userId?: string;
99
+ readonly config: CoupleFutureWizardConfig;
100
+ readonly translations: CoupleFutureWizardTranslations;
101
+ readonly data: CoupleFutureWizardData;
102
+ readonly callbacks?: CoupleFutureWizardCallbacks;
103
+ readonly t: (key: string) => string;
104
+ }
105
+
106
+ /** Wizard state (exposed to parent) */
107
+ export interface CoupleFutureWizardState {
108
+ readonly currentStepId: string;
109
+ readonly selectedScenario: WizardScenarioData | null;
110
+ readonly partnerA: FlowUploadedImageData | null;
111
+ readonly partnerB: FlowUploadedImageData | null;
112
+ readonly partnerAName: string;
113
+ readonly partnerBName: string;
114
+ readonly customPrompt: string;
115
+ readonly visualStyle: string;
116
+ readonly isGenerating: boolean;
117
+ readonly progress: number;
118
+ }
@@ -47,6 +47,22 @@ export type {
47
47
  } from "./infrastructure/coupleFeatureRegistry";
48
48
  export { enhanceCouplePrompt } from "./infrastructure/couplePromptEnhancer";
49
49
 
50
+ // Wizard Component
51
+ export { CoupleFutureWizard, resetCoupleFutureWizard } from "./presentation/components/CoupleFutureWizard";
52
+ export { GeneratingStepContent } from "./presentation/components/GeneratingStepContent";
53
+ export type {
54
+ CoupleFutureWizardProps,
55
+ CoupleFutureWizardConfig,
56
+ CoupleFutureWizardTranslations,
57
+ CoupleFutureWizardData,
58
+ CoupleFutureWizardCallbacks,
59
+ CoupleFutureWizardState,
60
+ WizardScenarioData,
61
+ WizardVisualStyleOption,
62
+ WizardPartnerConfig,
63
+ WizardStepConfig,
64
+ } from "./domain/wizard.types";
65
+
50
66
  // Generation utilities
51
67
  export {
52
68
  buildGenerationInputFromConfig,
@@ -0,0 +1,160 @@
1
+ /**
2
+ * CoupleFutureWizard
3
+ * Complete wizard component for couple future generation flow
4
+ */
5
+
6
+ import React, { useCallback, useMemo } from "react";
7
+ import { View, StyleSheet } from "react-native";
8
+ import { useAppDesignTokens } from "@umituz/react-native-design-system";
9
+ import { useFlow, resetFlowStore } from "../../../../infrastructure/flow";
10
+ import { StepType } from "../../../../domain/entities/flow-config.types";
11
+ import type { StepDefinition } from "../../../../domain/entities/flow-config.types";
12
+ import type { CoupleFutureWizardProps, WizardScenarioData } from "../../domain/wizard.types";
13
+ import { PartnerStepScreen } from "../../../partner-upload";
14
+ import { ScenarioPreviewScreen } from "../../../scenarios";
15
+ import { GeneratingStepContent } from "./GeneratingStepContent";
16
+
17
+ const createStepDefinitions = (
18
+ config: CoupleFutureWizardProps["config"],
19
+ ): readonly StepDefinition[] => {
20
+ return config.steps.map((step) => ({
21
+ id: step.id,
22
+ type: step.type,
23
+ required: step.enabled !== false,
24
+ }));
25
+ };
26
+
27
+ export const CoupleFutureWizard: React.FC<CoupleFutureWizardProps> = ({
28
+ config,
29
+ translations,
30
+ data,
31
+ callbacks,
32
+ t,
33
+ }) => {
34
+ const tokens = useAppDesignTokens();
35
+
36
+ const stepDefinitions = useMemo(
37
+ () => createStepDefinitions(config),
38
+ [config],
39
+ );
40
+
41
+ const flow = useFlow({ steps: stepDefinitions });
42
+
43
+ const handleScenarioSelect = useCallback(
44
+ (scenario: WizardScenarioData) => {
45
+ flow.setCategory(scenario);
46
+ callbacks?.onScenarioSelect?.(scenario);
47
+ flow.nextStep();
48
+ },
49
+ [flow, callbacks],
50
+ );
51
+
52
+ const handleScenarioPreviewContinue = useCallback(() => {
53
+ const checkFeature = callbacks?.requireFeature;
54
+ if (checkFeature) {
55
+ checkFeature(() => flow.nextStep());
56
+ } else {
57
+ flow.nextStep();
58
+ }
59
+ }, [flow, callbacks]);
60
+
61
+ const handlePartnerAContinue = useCallback(
62
+ (image: { uri: string; base64: string; mimeType: string }, name?: string) => {
63
+ flow.setPartnerImage("A", image);
64
+ if (name) flow.setPartnerName("A", name);
65
+ callbacks?.onPartnerUpload?.("A", image);
66
+ flow.nextStep();
67
+ },
68
+ [flow, callbacks],
69
+ );
70
+
71
+ const handlePartnerBContinue = useCallback(
72
+ (image: { uri: string; base64: string; mimeType: string }, name?: string) => {
73
+ flow.setPartnerImage("B", image);
74
+ if (name) flow.setPartnerName("B", name);
75
+ callbacks?.onPartnerUpload?.("B", image);
76
+ flow.startGeneration();
77
+ callbacks?.onGenerationStart?.();
78
+ },
79
+ [flow, callbacks],
80
+ );
81
+
82
+ const renderCurrentStep = useCallback(() => {
83
+ const step = flow.currentStep;
84
+ if (!step) return null;
85
+
86
+ switch (step.type) {
87
+ case StepType.SCENARIO_SELECTION:
88
+ return null; // Rendered by parent via CategoryNavigationContainer
89
+
90
+ case StepType.SCENARIO_PREVIEW:
91
+ return (
92
+ <ScenarioPreviewScreen
93
+ scenario={flow.selectedCategory as never}
94
+ translations={translations.scenarioPreview as never}
95
+ onBack={flow.previousStep}
96
+ onContinue={handleScenarioPreviewContinue}
97
+ t={t}
98
+ />
99
+ );
100
+
101
+ case StepType.PARTNER_UPLOAD:
102
+ const isPartnerA = step.id.includes("A") || step.id === "PARTNER_A";
103
+ const partnerTranslations = isPartnerA
104
+ ? translations.partnerA
105
+ : translations.partnerB;
106
+ const partnerConfig = isPartnerA ? config.partnerA : config.partnerB;
107
+
108
+ return (
109
+ <PartnerStepScreen
110
+ key={isPartnerA ? "a" : "b"}
111
+ translations={partnerTranslations as never}
112
+ t={t}
113
+ initialName=""
114
+ config={{
115
+ showFaceDetection: partnerConfig?.showFaceDetection ?? false,
116
+ showNameInput: partnerConfig?.showNameInput ?? false,
117
+ showPhotoTips: partnerConfig?.showPhotoTips ?? true,
118
+ maxFileSizeMB: 10,
119
+ maxNameLength: 30,
120
+ }}
121
+ onBack={flow.previousStep}
122
+ onContinue={isPartnerA ? handlePartnerAContinue as never : handlePartnerBContinue as never}
123
+ />
124
+ );
125
+
126
+ case StepType.GENERATING:
127
+ return (
128
+ <GeneratingStepContent
129
+ progress={flow.generationProgress}
130
+ title={translations.generator.title}
131
+ message={translations.generator.waitMessage}
132
+ hint={translations.generator.hint}
133
+ />
134
+ );
135
+
136
+ default:
137
+ return null;
138
+ }
139
+ }, [
140
+ flow,
141
+ config,
142
+ translations,
143
+ t,
144
+ handleScenarioPreviewContinue,
145
+ handlePartnerAContinue,
146
+ handlePartnerBContinue,
147
+ ]);
148
+
149
+ return (
150
+ <View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
151
+ {renderCurrentStep()}
152
+ </View>
153
+ );
154
+ };
155
+
156
+ export { resetFlowStore as resetCoupleFutureWizard };
157
+
158
+ const styles = StyleSheet.create({
159
+ container: { flex: 1 },
160
+ });
@@ -0,0 +1,86 @@
1
+ /**
2
+ * GeneratingStepContent
3
+ * Display component for generation progress
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, StyleSheet } from "react-native";
8
+ import {
9
+ AtomicText,
10
+ useAppDesignTokens,
11
+ } from "@umituz/react-native-design-system";
12
+ import { GenerationProgressBar } from "../../../../presentation/components";
13
+
14
+ interface GeneratingStepContentProps {
15
+ readonly progress: number;
16
+ readonly title: string;
17
+ readonly message: string;
18
+ readonly hint?: string;
19
+ }
20
+
21
+ export const GeneratingStepContent: React.FC<GeneratingStepContentProps> = ({
22
+ progress,
23
+ title,
24
+ message,
25
+ hint,
26
+ }) => {
27
+ const tokens = useAppDesignTokens();
28
+
29
+ return (
30
+ <View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
31
+ <View style={styles.content}>
32
+ <AtomicText type="headlineMedium" style={styles.title}>
33
+ {title}
34
+ </AtomicText>
35
+
36
+ <View style={styles.progressContainer}>
37
+ <GenerationProgressBar progress={progress} />
38
+ </View>
39
+
40
+ <AtomicText
41
+ type="bodyMedium"
42
+ style={[styles.message, { color: tokens.colors.textSecondary }]}
43
+ >
44
+ {message}
45
+ </AtomicText>
46
+
47
+ {hint ? (
48
+ <AtomicText
49
+ type="labelSmall"
50
+ style={[styles.hint, { color: tokens.colors.textTertiary }]}
51
+ >
52
+ {hint}
53
+ </AtomicText>
54
+ ) : null}
55
+ </View>
56
+ </View>
57
+ );
58
+ };
59
+
60
+ const styles = StyleSheet.create({
61
+ container: {
62
+ flex: 1,
63
+ justifyContent: "center",
64
+ alignItems: "center",
65
+ },
66
+ content: {
67
+ width: "100%",
68
+ paddingHorizontal: 24,
69
+ alignItems: "center",
70
+ },
71
+ title: {
72
+ textAlign: "center",
73
+ marginBottom: 32,
74
+ },
75
+ progressContainer: {
76
+ width: "100%",
77
+ marginBottom: 24,
78
+ },
79
+ message: {
80
+ textAlign: "center",
81
+ marginBottom: 16,
82
+ },
83
+ hint: {
84
+ textAlign: "center",
85
+ },
86
+ });