@umituz/react-native-ai-generation-content 1.24.3 → 1.25.2

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.24.3",
3
+ "version": "1.25.2",
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",
@@ -1,16 +1,93 @@
1
1
  /**
2
2
  * Wizard Configurations for ALL Scenarios
3
- * Each scenario defines its wizard flow here
4
- * NO feature-specific code - just configs!
3
+ * Auto-detects feature type and generates appropriate config
4
+ * Supports overrides for customization
5
5
  */
6
6
 
7
7
  import type { WizardFeatureConfig } from "../../wizard/domain/entities/wizard-config.types";
8
8
 
9
9
  /**
10
- * COUPLE SCENARIOS - 2 Photo Uploads
11
- * romantic-kiss, ai-hug, couple-future, couple-ai-baby, etc.
10
+ * Feature Type Classification
11
+ * Determines wizard flow based on scenario characteristics
12
12
  */
13
- const createCoupleWizardConfig = (scenarioId: string): WizardFeatureConfig => ({
13
+ export enum FeatureType {
14
+ COUPLE = "couple", // 2 photos - romantic/partner scenarios
15
+ SINGLE_PHOTO = "single_photo", // 1 photo - editing/transformation
16
+ FACE_SWAP = "face_swap", // 2 photos - face replacement
17
+ TEXT_BASED = "text_based", // 0 photos - text-to-media
18
+ }
19
+
20
+ /**
21
+ * Feature Detection Patterns
22
+ * Regex patterns to auto-detect feature type from scenario ID
23
+ */
24
+ const FEATURE_PATTERNS: Record<FeatureType, RegExp[]> = {
25
+ [FeatureType.COUPLE]: [
26
+ /kiss/i, // romantic-kiss, ai-kiss, first-kiss, etc.
27
+ /hug/i, // ai-hug, back-hug, bear-hug, etc.
28
+ /couple/i, // couple-future, couple-ai-baby
29
+ /partner/i, // partner scenarios
30
+ /wedding/i, // wedding scenarios
31
+ /anniversary/i,
32
+ /dance/i, // first-dance, etc.
33
+ /together/i,
34
+ /embrace/i,
35
+ /romance/i,
36
+ /love/i,
37
+ /relationship/i,
38
+ /years/i, // 5-years, 10-years (couple-future)
39
+ /age/i, // old-age (couple-future)
40
+ /future.*child/i, // future-child
41
+ /parenthood/i,
42
+ /proposal/i,
43
+ /engagement/i,
44
+ ],
45
+
46
+ [FeatureType.SINGLE_PHOTO]: [
47
+ /background.*remove/i,
48
+ /remove.*background/i,
49
+ /photo.*restore/i,
50
+ /restore.*photo/i,
51
+ /upscale/i,
52
+ /hd.*touch/i,
53
+ /touch.*up/i,
54
+ /enhance/i,
55
+ /anime.*selfie/i,
56
+ /selfie.*anime/i,
57
+ /image.*to.*video/i,
58
+ /remove.*object/i,
59
+ /object.*remove/i,
60
+ ],
61
+
62
+ [FeatureType.TEXT_BASED]: [
63
+ /text.*to.*video/i,
64
+ /text.*to.*image/i,
65
+ /prompt.*to/i,
66
+ ],
67
+
68
+ [FeatureType.FACE_SWAP]: [
69
+ /face.*swap/i,
70
+ /swap.*face/i,
71
+ ],
72
+ };
73
+
74
+ /**
75
+ * Detect feature type from scenario ID
76
+ */
77
+ export const detectFeatureType = (scenarioId: string): FeatureType => {
78
+ for (const [type, patterns] of Object.entries(FEATURE_PATTERNS)) {
79
+ if (patterns.some((pattern) => pattern.test(scenarioId))) {
80
+ return type as FeatureType;
81
+ }
82
+ }
83
+ // Default: COUPLE (most common in AI video generation apps)
84
+ return FeatureType.COUPLE;
85
+ };
86
+
87
+ /**
88
+ * Config Factory for COUPLE features (2 photos)
89
+ */
90
+ const createCoupleConfig = (scenarioId: string): WizardFeatureConfig => ({
14
91
  id: scenarioId,
15
92
  name: scenarioId,
16
93
  steps: [
@@ -18,8 +95,8 @@ const createCoupleWizardConfig = (scenarioId: string): WizardFeatureConfig => ({
18
95
  id: "photo_a",
19
96
  type: "photo_upload",
20
97
  label: "First Partner",
21
- titleKey: `${scenarioId}.partnerA.title`,
22
- subtitleKey: `${scenarioId}.partnerA.subtitle`,
98
+ titleKey: "photoUpload.step1.title",
99
+ subtitleKey: "photoUpload.step1.subtitle",
23
100
  showFaceDetection: true,
24
101
  showPhotoTips: true,
25
102
  required: true,
@@ -28,8 +105,8 @@ const createCoupleWizardConfig = (scenarioId: string): WizardFeatureConfig => ({
28
105
  id: "photo_b",
29
106
  type: "photo_upload",
30
107
  label: "Second Partner",
31
- titleKey: `${scenarioId}.partnerB.title`,
32
- subtitleKey: `${scenarioId}.partnerB.subtitle`,
108
+ titleKey: "photoUpload.step2.title",
109
+ subtitleKey: "photoUpload.step2.subtitle",
33
110
  showFaceDetection: true,
34
111
  showPhotoTips: true,
35
112
  required: true,
@@ -38,79 +115,38 @@ const createCoupleWizardConfig = (scenarioId: string): WizardFeatureConfig => ({
38
115
  });
39
116
 
40
117
  /**
41
- * SINGLE PHOTO SCENARIOS
42
- * image-to-video, face-swap (source), etc.
118
+ * Config Factory for SINGLE_PHOTO features (1 photo)
43
119
  */
44
- const createSinglePhotoWizardConfig = (
45
- scenarioId: string,
46
- options?: {
47
- requireStyle?: boolean;
48
- requireDuration?: boolean;
49
- },
50
- ): WizardFeatureConfig => {
51
- const steps: WizardFeatureConfig["steps"] = [
120
+ const createSinglePhotoConfig = (scenarioId: string): WizardFeatureConfig => ({
121
+ id: scenarioId,
122
+ name: scenarioId,
123
+ steps: [
52
124
  {
53
125
  id: "photo",
54
126
  type: "photo_upload",
55
127
  label: "Your Photo",
56
- titleKey: `${scenarioId}.photo.title`,
57
- subtitleKey: `${scenarioId}.photo.subtitle`,
128
+ titleKey: "photoUpload.single.title",
129
+ subtitleKey: "photoUpload.single.subtitle",
58
130
  showFaceDetection: false,
59
131
  showPhotoTips: true,
60
132
  required: true,
61
133
  },
62
- ];
63
-
64
- // Add style selection if needed
65
- if (options?.requireStyle) {
66
- steps.push({
67
- id: "style_selection",
68
- type: "selection",
69
- selectionType: "style",
70
- titleKey: `${scenarioId}.style.title`,
71
- subtitleKey: `${scenarioId}.style.subtitle`,
72
- options: [], // Filled by feature
73
- required: true,
74
- });
75
- }
76
-
77
- // Add duration selection if needed
78
- if (options?.requireDuration) {
79
- steps.push({
80
- id: "duration_selection",
81
- type: "selection",
82
- selectionType: "duration",
83
- titleKey: `${scenarioId}.duration.title`,
84
- subtitleKey: `${scenarioId}.duration.subtitle`,
85
- options: [
86
- { id: "5s", label: "5 seconds", value: 5 },
87
- { id: "10s", label: "10 seconds", value: 10 },
88
- { id: "15s", label: "15 seconds", value: 15 },
89
- ],
90
- required: true,
91
- });
92
- }
93
-
94
- return {
95
- id: scenarioId,
96
- name: scenarioId,
97
- steps,
98
- };
99
- };
134
+ ],
135
+ });
100
136
 
101
137
  /**
102
- * TEXT-TO-VIDEO SCENARIOS
138
+ * Config Factory for TEXT_BASED features (0 photos, text input)
103
139
  */
104
- const createTextToVideoWizardConfig = (scenarioId: string): WizardFeatureConfig => ({
140
+ const createTextBasedConfig = (scenarioId: string): WizardFeatureConfig => ({
105
141
  id: scenarioId,
106
142
  name: scenarioId,
107
143
  steps: [
108
144
  {
109
145
  id: "text_input",
110
146
  type: "text_input",
111
- titleKey: `${scenarioId}.prompt.title`,
112
- subtitleKey: `${scenarioId}.prompt.subtitle`,
113
- placeholderKey: `${scenarioId}.prompt.placeholder`,
147
+ titleKey: "textInput.title",
148
+ subtitleKey: "textInput.subtitle",
149
+ placeholderKey: "textInput.placeholder",
114
150
  minLength: 10,
115
151
  maxLength: 500,
116
152
  multiline: true,
@@ -120,102 +156,129 @@ const createTextToVideoWizardConfig = (scenarioId: string): WizardFeatureConfig
120
156
  id: "style_selection",
121
157
  type: "selection",
122
158
  selectionType: "style",
123
- titleKey: `${scenarioId}.style.title`,
124
- options: [], // Filled by feature
125
- required: true,
126
- },
127
- {
128
- id: "duration_selection",
129
- type: "selection",
130
- selectionType: "duration",
131
- titleKey: `${scenarioId}.duration.title`,
132
- options: [
133
- { id: "5s", label: "5 seconds", value: 5 },
134
- { id: "10s", label: "10 seconds", value: 10 },
135
- ],
136
- required: true,
159
+ titleKey: "styleSelection.title",
160
+ subtitleKey: "styleSelection.subtitle",
161
+ options: [], // Provided by app/feature
162
+ required: false,
137
163
  },
138
164
  ],
139
165
  });
140
166
 
141
167
  /**
142
- * SCENARIO WIZARD CONFIG REGISTRY
143
- * Maps scenario ID to wizard config
144
- */
145
- export const SCENARIO_WIZARD_CONFIGS: Record<string, WizardFeatureConfig> = {
146
- // COUPLE SCENARIOS (2 photos)
147
- "romantic-kiss": createCoupleWizardConfig("romantic-kiss"),
148
- "ai-hug": createCoupleWizardConfig("ai-hug"),
149
- "couple-future-40": createCoupleWizardConfig("couple-future-40"),
150
- "couple-future-50": createCoupleWizardConfig("couple-future-50"),
151
- "couple-future-60": createCoupleWizardConfig("couple-future-60"),
152
- "couple-future-70": createCoupleWizardConfig("couple-future-70"),
153
- "couple-future-80": createCoupleWizardConfig("couple-future-80"),
154
- "couple-ai-baby": createCoupleWizardConfig("couple-ai-baby"),
155
-
156
- // SINGLE PHOTO SCENARIOS
157
- "image-to-video": createSinglePhotoWizardConfig("image-to-video", {
158
- requireStyle: true,
159
- requireDuration: true,
160
- }),
161
- "face-swap": createSinglePhotoWizardConfig("face-swap"),
162
- "anime-selfie": createSinglePhotoWizardConfig("anime-selfie"),
163
-
164
- // TEXT-TO-VIDEO SCENARIOS
165
- "text-to-video": createTextToVideoWizardConfig("text-to-video"),
166
- };
167
-
168
- /**
169
- * DEFAULT WIZARD CONFIG
170
- * Used for ALL scenarios that don't have specific config
171
- * Couple/Partner scenarios → 2 photo uploads
168
+ * Config Factory for FACE_SWAP features (2 photos, different context)
172
169
  */
173
- const DEFAULT_WIZARD_CONFIG = (scenarioId: string): WizardFeatureConfig => ({
170
+ const createFaceSwapConfig = (scenarioId: string): WizardFeatureConfig => ({
174
171
  id: scenarioId,
175
172
  name: scenarioId,
176
173
  steps: [
177
174
  {
178
- id: "photo_a",
175
+ id: "source_photo",
179
176
  type: "photo_upload",
180
- label: "First Partner",
181
- titleKey: "photoUpload.step1.title",
182
- subtitleKey: "photoUpload.step1.subtitle",
177
+ label: "Source Face",
178
+ titleKey: "faceSwap.source.title",
179
+ subtitleKey: "faceSwap.source.subtitle",
183
180
  showFaceDetection: true,
184
181
  showPhotoTips: true,
185
182
  required: true,
186
183
  },
187
184
  {
188
- id: "photo_b",
185
+ id: "target_photo",
189
186
  type: "photo_upload",
190
- label: "Second Partner",
191
- titleKey: "photoUpload.step2.title",
192
- subtitleKey: "photoUpload.step2.subtitle",
193
- showFaceDetection: true,
187
+ label: "Target Photo",
188
+ titleKey: "faceSwap.target.title",
189
+ subtitleKey: "faceSwap.target.subtitle",
190
+ showFaceDetection: false,
194
191
  showPhotoTips: true,
195
192
  required: true,
196
193
  },
197
194
  ],
198
195
  });
199
196
 
197
+ /**
198
+ * Config Factories Registry
199
+ */
200
+ const FEATURE_CONFIG_FACTORIES: Record<FeatureType, (id: string) => WizardFeatureConfig> = {
201
+ [FeatureType.COUPLE]: createCoupleConfig,
202
+ [FeatureType.SINGLE_PHOTO]: createSinglePhotoConfig,
203
+ [FeatureType.TEXT_BASED]: createTextBasedConfig,
204
+ [FeatureType.FACE_SWAP]: createFaceSwapConfig,
205
+ };
206
+
207
+ /**
208
+ * Explicit Wizard Configs (Optional)
209
+ * Define specific configs for scenarios that need custom flows
210
+ * Most scenarios will use auto-generated configs from factories
211
+ */
212
+ export const SCENARIO_WIZARD_CONFIGS: Record<string, WizardFeatureConfig> = {
213
+ // Add custom configs here only if needed
214
+ // Example:
215
+ // "special-scenario": {
216
+ // id: "special-scenario",
217
+ // steps: [...custom steps]
218
+ // }
219
+ };
220
+
221
+ /**
222
+ * Merge config overrides
223
+ */
224
+ const mergeConfigOverrides = (
225
+ config: WizardFeatureConfig,
226
+ overrides?: Partial<WizardFeatureConfig>,
227
+ ): WizardFeatureConfig => {
228
+ if (!overrides) return config;
229
+
230
+ return {
231
+ ...config,
232
+ ...overrides,
233
+ steps: overrides.steps || config.steps,
234
+ };
235
+ };
236
+
200
237
  /**
201
238
  * Get wizard config for a scenario
202
- * Returns specific config if exists, otherwise returns DEFAULT config
239
+ * 1. Check for explicit config in SCENARIO_WIZARD_CONFIGS
240
+ * 2. Auto-detect feature type and generate config
241
+ * 3. Apply overrides if provided
242
+ *
203
243
  * This means ALL scenarios work automatically!
204
244
  */
205
- export const getScenarioWizardConfig = (scenarioId: string): WizardFeatureConfig => {
206
- return SCENARIO_WIZARD_CONFIGS[scenarioId] || DEFAULT_WIZARD_CONFIG(scenarioId);
245
+ export const getScenarioWizardConfig = (
246
+ scenarioId: string,
247
+ overrides?: Partial<WizardFeatureConfig>,
248
+ ): WizardFeatureConfig => {
249
+ // 1. Explicit config (highest priority)
250
+ if (SCENARIO_WIZARD_CONFIGS[scenarioId]) {
251
+ return mergeConfigOverrides(SCENARIO_WIZARD_CONFIGS[scenarioId], overrides);
252
+ }
253
+
254
+ // 2. Auto-detect feature type
255
+ const featureType = detectFeatureType(scenarioId);
256
+
257
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
258
+ console.log("[WizardConfig] Auto-detected feature type", {
259
+ scenarioId,
260
+ featureType,
261
+ });
262
+ }
263
+
264
+ // 3. Generate config from factory
265
+ const factory = FEATURE_CONFIG_FACTORIES[featureType];
266
+ const config = factory(scenarioId);
267
+
268
+ // 4. Apply overrides
269
+ return mergeConfigOverrides(config, overrides);
207
270
  };
208
271
 
209
272
  /**
210
- * Check if scenario has wizard config
273
+ * Check if scenario has explicit wizard config
211
274
  */
212
- export const hasWizardConfig = (scenarioId: string): boolean => {
275
+ export const hasExplicitConfig = (scenarioId: string): boolean => {
213
276
  return scenarioId in SCENARIO_WIZARD_CONFIGS;
214
277
  };
215
278
 
216
279
  /**
217
- * Get all scenario IDs with wizard configs
280
+ * Get feature type for a scenario
218
281
  */
219
- export const getConfiguredScenarioIds = (): string[] => {
220
- return Object.keys(SCENARIO_WIZARD_CONFIGS);
282
+ export const getScenarioFeatureType = (scenarioId: string): FeatureType => {
283
+ return detectFeatureType(scenarioId);
221
284
  };
@@ -14,10 +14,12 @@ export { SCENARIOS } from "./infrastructure/ScenariosData";
14
14
  // Utils
15
15
  export { createStoryTemplate } from "./infrastructure/utils/scenario-utils";
16
16
 
17
- // Wizard Configurations - Each scenario's wizard flow
17
+ // Wizard Configurations - Auto-detects feature type and generates config
18
18
  export {
19
+ FeatureType,
19
20
  SCENARIO_WIZARD_CONFIGS,
21
+ detectFeatureType,
20
22
  getScenarioWizardConfig,
21
- hasWizardConfig,
22
- getConfiguredScenarioIds,
23
+ hasExplicitConfig,
24
+ getScenarioFeatureType,
23
25
  } from "./configs/wizard-configs";
@@ -29,7 +29,7 @@ export interface GenericWizardFlowProps {
29
29
  readonly onBack?: () => void;
30
30
  readonly t: (key: string) => string;
31
31
  readonly translations?: Record<string, string>;
32
- readonly renderPreview?: () => React.ReactElement | null;
32
+ readonly renderPreview?: (onContinue: () => void) => React.ReactElement | null;
33
33
  readonly renderGenerating?: (progress: number) => React.ReactElement | null;
34
34
  readonly renderResult?: (result: unknown) => React.ReactElement | null;
35
35
  }
@@ -144,7 +144,8 @@ export const GenericWizardFlow: React.FC<GenericWizardFlowProps> = ({
144
144
  // Special steps with custom renderers
145
145
  switch (step.type) {
146
146
  case StepType.SCENARIO_PREVIEW:
147
- return renderPreview?.() || null;
147
+ // Preview continues to next step automatically
148
+ return renderPreview?.(flow.nextStep) || null;
148
149
 
149
150
  case StepType.GENERATING:
150
151
  return renderGenerating?.(flow.generationProgress) || null;