@umituz/react-native-ai-generation-content 1.26.8 → 1.26.10

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 (26) hide show
  1. package/package.json +1 -1
  2. package/src/domains/generation/application/generation-strategy.factory.ts +1 -3
  3. package/src/domains/generation/infrastructure/executors/executor-factory.ts +1 -1
  4. package/src/domains/generation/infrastructure/flow/step-builder.ts +2 -11
  5. package/src/domains/generation/infrastructure/flow/useFlow.ts +1 -1
  6. package/src/domains/generation/infrastructure/flow/useFlowStore.ts +1 -1
  7. package/src/domains/generation/presentation/useAIGeneration.hook.ts +9 -3
  8. package/src/domains/generation/wizard/domain/entities/wizard-config.types.ts +1 -1
  9. package/src/domains/generation/wizard/index.ts +0 -29
  10. package/src/domains/generation/wizard/infrastructure/builders/dynamic-step-builder.ts +2 -3
  11. package/src/domains/generation/wizard/infrastructure/strategies/wizard-strategy.factory.ts +7 -7
  12. package/src/domains/generation/wizard/presentation/hooks/usePhotoUploadState.ts +1 -1
  13. package/src/domains/generation/wizard/presentation/hooks/useWizardGeneration.ts +2 -2
  14. package/src/domains/scenarios/configs/wizard-configs.ts +1 -1
  15. package/src/index.ts +1 -1
  16. package/src/infrastructure/wrappers/synchronous-generation.wrapper.ts +3 -2
  17. package/src/presentation/hooks/generation/index.ts +0 -1
  18. package/src/presentation/hooks/generation/orchestrator.ts +8 -3
  19. package/src/presentation/hooks/index.ts +0 -1
  20. package/src/domains/generation/wizard/infrastructure/renderers/step-renderer.tsx +0 -107
  21. package/src/domains/generation/wizard/presentation/components/GenericWizardFlow.tsx +0 -297
  22. package/src/domains/generation/wizard/presentation/screens/GeneratingScreen.tsx +0 -123
  23. package/src/domains/generation/wizard/presentation/screens/GenericPhotoUploadScreen.tsx +0 -211
  24. package/src/domains/generation/wizard/presentation/steps/PhotoUploadStep.tsx +0 -64
  25. package/src/domains/generation/wizard/presentation/steps/SelectionStep.tsx +0 -244
  26. package/src/domains/generation/wizard/presentation/steps/TextInputStep.tsx +0 -199
@@ -1,244 +0,0 @@
1
- /**
2
- * Generic Selection Step
3
- * Used by ANY feature that needs selection
4
- * (style, duration, aspect ratio, quality, etc.)
5
- */
6
-
7
- import React, { useState, useCallback } from "react";
8
- import { View, StyleSheet, TouchableOpacity, ScrollView } from "react-native";
9
- import { useAppDesignTokens, AtomicText } from "@umituz/react-native-design-system";
10
- import type { SelectionStepConfig } from "../../domain/entities/wizard-config.types";
11
-
12
- export interface SelectionStepProps {
13
- readonly config: SelectionStepConfig;
14
- readonly onContinue: (selected: string | string[]) => void;
15
- readonly onBack: () => void;
16
- readonly t: (key: string) => string;
17
- readonly translations?: Record<string, string>;
18
- }
19
-
20
- export const SelectionStep: React.FC<SelectionStepProps> = ({
21
- config,
22
- onContinue,
23
- onBack,
24
- t,
25
- translations,
26
- }) => {
27
- const tokens = useAppDesignTokens();
28
- const [selectedIds, setSelectedIds] = useState<string[]>(
29
- config.defaultValue
30
- ? Array.isArray(config.defaultValue)
31
- ? config.defaultValue
32
- : [config.defaultValue]
33
- : [],
34
- );
35
-
36
- if (typeof __DEV__ !== "undefined" && __DEV__) {
37
- console.log("[SelectionStep] Rendering", {
38
- stepId: config.id,
39
- selectionType: config.selectionType,
40
- multiSelect: config.multiSelect,
41
- selectedCount: selectedIds.length,
42
- });
43
- }
44
-
45
- const handleOptionPress = useCallback(
46
- (optionId: string) => {
47
- if (config.multiSelect) {
48
- // Multi-select: toggle option
49
- setSelectedIds((prev) => {
50
- if (prev.includes(optionId)) {
51
- return prev.filter((id) => id !== optionId);
52
- }
53
- return [...prev, optionId];
54
- });
55
- } else {
56
- // Single-select: replace selection
57
- setSelectedIds([optionId]);
58
- }
59
- },
60
- [config.multiSelect],
61
- );
62
-
63
- const handleContinue = useCallback(() => {
64
- if (selectedIds.length === 0) {
65
- return; // Don't allow continue without selection
66
- }
67
-
68
- if (typeof __DEV__ !== "undefined" && __DEV__) {
69
- console.log("[SelectionStep] Continue", {
70
- stepId: config.id,
71
- selected: config.multiSelect ? selectedIds : selectedIds[0],
72
- });
73
- }
74
-
75
- // Return single value for single-select, array for multi-select
76
- onContinue(config.multiSelect ? selectedIds : selectedIds[0]);
77
- }, [selectedIds, config, onContinue]);
78
-
79
- return (
80
- <View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
81
- {/* Header */}
82
- <View style={styles.header}>
83
- <TouchableOpacity onPress={onBack} style={styles.backButton}>
84
- <AtomicText type="body">{t("common.back")}</AtomicText>
85
- </TouchableOpacity>
86
- </View>
87
-
88
- {/* Content */}
89
- <ScrollView style={styles.content}>
90
- {/* Title */}
91
- {config.titleKey && (
92
- <AtomicText type="heading2" style={styles.title}>
93
- {t(config.titleKey)}
94
- </AtomicText>
95
- )}
96
-
97
- {/* Subtitle */}
98
- {config.subtitleKey && (
99
- <AtomicText type="body" style={styles.subtitle}>
100
- {t(config.subtitleKey)}
101
- </AtomicText>
102
- )}
103
-
104
- {/* Options */}
105
- <View style={styles.optionsContainer}>
106
- {config.options.map((option) => {
107
- const isSelected = selectedIds.includes(option.id);
108
- return (
109
- <TouchableOpacity
110
- key={option.id}
111
- style={[
112
- styles.optionCard,
113
- {
114
- backgroundColor: isSelected
115
- ? tokens.colors.primaryContainer
116
- : tokens.colors.backgroundSecondary,
117
- borderColor: isSelected ? tokens.colors.primary : tokens.colors.border,
118
- },
119
- ]}
120
- onPress={() => handleOptionPress(option.id)}
121
- >
122
- {/* Option Icon (if provided) */}
123
- {option.icon && (
124
- <View style={styles.iconContainer}>
125
- <AtomicText type="heading3">{option.icon}</AtomicText>
126
- </View>
127
- )}
128
-
129
- {/* Option Label */}
130
- <AtomicText
131
- type="body"
132
- style={[
133
- styles.optionLabel,
134
- {
135
- color: isSelected ? tokens.colors.onPrimaryContainer : tokens.colors.textPrimary,
136
- },
137
- ]}
138
- >
139
- {option.label}
140
- </AtomicText>
141
-
142
- {/* Selection Indicator */}
143
- {isSelected && (
144
- <View
145
- style={[
146
- styles.selectedIndicator,
147
- {
148
- backgroundColor: tokens.colors.primary,
149
- },
150
- ]}
151
- >
152
- <AtomicText type="caption" style={{ color: tokens.colors.textOnPrimary }}>
153
-
154
- </AtomicText>
155
- </View>
156
- )}
157
- </TouchableOpacity>
158
- );
159
- })}
160
- </View>
161
- </ScrollView>
162
-
163
- {/* Continue Button */}
164
- <View style={styles.footer}>
165
- <TouchableOpacity
166
- style={[
167
- styles.continueButton,
168
- {
169
- backgroundColor: selectedIds.length > 0 ? tokens.colors.primary : tokens.colors.disabled,
170
- },
171
- ]}
172
- onPress={handleContinue}
173
- disabled={selectedIds.length === 0}
174
- >
175
- <AtomicText
176
- type="buttonLarge"
177
- style={{
178
- color: selectedIds.length > 0 ? tokens.colors.textOnPrimary : tokens.colors.textDisabled,
179
- }}
180
- >
181
- {t("common.continue")}
182
- </AtomicText>
183
- </TouchableOpacity>
184
- </View>
185
- </View>
186
- );
187
- };
188
-
189
- const styles = StyleSheet.create({
190
- container: {
191
- flex: 1,
192
- },
193
- header: {
194
- padding: 16,
195
- },
196
- backButton: {
197
- alignSelf: "flex-start",
198
- },
199
- content: {
200
- flex: 1,
201
- padding: 16,
202
- },
203
- title: {
204
- marginBottom: 8,
205
- },
206
- subtitle: {
207
- marginBottom: 24,
208
- },
209
- optionsContainer: {
210
- gap: 12,
211
- },
212
- optionCard: {
213
- padding: 16,
214
- borderRadius: 12,
215
- borderWidth: 2,
216
- flexDirection: "row",
217
- alignItems: "center",
218
- gap: 12,
219
- },
220
- iconContainer: {
221
- width: 40,
222
- height: 40,
223
- alignItems: "center",
224
- justifyContent: "center",
225
- },
226
- optionLabel: {
227
- flex: 1,
228
- },
229
- selectedIndicator: {
230
- width: 24,
231
- height: 24,
232
- borderRadius: 12,
233
- alignItems: "center",
234
- justifyContent: "center",
235
- },
236
- footer: {
237
- padding: 16,
238
- },
239
- continueButton: {
240
- padding: 16,
241
- borderRadius: 8,
242
- alignItems: "center",
243
- },
244
- });
@@ -1,199 +0,0 @@
1
- /**
2
- * Generic Text Input Step
3
- * Used by ANY feature that needs text input
4
- * (text-to-video, prompt-based generation, etc.)
5
- */
6
-
7
- import React, { useState, useCallback } from "react";
8
- import { View, StyleSheet, TextInput, TouchableOpacity } from "react-native";
9
- import { useAppDesignTokens, AtomicText } from "@umituz/react-native-design-system";
10
- import type { TextInputStepConfig } from "../../domain/entities/wizard-config.types";
11
-
12
- export interface TextInputStepProps {
13
- readonly config: TextInputStepConfig;
14
- readonly onContinue: (text: string) => void;
15
- readonly onBack: () => void;
16
- readonly t: (key: string) => string;
17
- readonly translations?: Record<string, string>;
18
- }
19
-
20
- export const TextInputStep: React.FC<TextInputStepProps> = ({
21
- config,
22
- onContinue,
23
- onBack,
24
- t,
25
- translations,
26
- }) => {
27
- const tokens = useAppDesignTokens();
28
- const [text, setText] = useState("");
29
- const [error, setError] = useState<string | null>(null);
30
-
31
- if (typeof __DEV__ !== "undefined" && __DEV__) {
32
- console.log("[TextInputStep] Rendering", {
33
- stepId: config.id,
34
- textLength: text.length,
35
- minLength: config.minLength,
36
- maxLength: config.maxLength,
37
- });
38
- }
39
-
40
- const handleContinue = useCallback(() => {
41
- // Validate text length
42
- if (config.minLength && text.length < config.minLength) {
43
- setError(t("textInput.errors.tooShort"));
44
- return;
45
- }
46
-
47
- if (config.maxLength && text.length > config.maxLength) {
48
- setError(t("textInput.errors.tooLong"));
49
- return;
50
- }
51
-
52
- if (text.trim().length === 0) {
53
- setError(t("textInput.errors.required"));
54
- return;
55
- }
56
-
57
- if (typeof __DEV__ !== "undefined" && __DEV__) {
58
- console.log("[TextInputStep] Continue", { stepId: config.id, text });
59
- }
60
-
61
- onContinue(text);
62
- }, [text, config, onContinue, t]);
63
-
64
- const handleTextChange = useCallback((newText: string) => {
65
- setText(newText);
66
- setError(null); // Clear error on change
67
- }, []);
68
-
69
- return (
70
- <View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
71
- {/* Header */}
72
- <View style={styles.header}>
73
- <TouchableOpacity onPress={onBack} style={styles.backButton}>
74
- <AtomicText type="body">{t("common.back")}</AtomicText>
75
- </TouchableOpacity>
76
- </View>
77
-
78
- {/* Content */}
79
- <View style={styles.content}>
80
- {/* Title */}
81
- {config.titleKey && (
82
- <AtomicText type="heading2" style={styles.title}>
83
- {t(config.titleKey)}
84
- </AtomicText>
85
- )}
86
-
87
- {/* Subtitle */}
88
- {config.subtitleKey && (
89
- <AtomicText type="body" style={styles.subtitle}>
90
- {t(config.subtitleKey)}
91
- </AtomicText>
92
- )}
93
-
94
- {/* Text Input */}
95
- <TextInput
96
- style={[
97
- styles.input,
98
- config.multiline && styles.multilineInput,
99
- {
100
- backgroundColor: tokens.colors.backgroundSecondary,
101
- borderColor: error ? tokens.colors.error : tokens.colors.border,
102
- color: tokens.colors.textPrimary,
103
- },
104
- ]}
105
- value={text}
106
- onChangeText={handleTextChange}
107
- placeholder={config.placeholderKey ? t(config.placeholderKey) : t("textInput.placeholder")}
108
- placeholderTextColor={tokens.colors.textSecondary}
109
- multiline={config.multiline}
110
- numberOfLines={config.multiline ? 5 : 1}
111
- maxLength={config.maxLength}
112
- />
113
-
114
- {/* Character Count */}
115
- {config.maxLength && (
116
- <AtomicText type="caption" style={styles.characterCount}>
117
- {text.length} / {config.maxLength}
118
- </AtomicText>
119
- )}
120
-
121
- {/* Error Message */}
122
- {error && (
123
- <AtomicText type="body" style={[styles.error, { color: tokens.colors.error }]}>
124
- {error}
125
- </AtomicText>
126
- )}
127
- </View>
128
-
129
- {/* Continue Button */}
130
- <View style={styles.footer}>
131
- <TouchableOpacity
132
- style={[
133
- styles.continueButton,
134
- {
135
- backgroundColor: text.trim().length > 0 ? tokens.colors.primary : tokens.colors.disabled,
136
- },
137
- ]}
138
- onPress={handleContinue}
139
- disabled={text.trim().length === 0}
140
- >
141
- <AtomicText
142
- type="buttonLarge"
143
- style={{ color: text.trim().length > 0 ? tokens.colors.textOnPrimary : tokens.colors.textDisabled }}
144
- >
145
- {t("common.continue")}
146
- </AtomicText>
147
- </TouchableOpacity>
148
- </View>
149
- </View>
150
- );
151
- };
152
-
153
- const styles = StyleSheet.create({
154
- container: {
155
- flex: 1,
156
- },
157
- header: {
158
- padding: 16,
159
- },
160
- backButton: {
161
- alignSelf: "flex-start",
162
- },
163
- content: {
164
- flex: 1,
165
- padding: 16,
166
- },
167
- title: {
168
- marginBottom: 8,
169
- },
170
- subtitle: {
171
- marginBottom: 24,
172
- },
173
- input: {
174
- borderWidth: 1,
175
- borderRadius: 8,
176
- padding: 12,
177
- fontSize: 16,
178
- marginBottom: 8,
179
- },
180
- multilineInput: {
181
- height: 120,
182
- textAlignVertical: "top",
183
- },
184
- characterCount: {
185
- textAlign: "right",
186
- marginBottom: 8,
187
- },
188
- error: {
189
- marginTop: 8,
190
- },
191
- footer: {
192
- padding: 16,
193
- },
194
- continueButton: {
195
- padding: 16,
196
- borderRadius: 8,
197
- alignItems: "center",
198
- },
199
- });