@umituz/react-native-ai-generation-content 1.23.5 → 1.24.1
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 +3 -2
- package/src/domain/entities/step-config.types.ts +133 -0
- package/src/domains/scenarios/configs/wizard-configs.ts +187 -0
- package/src/domains/scenarios/index.ts +8 -0
- package/src/domains/wizard/domain/entities/wizard-config.types.ts +214 -0
- package/src/domains/wizard/index.ts +62 -0
- package/src/domains/wizard/infrastructure/builders/dynamic-step-builder.ts +107 -0
- package/src/domains/wizard/infrastructure/renderers/step-renderer.tsx +106 -0
- package/src/domains/wizard/presentation/components/GenericWizardFlow.tsx +189 -0
- package/src/domains/wizard/presentation/hooks/usePhotoUploadState.ts +115 -0
- package/src/domains/wizard/presentation/screens/GenericPhotoUploadScreen.tsx +226 -0
- package/src/domains/wizard/presentation/steps/PhotoUploadStep.tsx +67 -0
- package/src/domains/wizard/presentation/steps/SelectionStep.tsx +244 -0
- package/src/domains/wizard/presentation/steps/TextInputStep.tsx +199 -0
- package/src/features/couple-future/domain/wizard-config.adapter.ts +76 -0
- package/src/features/couple-future/presentation/components/CoupleFutureWizard.tsx +19 -0
- package/src/index.ts +3 -0
- package/src/infrastructure/flow/step-builder.ts +226 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.24.1",
|
|
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",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"./content-moderation": "./src/domains/content-moderation/index.ts",
|
|
11
11
|
"./creations": "./src/domains/creations/index.ts",
|
|
12
12
|
"./face-detection": "./src/domains/face-detection/index.ts",
|
|
13
|
-
"./feature-background": "./src/domains/feature-background/index.ts"
|
|
13
|
+
"./feature-background": "./src/domains/feature-background/index.ts",
|
|
14
|
+
"./wizard": "./src/domains/wizard/index.ts"
|
|
14
15
|
},
|
|
15
16
|
"files": [
|
|
16
17
|
"src"
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic Step Configuration Types
|
|
3
|
+
* Configuration-driven wizard flow system
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { StepType } from "./flow-config.types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Photo Upload Step Config
|
|
10
|
+
*/
|
|
11
|
+
export interface PhotoUploadStepConfig {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
readonly label?: string; // "First Partner", "Your Photo", etc.
|
|
14
|
+
readonly titleKey?: string;
|
|
15
|
+
readonly subtitleKey?: string;
|
|
16
|
+
readonly showFaceDetection?: boolean;
|
|
17
|
+
readonly showNameInput?: boolean;
|
|
18
|
+
readonly showPhotoTips?: boolean;
|
|
19
|
+
readonly required?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Text Input Step Config
|
|
24
|
+
*/
|
|
25
|
+
export interface TextInputStepConfig {
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly titleKey?: string;
|
|
28
|
+
readonly placeholderKey?: string;
|
|
29
|
+
readonly minLength?: number;
|
|
30
|
+
readonly maxLength?: number;
|
|
31
|
+
readonly required?: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Style Selection Step Config
|
|
36
|
+
*/
|
|
37
|
+
export interface StyleSelectionStepConfig {
|
|
38
|
+
readonly id: string;
|
|
39
|
+
readonly titleKey?: string;
|
|
40
|
+
readonly styles: readonly string[]; // style IDs
|
|
41
|
+
readonly required?: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Duration Selection Step Config
|
|
46
|
+
*/
|
|
47
|
+
export interface DurationSelectionStepConfig {
|
|
48
|
+
readonly id: string;
|
|
49
|
+
readonly titleKey?: string;
|
|
50
|
+
readonly durations: readonly number[]; // seconds
|
|
51
|
+
readonly defaultDuration?: number;
|
|
52
|
+
readonly required?: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Next Step Decision Function
|
|
57
|
+
* Evaluates current state and determines next step
|
|
58
|
+
*/
|
|
59
|
+
export type NextStepDecision = (context: {
|
|
60
|
+
readonly values: Record<string, unknown>;
|
|
61
|
+
readonly currentStepId: string;
|
|
62
|
+
readonly completedSteps: readonly string[];
|
|
63
|
+
}) => string | null;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Step Definition with Configuration
|
|
67
|
+
*/
|
|
68
|
+
export interface DynamicStepDefinition {
|
|
69
|
+
readonly id: string;
|
|
70
|
+
readonly type: StepType;
|
|
71
|
+
readonly enabled?: boolean;
|
|
72
|
+
readonly required?: boolean;
|
|
73
|
+
readonly config?:
|
|
74
|
+
| PhotoUploadStepConfig
|
|
75
|
+
| TextInputStepConfig
|
|
76
|
+
| StyleSelectionStepConfig
|
|
77
|
+
| DurationSelectionStepConfig
|
|
78
|
+
| Record<string, unknown>;
|
|
79
|
+
readonly nextStep?: string | NextStepDecision;
|
|
80
|
+
readonly skipIf?: (context: { readonly values: Record<string, unknown> }) => boolean;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Feature Flow Configuration
|
|
85
|
+
* Defines complete flow for a feature/scenario
|
|
86
|
+
*/
|
|
87
|
+
export interface FeatureFlowConfig {
|
|
88
|
+
readonly id: string;
|
|
89
|
+
readonly name: string;
|
|
90
|
+
readonly steps: readonly DynamicStepDefinition[];
|
|
91
|
+
readonly initialStepId?: string;
|
|
92
|
+
readonly onComplete?: (data: Record<string, unknown>) => void | Promise<void>;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Scenario Step Configuration
|
|
97
|
+
* Simplified config for scenario-based flows
|
|
98
|
+
*/
|
|
99
|
+
export interface ScenarioStepConfig {
|
|
100
|
+
readonly photoUploads?: {
|
|
101
|
+
readonly count: number;
|
|
102
|
+
readonly labels?: readonly string[];
|
|
103
|
+
readonly showFaceDetection?: boolean;
|
|
104
|
+
readonly showNameInput?: boolean;
|
|
105
|
+
};
|
|
106
|
+
readonly textInput?: {
|
|
107
|
+
readonly enabled: boolean;
|
|
108
|
+
readonly required?: boolean;
|
|
109
|
+
readonly minLength?: number;
|
|
110
|
+
readonly maxLength?: number;
|
|
111
|
+
};
|
|
112
|
+
readonly styleSelection?: {
|
|
113
|
+
readonly enabled: boolean;
|
|
114
|
+
readonly required?: boolean;
|
|
115
|
+
readonly styles?: readonly string[];
|
|
116
|
+
};
|
|
117
|
+
readonly durationSelection?: {
|
|
118
|
+
readonly enabled: boolean;
|
|
119
|
+
readonly required?: boolean;
|
|
120
|
+
readonly durations?: readonly number[];
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Step Builder Result
|
|
126
|
+
*/
|
|
127
|
+
export interface BuiltStep {
|
|
128
|
+
readonly id: string;
|
|
129
|
+
readonly type: StepType;
|
|
130
|
+
readonly config: Record<string, unknown>;
|
|
131
|
+
readonly required: boolean;
|
|
132
|
+
readonly nextStep?: string | NextStepDecision;
|
|
133
|
+
}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wizard Configurations for ALL Scenarios
|
|
3
|
+
* Each scenario defines its wizard flow here
|
|
4
|
+
* NO feature-specific code - just configs!
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { WizardFeatureConfig } from "../../wizard/domain/entities/wizard-config.types";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* COUPLE SCENARIOS - 2 Photo Uploads
|
|
11
|
+
* romantic-kiss, ai-hug, couple-future, couple-ai-baby, etc.
|
|
12
|
+
*/
|
|
13
|
+
const createCoupleWizardConfig = (scenarioId: string): WizardFeatureConfig => ({
|
|
14
|
+
id: scenarioId,
|
|
15
|
+
name: scenarioId,
|
|
16
|
+
steps: [
|
|
17
|
+
{
|
|
18
|
+
id: "photo_a",
|
|
19
|
+
type: "photo_upload",
|
|
20
|
+
label: "First Partner",
|
|
21
|
+
titleKey: `${scenarioId}.partnerA.title`,
|
|
22
|
+
subtitleKey: `${scenarioId}.partnerA.subtitle`,
|
|
23
|
+
showFaceDetection: true,
|
|
24
|
+
showPhotoTips: true,
|
|
25
|
+
required: true,
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "photo_b",
|
|
29
|
+
type: "photo_upload",
|
|
30
|
+
label: "Second Partner",
|
|
31
|
+
titleKey: `${scenarioId}.partnerB.title`,
|
|
32
|
+
subtitleKey: `${scenarioId}.partnerB.subtitle`,
|
|
33
|
+
showFaceDetection: true,
|
|
34
|
+
showPhotoTips: true,
|
|
35
|
+
required: true,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* SINGLE PHOTO SCENARIOS
|
|
42
|
+
* image-to-video, face-swap (source), etc.
|
|
43
|
+
*/
|
|
44
|
+
const createSinglePhotoWizardConfig = (
|
|
45
|
+
scenarioId: string,
|
|
46
|
+
options?: {
|
|
47
|
+
requireStyle?: boolean;
|
|
48
|
+
requireDuration?: boolean;
|
|
49
|
+
},
|
|
50
|
+
): WizardFeatureConfig => {
|
|
51
|
+
const steps: WizardFeatureConfig["steps"] = [
|
|
52
|
+
{
|
|
53
|
+
id: "photo",
|
|
54
|
+
type: "photo_upload",
|
|
55
|
+
label: "Your Photo",
|
|
56
|
+
titleKey: `${scenarioId}.photo.title`,
|
|
57
|
+
subtitleKey: `${scenarioId}.photo.subtitle`,
|
|
58
|
+
showFaceDetection: false,
|
|
59
|
+
showPhotoTips: true,
|
|
60
|
+
required: true,
|
|
61
|
+
},
|
|
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
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* TEXT-TO-VIDEO SCENARIOS
|
|
103
|
+
*/
|
|
104
|
+
const createTextToVideoWizardConfig = (scenarioId: string): WizardFeatureConfig => ({
|
|
105
|
+
id: scenarioId,
|
|
106
|
+
name: scenarioId,
|
|
107
|
+
steps: [
|
|
108
|
+
{
|
|
109
|
+
id: "text_input",
|
|
110
|
+
type: "text_input",
|
|
111
|
+
titleKey: `${scenarioId}.prompt.title`,
|
|
112
|
+
subtitleKey: `${scenarioId}.prompt.subtitle`,
|
|
113
|
+
placeholderKey: `${scenarioId}.prompt.placeholder`,
|
|
114
|
+
minLength: 10,
|
|
115
|
+
maxLength: 500,
|
|
116
|
+
multiline: true,
|
|
117
|
+
required: true,
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: "style_selection",
|
|
121
|
+
type: "selection",
|
|
122
|
+
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,
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
/**
|
|
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
|
+
* Get wizard config for a scenario
|
|
170
|
+
*/
|
|
171
|
+
export const getScenarioWizardConfig = (scenarioId: string): WizardFeatureConfig | null => {
|
|
172
|
+
return SCENARIO_WIZARD_CONFIGS[scenarioId] || null;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Check if scenario has wizard config
|
|
177
|
+
*/
|
|
178
|
+
export const hasWizardConfig = (scenarioId: string): boolean => {
|
|
179
|
+
return scenarioId in SCENARIO_WIZARD_CONFIGS;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Get all scenario IDs with wizard configs
|
|
184
|
+
*/
|
|
185
|
+
export const getConfiguredScenarioIds = (): string[] => {
|
|
186
|
+
return Object.keys(SCENARIO_WIZARD_CONFIGS);
|
|
187
|
+
};
|
|
@@ -13,3 +13,11 @@ export { SCENARIOS } from "./infrastructure/ScenariosData";
|
|
|
13
13
|
|
|
14
14
|
// Utils
|
|
15
15
|
export { createStoryTemplate } from "./infrastructure/utils/scenario-utils";
|
|
16
|
+
|
|
17
|
+
// Wizard Configurations - Each scenario's wizard flow
|
|
18
|
+
export {
|
|
19
|
+
SCENARIO_WIZARD_CONFIGS,
|
|
20
|
+
getScenarioWizardConfig,
|
|
21
|
+
hasWizardConfig,
|
|
22
|
+
getConfiguredScenarioIds,
|
|
23
|
+
} from "./configs/wizard-configs";
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wizard Configuration Types
|
|
3
|
+
* Generic, feature-agnostic wizard configuration system
|
|
4
|
+
*
|
|
5
|
+
* All features use these same types - NO feature-specific wizards!
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { StepType } from "../../../../domain/entities/flow-config.types";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generic Step Configuration
|
|
12
|
+
* Base interface for all step configs
|
|
13
|
+
*/
|
|
14
|
+
export interface BaseStepConfig {
|
|
15
|
+
readonly id: string;
|
|
16
|
+
readonly type: StepType | string;
|
|
17
|
+
readonly enabled?: boolean;
|
|
18
|
+
readonly required?: boolean;
|
|
19
|
+
readonly titleKey?: string;
|
|
20
|
+
readonly subtitleKey?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Photo Upload Step Configuration
|
|
25
|
+
* Used by ANY feature that needs photo uploads (couple, face-swap, image-to-video, etc.)
|
|
26
|
+
*/
|
|
27
|
+
export interface PhotoUploadStepConfig extends BaseStepConfig {
|
|
28
|
+
readonly type: "photo_upload";
|
|
29
|
+
readonly label?: string; // "Partner A", "Your Photo", etc.
|
|
30
|
+
readonly showFaceDetection?: boolean;
|
|
31
|
+
readonly showNameInput?: boolean;
|
|
32
|
+
readonly showPhotoTips?: boolean;
|
|
33
|
+
readonly maxFileSizeMB?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Text Input Step Configuration
|
|
38
|
+
* Used by text-to-video, prompt-based features, etc.
|
|
39
|
+
*/
|
|
40
|
+
export interface TextInputStepConfig extends BaseStepConfig {
|
|
41
|
+
readonly type: "text_input";
|
|
42
|
+
readonly placeholderKey?: string;
|
|
43
|
+
readonly minLength?: number;
|
|
44
|
+
readonly maxLength?: number;
|
|
45
|
+
readonly multiline?: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Selection Step Configuration
|
|
50
|
+
* Generic selection (style, duration, aspect ratio, etc.)
|
|
51
|
+
*/
|
|
52
|
+
export interface SelectionStepConfig extends BaseStepConfig {
|
|
53
|
+
readonly type: "selection";
|
|
54
|
+
readonly selectionType: "style" | "duration" | "aspect_ratio" | "quality" | "custom";
|
|
55
|
+
readonly options: readonly {
|
|
56
|
+
readonly id: string;
|
|
57
|
+
readonly label: string;
|
|
58
|
+
readonly icon?: string;
|
|
59
|
+
readonly value: unknown;
|
|
60
|
+
}[];
|
|
61
|
+
readonly multiSelect?: boolean;
|
|
62
|
+
readonly defaultValue?: string | string[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Preview Step Configuration
|
|
67
|
+
* Shows preview before generation (scenario preview, settings review, etc.)
|
|
68
|
+
*/
|
|
69
|
+
export interface PreviewStepConfig extends BaseStepConfig {
|
|
70
|
+
readonly type: "preview";
|
|
71
|
+
readonly previewType: "scenario" | "settings" | "custom";
|
|
72
|
+
readonly showContinueButton?: boolean;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Union of all step config types
|
|
77
|
+
*/
|
|
78
|
+
export type WizardStepConfig =
|
|
79
|
+
| PhotoUploadStepConfig
|
|
80
|
+
| TextInputStepConfig
|
|
81
|
+
| SelectionStepConfig
|
|
82
|
+
| PreviewStepConfig
|
|
83
|
+
| BaseStepConfig;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Feature Flow Configuration
|
|
87
|
+
* Each feature (image-to-video, face-swap, couple-future, etc.) provides this
|
|
88
|
+
*/
|
|
89
|
+
export interface WizardFeatureConfig {
|
|
90
|
+
readonly id: string;
|
|
91
|
+
readonly name: string;
|
|
92
|
+
readonly steps: readonly WizardStepConfig[];
|
|
93
|
+
readonly translations?: {
|
|
94
|
+
readonly [key: string]: string | Record<string, string>;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Scenario-based Configuration Builder
|
|
100
|
+
* Shorthand for common patterns (couple scenarios, single photo, etc.)
|
|
101
|
+
*/
|
|
102
|
+
export interface ScenarioBasedConfig {
|
|
103
|
+
readonly photoCount?: number; // 0, 1, 2, etc.
|
|
104
|
+
readonly photoLabels?: readonly string[];
|
|
105
|
+
readonly requireText?: boolean;
|
|
106
|
+
readonly requireStyleSelection?: boolean;
|
|
107
|
+
readonly requireDurationSelection?: boolean;
|
|
108
|
+
readonly customSteps?: readonly WizardStepConfig[];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Build wizard config from scenario shorthand
|
|
113
|
+
*/
|
|
114
|
+
export const buildWizardConfigFromScenario = (
|
|
115
|
+
scenarioId: string,
|
|
116
|
+
config: ScenarioBasedConfig,
|
|
117
|
+
): WizardFeatureConfig => {
|
|
118
|
+
const steps: WizardStepConfig[] = [];
|
|
119
|
+
|
|
120
|
+
// Add photo upload steps (dynamic count!)
|
|
121
|
+
if (config.photoCount && config.photoCount > 0) {
|
|
122
|
+
for (let i = 0; i < config.photoCount; i++) {
|
|
123
|
+
steps.push({
|
|
124
|
+
id: `photo_${i}`,
|
|
125
|
+
type: "photo_upload",
|
|
126
|
+
label: config.photoLabels?.[i] || `Photo ${i + 1}`,
|
|
127
|
+
showFaceDetection: true,
|
|
128
|
+
showPhotoTips: true,
|
|
129
|
+
required: true,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Add text input
|
|
135
|
+
if (config.requireText) {
|
|
136
|
+
steps.push({
|
|
137
|
+
id: "text_input",
|
|
138
|
+
type: "text_input",
|
|
139
|
+
required: true,
|
|
140
|
+
minLength: 10,
|
|
141
|
+
maxLength: 500,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Add style selection
|
|
146
|
+
if (config.requireStyleSelection) {
|
|
147
|
+
steps.push({
|
|
148
|
+
id: "style_selection",
|
|
149
|
+
type: "selection",
|
|
150
|
+
selectionType: "style",
|
|
151
|
+
options: [], // Provided by feature
|
|
152
|
+
required: true,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Add duration selection
|
|
157
|
+
if (config.requireDurationSelection) {
|
|
158
|
+
steps.push({
|
|
159
|
+
id: "duration_selection",
|
|
160
|
+
type: "selection",
|
|
161
|
+
selectionType: "duration",
|
|
162
|
+
options: [
|
|
163
|
+
{ id: "5s", label: "5 seconds", value: 5 },
|
|
164
|
+
{ id: "10s", label: "10 seconds", value: 10 },
|
|
165
|
+
{ id: "15s", label: "15 seconds", value: 15 },
|
|
166
|
+
],
|
|
167
|
+
required: true,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Add custom steps
|
|
172
|
+
if (config.customSteps) {
|
|
173
|
+
steps.push(...config.customSteps);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return {
|
|
177
|
+
id: scenarioId,
|
|
178
|
+
name: scenarioId,
|
|
179
|
+
steps,
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Pre-configured scenarios for common use cases
|
|
185
|
+
*/
|
|
186
|
+
export const WIZARD_PRESETS = {
|
|
187
|
+
// Couple/Partner features (2 photos)
|
|
188
|
+
COUPLE: {
|
|
189
|
+
photoCount: 2,
|
|
190
|
+
photoLabels: ["First Partner", "Second Partner"],
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
// Single photo features
|
|
194
|
+
SINGLE_PHOTO: {
|
|
195
|
+
photoCount: 1,
|
|
196
|
+
photoLabels: ["Your Photo"],
|
|
197
|
+
requireStyleSelection: true,
|
|
198
|
+
requireDurationSelection: true,
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
// Text-only features
|
|
202
|
+
TEXT_ONLY: {
|
|
203
|
+
photoCount: 0,
|
|
204
|
+
requireText: true,
|
|
205
|
+
requireStyleSelection: true,
|
|
206
|
+
requireDurationSelection: true,
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
// Face swap (2 photos, specific requirements)
|
|
210
|
+
FACE_SWAP: {
|
|
211
|
+
photoCount: 2,
|
|
212
|
+
photoLabels: ["Source Face", "Target Face"],
|
|
213
|
+
},
|
|
214
|
+
} as const;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wizard Domain - Public API
|
|
3
|
+
* Generic, configuration-driven wizard system
|
|
4
|
+
* Works for ALL features - NO feature-specific code!
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Domain Entities - Configuration Types
|
|
8
|
+
export type {
|
|
9
|
+
BaseStepConfig,
|
|
10
|
+
PhotoUploadStepConfig,
|
|
11
|
+
TextInputStepConfig,
|
|
12
|
+
SelectionStepConfig,
|
|
13
|
+
PreviewStepConfig,
|
|
14
|
+
WizardStepConfig,
|
|
15
|
+
WizardFeatureConfig,
|
|
16
|
+
ScenarioBasedConfig,
|
|
17
|
+
} from "./domain/entities/wizard-config.types";
|
|
18
|
+
|
|
19
|
+
export { buildWizardConfigFromScenario, WIZARD_PRESETS } from "./domain/entities/wizard-config.types";
|
|
20
|
+
|
|
21
|
+
// Infrastructure - Builders
|
|
22
|
+
export {
|
|
23
|
+
buildFlowStepsFromWizard,
|
|
24
|
+
getPhotoUploadCount,
|
|
25
|
+
getStepConfig,
|
|
26
|
+
quickBuildWizard,
|
|
27
|
+
} from "./infrastructure/builders/dynamic-step-builder";
|
|
28
|
+
|
|
29
|
+
// Infrastructure - Renderers
|
|
30
|
+
export { renderStep } from "./infrastructure/renderers/step-renderer";
|
|
31
|
+
export type { StepRendererProps } from "./infrastructure/renderers/step-renderer";
|
|
32
|
+
|
|
33
|
+
// Presentation - Components
|
|
34
|
+
export { GenericWizardFlow } from "./presentation/components/GenericWizardFlow";
|
|
35
|
+
export type { GenericWizardFlowProps } from "./presentation/components/GenericWizardFlow";
|
|
36
|
+
|
|
37
|
+
// Presentation - Steps
|
|
38
|
+
export { PhotoUploadStep } from "./presentation/steps/PhotoUploadStep";
|
|
39
|
+
export type { PhotoUploadStepProps } from "./presentation/steps/PhotoUploadStep";
|
|
40
|
+
|
|
41
|
+
export { TextInputStep } from "./presentation/steps/TextInputStep";
|
|
42
|
+
export type { TextInputStepProps } from "./presentation/steps/TextInputStep";
|
|
43
|
+
|
|
44
|
+
export { SelectionStep } from "./presentation/steps/SelectionStep";
|
|
45
|
+
export type { SelectionStepProps } from "./presentation/steps/SelectionStep";
|
|
46
|
+
|
|
47
|
+
// Presentation - Screens
|
|
48
|
+
export { GenericPhotoUploadScreen } from "./presentation/screens/GenericPhotoUploadScreen";
|
|
49
|
+
export type {
|
|
50
|
+
PhotoUploadScreenProps,
|
|
51
|
+
PhotoUploadScreenConfig,
|
|
52
|
+
PhotoUploadScreenTranslations,
|
|
53
|
+
} from "./presentation/screens/GenericPhotoUploadScreen";
|
|
54
|
+
|
|
55
|
+
// Presentation - Hooks
|
|
56
|
+
export { usePhotoUploadState } from "./presentation/hooks/usePhotoUploadState";
|
|
57
|
+
export type {
|
|
58
|
+
UsePhotoUploadStateProps,
|
|
59
|
+
UsePhotoUploadStateReturn,
|
|
60
|
+
PhotoUploadConfig,
|
|
61
|
+
PhotoUploadTranslations,
|
|
62
|
+
} from "./presentation/hooks/usePhotoUploadState";
|