@umituz/react-native-ai-generation-content 1.21.1 → 1.22.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.21.1",
3
+ "version": "1.22.0",
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",
@@ -14,18 +14,54 @@ export enum ScenarioCategory {
14
14
  CULTURAL = "cultural",
15
15
  }
16
16
 
17
+ /**
18
+ * Output type for AI generation
19
+ */
20
+ export type ScenarioOutputType = 'image' | 'video' | 'both';
21
+
22
+ /**
23
+ * Scenario media configuration
24
+ */
25
+ export interface ScenarioMedia {
26
+ readonly imageUrl?: string; // Preview/thumbnail image
27
+ readonly videoUrl?: string; // Preview video URL
28
+ readonly previewImageUrl?: string; // Smaller thumbnail
29
+ }
30
+
17
31
  export interface ScenarioData {
18
32
  readonly id: string;
19
33
  readonly category?: ScenarioCategory | string;
34
+
35
+ // Content (app provides in target language)
20
36
  readonly title: string;
21
37
  readonly description: string;
38
+
39
+ // AI Configuration
40
+ readonly outputType: ScenarioOutputType; // What this scenario generates
41
+ readonly aiPrompt: string; // AI generation prompt
42
+ readonly storyTemplate?: string; // Story template with placeholders (optional)
43
+
44
+ // Media
22
45
  readonly icon: string;
23
- readonly imageUrl?: string;
24
- readonly previewImageUrl?: string;
25
- readonly aiPrompt: string;
26
- readonly storyTemplate: string;
27
- readonly requiresPhoto?: boolean;
28
- readonly hidden?: boolean;
46
+ readonly imageUrl?: string; // Preview image
47
+ readonly videoUrl?: string; // Preview video
48
+ readonly previewImageUrl?: string; // Thumbnail
49
+
50
+ // Requirements
51
+ readonly requiresPhoto?: boolean; // Requires user photo upload
52
+ readonly requiresMultiplePhotos?: boolean; // Requires multiple photos (e.g., couples)
53
+ readonly minPhotos?: number; // Minimum photos required
54
+ readonly maxPhotos?: number; // Maximum photos allowed
55
+
56
+ // Display
57
+ readonly hidden?: boolean; // Hide from UI
58
+ readonly featured?: boolean; // Featured/promoted scenario
59
+ readonly order?: number; // Display order
60
+
61
+ // Metadata
62
+ readonly tags?: readonly string[]; // Search/filter tags
63
+ readonly duration?: number; // Video duration (for video scenarios)
64
+ readonly aspectRatio?: string; // Output aspect ratio (e.g., "16:9", "9:16")
29
65
  }
30
66
 
31
67
  /**
@@ -33,8 +69,8 @@ export interface ScenarioData {
33
69
  */
34
70
  export interface ScenarioMainCategory {
35
71
  readonly id: string;
36
- readonly titleKey: string;
37
- readonly descriptionKey?: string;
72
+ readonly title: string;
73
+ readonly description?: string;
38
74
  readonly icon?: string;
39
75
  readonly emoji?: string;
40
76
  readonly order: number;
@@ -46,8 +82,8 @@ export interface ScenarioMainCategory {
46
82
  */
47
83
  export interface ScenarioSubCategory {
48
84
  readonly id: string;
49
- readonly titleKey: string;
50
- readonly descriptionKey?: string;
85
+ readonly title: string;
86
+ readonly description?: string;
51
87
  readonly icon?: string;
52
88
  readonly emoji?: string;
53
89
  readonly mainCategoryId: string;
@@ -4,7 +4,7 @@
4
4
  * Main Category → Sub Category → Scenario List
5
5
  */
6
6
 
7
- import React, { useState, useCallback } from "react";
7
+ import React, { useState, useCallback, useEffect } from "react";
8
8
  import type {
9
9
  ScenarioData,
10
10
  ScenarioMainCategory,
@@ -45,22 +45,61 @@ export const CategoryNavigationContainer: React.FC<
45
45
  const [selectedMainCategoryId, setSelectedMainCategoryId] = useState<string | null>(null);
46
46
  const [selectedSubCategoryId, setSelectedSubCategoryId] = useState<string | null>(null);
47
47
 
48
+ // Debug: Initial mount
49
+ useEffect(() => {
50
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
51
+ console.log("[CategoryNavigationContainer] Mounted", {
52
+ mainCategoriesCount: mainCategories.length,
53
+ subCategoriesCount: subCategories.length,
54
+ scenariosCount: scenarios.length,
55
+ currentStep,
56
+ });
57
+ }
58
+ }, []);
59
+
60
+ // Debug: Step changes
61
+ useEffect(() => {
62
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
63
+ console.log("[CategoryNavigationContainer] Step changed", {
64
+ currentStep,
65
+ selectedMainCategoryId,
66
+ selectedSubCategoryId,
67
+ });
68
+ }
69
+ }, [currentStep, selectedMainCategoryId, selectedSubCategoryId]);
70
+
48
71
  const handleSelectMainCategory = useCallback((categoryId: string) => {
72
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
73
+ console.log("[CategoryNavigationContainer] Main category selected", {
74
+ categoryId,
75
+ });
76
+ }
49
77
  setSelectedMainCategoryId(categoryId);
50
78
  setCurrentStep("sub_category");
51
79
  }, []);
52
80
 
53
81
  const handleSelectSubCategory = useCallback((subCategoryId: string) => {
82
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
83
+ console.log("[CategoryNavigationContainer] Sub category selected", {
84
+ subCategoryId,
85
+ });
86
+ }
54
87
  setSelectedSubCategoryId(subCategoryId);
55
88
  setCurrentStep("scenario_list");
56
89
  }, []);
57
90
 
58
91
  const handleBackFromSubCategory = useCallback(() => {
92
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
93
+ console.log("[CategoryNavigationContainer] Back from sub category");
94
+ }
59
95
  setSelectedMainCategoryId(null);
60
96
  setCurrentStep("main_category");
61
97
  }, []);
62
98
 
63
99
  const handleBackFromScenarioList = useCallback(() => {
100
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
101
+ console.log("[CategoryNavigationContainer] Back from scenario list");
102
+ }
64
103
  setSelectedSubCategoryId(null);
65
104
  setCurrentStep("sub_category");
66
105
  }, []);
@@ -72,6 +111,11 @@ export const CategoryNavigationContainer: React.FC<
72
111
  }, [onBack]);
73
112
 
74
113
  if (currentStep === "main_category") {
114
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
115
+ console.log("[CategoryNavigationContainer] Rendering MainCategoryScreen", {
116
+ mainCategoriesCount: mainCategories.length,
117
+ });
118
+ }
75
119
  return (
76
120
  <MainCategoryScreen
77
121
  mainCategories={mainCategories}
@@ -85,6 +129,12 @@ export const CategoryNavigationContainer: React.FC<
85
129
  }
86
130
 
87
131
  if (currentStep === "sub_category" && selectedMainCategoryId) {
132
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
133
+ console.log("[CategoryNavigationContainer] Rendering SubCategoryScreen", {
134
+ selectedMainCategoryId,
135
+ subCategoriesCount: subCategories.length,
136
+ });
137
+ }
88
138
  return (
89
139
  <SubCategoryScreen
90
140
  mainCategoryId={selectedMainCategoryId}
@@ -97,6 +147,12 @@ export const CategoryNavigationContainer: React.FC<
97
147
  }
98
148
 
99
149
  if (currentStep === "scenario_list" && selectedSubCategoryId) {
150
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
151
+ console.log("[CategoryNavigationContainer] Rendering HierarchicalScenarioListScreen", {
152
+ selectedSubCategoryId,
153
+ scenariosCount: scenarios.length,
154
+ });
155
+ }
100
156
  return (
101
157
  <HierarchicalScenarioListScreen
102
158
  subCategoryId={selectedSubCategoryId}
@@ -110,5 +166,13 @@ export const CategoryNavigationContainer: React.FC<
110
166
  );
111
167
  }
112
168
 
169
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
170
+ console.log("[CategoryNavigationContainer] Rendering NULL - no matching condition", {
171
+ currentStep,
172
+ selectedMainCategoryId,
173
+ selectedSubCategoryId,
174
+ });
175
+ }
176
+
113
177
  return null;
114
178
  };
@@ -4,7 +4,7 @@
4
4
  * PERFORMANCE OPTIMIZED: No FlatList key remounting, memoized calculations
5
5
  */
6
6
 
7
- import React, { useMemo, useCallback, useState } from "react";
7
+ import React, { useMemo, useCallback, useState, useEffect } from "react";
8
8
  import {
9
9
  View,
10
10
  FlatList,
@@ -56,13 +56,44 @@ export const HierarchicalScenarioListScreen: React.FC<HierarchicalScenarioListSc
56
56
  );
57
57
 
58
58
  const filteredScenarios = useMemo(() => {
59
- if (!subCategory) return [];
59
+ if (!subCategory) {
60
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
61
+ console.log("[HierarchicalScenarioListScreen] No subCategory found", {
62
+ subCategoryId,
63
+ subCategoriesCount: subCategories.length,
64
+ });
65
+ }
66
+ return [];
67
+ }
60
68
 
61
- return scenarios.filter((scenario) => {
69
+ const filtered = scenarios.filter((scenario) => {
62
70
  if (!scenario.category) return false;
63
71
  return subCategory.scenarioCategories.includes(scenario.category);
64
72
  });
65
- }, [scenarios, subCategory]);
73
+
74
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
75
+ console.log("[HierarchicalScenarioListScreen] Filtered scenarios", {
76
+ subCategoryId: subCategory.id,
77
+ scenarioCategories: subCategory.scenarioCategories,
78
+ totalScenarios: scenarios.length,
79
+ filteredCount: filtered.length,
80
+ sampleScenarioCategories: scenarios.slice(0, 5).map(s => s.category),
81
+ });
82
+ }
83
+
84
+ return filtered;
85
+ }, [scenarios, subCategory, subCategoryId, subCategories]);
86
+
87
+ // Debug: Monitor component state
88
+ useEffect(() => {
89
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
90
+ console.log("[HierarchicalScenarioListScreen] Component state", {
91
+ subCategoryId,
92
+ hasSubCategory: !!subCategory,
93
+ filteredScenariosCount: filteredScenarios.length,
94
+ });
95
+ }
96
+ }, [subCategoryId, subCategory, filteredScenarios]);
66
97
 
67
98
  const horizontalPadding = tokens.spacing.md;
68
99
  const cardSpacing = tokens.spacing.md;
@@ -91,15 +122,13 @@ export const HierarchicalScenarioListScreen: React.FC<HierarchicalScenarioListSc
91
122
 
92
123
  const renderItem = useCallback(
93
124
  ({ item }: ListRenderItemInfo<ScenarioData>) => {
94
- const title = t(`scenario.${item.id}.title`);
95
- const description = t(`scenario.${item.id}.description`);
96
125
  const isSelected = selectedId === item.id;
97
126
 
98
127
  return (
99
128
  <AtomicCard
100
129
  image={item.previewImageUrl || item.imageUrl || ""}
101
- title={title}
102
- subtitle={description}
130
+ title={item.title}
131
+ subtitle={item.description}
103
132
  imageAspectRatio={1.25}
104
133
  selected={isSelected}
105
134
  style={{ width: cardWidth }}
@@ -108,7 +137,7 @@ export const HierarchicalScenarioListScreen: React.FC<HierarchicalScenarioListSc
108
137
  />
109
138
  );
110
139
  },
111
- [cardWidth, selectedId, t, handleCardPress]
140
+ [cardWidth, selectedId, handleCardPress]
112
141
  );
113
142
 
114
143
  const ListEmptyComponent = useMemo(
@@ -3,7 +3,7 @@
3
3
  * Displays main categories for hierarchical scenario selection
4
4
  */
5
5
 
6
- import React, { useMemo, useCallback } from "react";
6
+ import React, { useMemo, useCallback, useEffect } from "react";
7
7
  import {
8
8
  View,
9
9
  FlatList,
@@ -42,10 +42,22 @@ export const MainCategoryScreen: React.FC<MainCategoryScreenProps> = ({
42
42
  const tokens = useAppDesignTokens();
43
43
  const insets = useSafeAreaInsets();
44
44
 
45
+ // Debug: Monitor component state
46
+ useEffect(() => {
47
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
48
+ console.log("[MainCategoryScreen] Component mounted/updated", {
49
+ mainCategoriesCount: mainCategories.length,
50
+ });
51
+ }
52
+ }, [mainCategories]);
53
+
45
54
  const styles = useMemo(() => createStyles(tokens), [tokens]);
46
55
 
47
56
  const handleCategoryPress = useCallback(
48
57
  (categoryId: string) => {
58
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
59
+ console.log("[MainCategoryScreen] Category pressed", { categoryId });
60
+ }
49
61
  onSelectCategory(categoryId);
50
62
  },
51
63
  [onSelectCategory]
@@ -53,8 +65,8 @@ export const MainCategoryScreen: React.FC<MainCategoryScreenProps> = ({
53
65
 
54
66
  const renderItem = useCallback(
55
67
  ({ item }: ListRenderItemInfo<ScenarioMainCategory>) => {
56
- const title = t(item.titleKey);
57
- const description = item.descriptionKey ? t(item.descriptionKey) : "";
68
+ const title = item.title;
69
+ const description = item.description || "";
58
70
 
59
71
  return (
60
72
  <TouchableOpacity
@@ -109,7 +121,7 @@ export const MainCategoryScreen: React.FC<MainCategoryScreenProps> = ({
109
121
  </TouchableOpacity>
110
122
  );
111
123
  },
112
- [t, tokens, styles, handleCategoryPress]
124
+ [tokens, styles, handleCategoryPress]
113
125
  );
114
126
 
115
127
  return (
@@ -3,7 +3,7 @@
3
3
  * Displays sub-categories for a selected main category
4
4
  */
5
5
 
6
- import React, { useMemo, useCallback } from "react";
6
+ import React, { useMemo, useCallback, useEffect } from "react";
7
7
  import {
8
8
  View,
9
9
  FlatList,
@@ -44,15 +44,38 @@ export const SubCategoryScreen: React.FC<SubCategoryScreenProps> = ({
44
44
  const tokens = useAppDesignTokens();
45
45
  const insets = useSafeAreaInsets();
46
46
 
47
- const filteredSubCategories = useMemo(
48
- () => subCategories.filter((sub) => sub.mainCategoryId === mainCategoryId),
49
- [subCategories, mainCategoryId]
50
- );
47
+ const filteredSubCategories = useMemo(() => {
48
+ const filtered = subCategories.filter((sub) => sub.mainCategoryId === mainCategoryId);
49
+
50
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
51
+ console.log("[SubCategoryScreen] Filtered sub-categories", {
52
+ mainCategoryId,
53
+ totalSubCategories: subCategories.length,
54
+ filteredCount: filtered.length,
55
+ sampleMainCategoryIds: subCategories.slice(0, 5).map(s => s.mainCategoryId),
56
+ });
57
+ }
58
+
59
+ return filtered;
60
+ }, [subCategories, mainCategoryId]);
61
+
62
+ // Debug: Monitor component state
63
+ useEffect(() => {
64
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
65
+ console.log("[SubCategoryScreen] Component mounted/updated", {
66
+ mainCategoryId,
67
+ filteredSubCategoriesCount: filteredSubCategories.length,
68
+ });
69
+ }
70
+ }, [mainCategoryId, filteredSubCategories]);
51
71
 
52
72
  const styles = useMemo(() => createStyles(tokens), [tokens]);
53
73
 
54
74
  const handleSubCategoryPress = useCallback(
55
75
  (subCategoryId: string) => {
76
+ if (typeof __DEV__ !== "undefined" && __DEV__) {
77
+ console.log("[SubCategoryScreen] Sub-category pressed", { subCategoryId });
78
+ }
56
79
  onSelectSubCategory(subCategoryId);
57
80
  },
58
81
  [onSelectSubCategory]
@@ -60,8 +83,8 @@ export const SubCategoryScreen: React.FC<SubCategoryScreenProps> = ({
60
83
 
61
84
  const renderItem = useCallback(
62
85
  ({ item }: ListRenderItemInfo<ScenarioSubCategory>) => {
63
- const title = t(item.titleKey);
64
- const description = item.descriptionKey ? t(item.descriptionKey) : "";
86
+ const title = item.title;
87
+ const description = item.description || "";
65
88
 
66
89
  return (
67
90
  <TouchableOpacity
@@ -116,7 +139,7 @@ export const SubCategoryScreen: React.FC<SubCategoryScreenProps> = ({
116
139
  </TouchableOpacity>
117
140
  );
118
141
  },
119
- [t, tokens, styles, handleSubCategoryPress]
142
+ [tokens, styles, handleSubCategoryPress]
120
143
  );
121
144
 
122
145
  return (