@umituz/react-native-ai-generation-content 1.26.7 → 1.26.9

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 (29) 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 +13 -15
  12. package/src/domains/generation/wizard/presentation/hooks/usePhotoUploadState.ts +2 -2
  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/generation/useAIGenerateState.ts +3 -0
  20. package/src/presentation/hooks/index.ts +0 -1
  21. package/src/presentation/layouts/types/layout-props.ts +30 -4
  22. package/src/domains/generation/wizard/infrastructure/renderers/step-renderer.tsx +0 -107
  23. package/src/domains/generation/wizard/presentation/components/GenericWizardFlow.tsx +0 -297
  24. package/src/domains/generation/wizard/presentation/screens/GeneratingScreen.tsx +0 -123
  25. package/src/domains/generation/wizard/presentation/screens/GenericPhotoUploadScreen.tsx +0 -222
  26. package/src/domains/generation/wizard/presentation/steps/PhotoUploadStep.tsx +0 -66
  27. package/src/domains/generation/wizard/presentation/steps/SelectionStep.tsx +0 -244
  28. package/src/domains/generation/wizard/presentation/steps/TextInputStep.tsx +0 -199
  29. package/src/presentation/hooks/generation/useAIFeatureGeneration.ts +0 -180
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-ai-generation-content",
3
- "version": "1.26.7",
3
+ "version": "1.26.9",
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",
@@ -3,11 +3,9 @@
3
3
  * Creates generation strategies from feature configs
4
4
  */
5
5
 
6
- import type { GenerationStrategy } from "../../../presentation/hooks/generation/orchestrator";
6
+ import type { GenerationStrategy } from "../../../presentation/hooks/generation/types";
7
7
  import type { FeatureConfig } from "../domain/feature-config.types";
8
8
  import type {
9
- ImageGenerationInput,
10
- VideoGenerationInput,
11
9
  ImageGenerationOutput,
12
10
  VideoGenerationOutput,
13
11
  } from "../domain/generation.types";
@@ -3,7 +3,7 @@
3
3
  * Creates appropriate executor based on generation type
4
4
  */
5
5
 
6
- import type { GenerationExecutor } from "../../domains/generation/domain/generation.types";
6
+ import type { GenerationExecutor } from "../../domain/generation.types";
7
7
  import { ImageExecutor } from "./image-executor";
8
8
  import { VideoExecutor } from "./video-executor";
9
9
 
@@ -3,13 +3,12 @@
3
3
  * Builds step definitions from configuration
4
4
  */
5
5
 
6
- import { StepType } from "../../domain/entities/flow-config.types";
6
+ import { StepType } from "../../../../domain/entities/flow-config.types";
7
7
  import type {
8
8
  ScenarioStepConfig,
9
9
  DynamicStepDefinition,
10
- BuiltStep,
11
10
  PhotoUploadStepConfig,
12
- } from "../../domain/entities/step-config.types";
11
+ } from "../../../../domain/entities/step-config.types";
13
12
 
14
13
  /**
15
14
  * Build steps from scenario configuration
@@ -121,14 +120,6 @@ export const resolveNextStep = (
121
120
  const currentStep = steps.find((s) => s.id === currentStepId);
122
121
  if (!currentStep) return null;
123
122
 
124
- // Check if should skip based on skipIf condition
125
- const nextStepCandidates = steps.filter((s) => {
126
- if (s.skipIf && s.skipIf({ values: context.values })) {
127
- return false;
128
- }
129
- return true;
130
- });
131
-
132
123
  // If nextStep is a function, call it
133
124
  if (typeof currentStep.nextStep === "function") {
134
125
  return currentStep.nextStep({
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { useRef, useCallback, useMemo } from "react";
7
7
  import { createFlowStore, type FlowStoreType } from "./useFlowStore";
8
- import type { FlowState, FlowActions, StepDefinition, FlowUploadedImageData } from "../../domain/entities/flow-config.types";
8
+ import type { FlowState, FlowActions, StepDefinition, FlowUploadedImageData } from "../../../../domain/entities/flow-config.types";
9
9
 
10
10
  interface UseFlowConfig {
11
11
  steps: readonly StepDefinition[];
@@ -9,7 +9,7 @@ import type {
9
9
  FlowActions,
10
10
  FlowUploadedImageData,
11
11
  StepDefinition,
12
- } from "../../domain/entities/flow-config.types";
12
+ } from "../../../../domain/entities/flow-config.types";
13
13
 
14
14
  interface FlowStoreState extends FlowState {
15
15
  stepDefinitions: readonly StepDefinition[];
@@ -48,7 +48,7 @@ export interface UseAIGenerationProps {
48
48
 
49
49
  export interface UseAIGenerationReturn {
50
50
  /** Trigger generation */
51
- generate: (input: unknown) => Promise<void>;
51
+ generate: (input: unknown) => Promise<unknown>;
52
52
 
53
53
  /** Whether generation is in progress */
54
54
  isGenerating: boolean;
@@ -92,9 +92,15 @@ export function useAIGeneration(
92
92
  // Use orchestrator for lifecycle management
93
93
  const orchestrator = useGenerationOrchestrator(strategy, {
94
94
  userId,
95
- alertMessages,
95
+ alertMessages: alertMessages || {
96
+ networkError: "No internet connection",
97
+ policyViolation: "Content policy violation",
98
+ saveFailed: "Failed to save",
99
+ creditFailed: "Failed to deduct credits",
100
+ unknown: "An error occurred",
101
+ },
96
102
  onSuccess,
97
- onError,
103
+ onError: onError ? (error) => onError(error.message) : undefined,
98
104
  onCreditsExhausted,
99
105
  });
100
106
 
@@ -5,7 +5,7 @@
5
5
  * All features use these same types - NO feature-specific wizards!
6
6
  */
7
7
 
8
- import type { StepType } from "../../../../domain/entities/flow-config.types";
8
+ import type { StepType } from "../../../../../domain/entities/flow-config.types";
9
9
 
10
10
  /**
11
11
  * Generic Step Configuration
@@ -26,35 +26,6 @@ export {
26
26
  quickBuildWizard,
27
27
  } from "./infrastructure/builders/dynamic-step-builder";
28
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
- export { GeneratingScreen } from "./presentation/screens/GeneratingScreen";
56
- export type { GeneratingScreenProps } from "./presentation/screens/GeneratingScreen";
57
-
58
29
  // Presentation - Hooks
59
30
  export { usePhotoUploadState } from "./presentation/hooks/usePhotoUploadState";
60
31
  export type {
@@ -4,13 +4,12 @@
4
4
  * Works with ANY feature - completely generic!
5
5
  */
6
6
 
7
- import { StepType } from "../../../../domain/entities/flow-config.types";
8
- import type { StepDefinition } from "../../../../domain/entities/flow-config.types";
7
+ import { StepType } from "../../../../../domain/entities/flow-config.types";
8
+ import type { StepDefinition } from "../../../../../domain/entities/flow-config.types";
9
9
  import type {
10
10
  WizardFeatureConfig,
11
11
  WizardStepConfig,
12
12
  ScenarioBasedConfig,
13
- buildWizardConfigFromScenario,
14
13
  } from "../../domain/entities/wizard-config.types";
15
14
 
16
15
  /**
@@ -5,13 +5,11 @@
5
5
  */
6
6
 
7
7
  import { readFileAsBase64 } from "@umituz/react-native-design-system";
8
- import type { GenerationStrategy } from "../../../../presentation/hooks/generation/types";
9
- import type { VideoFeatureType } from "../../../../domain/interfaces";
10
- import { executeVideoFeature } from "../../../../infrastructure/services/video-feature-executor.service";
11
- import { createCreationsRepository } from "../../../creations/infrastructure/adapters";
12
- import { enhanceCouplePrompt } from "../../../../features/couple-future/infrastructure/couplePromptEnhancer";
13
- import type { CoupleFeatureSelection } from "../../../../features/couple-future/domain/types";
14
- import type { WizardOutputType, WizardScenarioData } from "../../presentation/hooks/useWizardGeneration";
8
+ import type { GenerationStrategy } from "../../../../../presentation/hooks/generation/types";
9
+ import type { VideoFeatureType } from "../../../../../domain/interfaces";
10
+ import { executeVideoFeature } from "../../../../../infrastructure/services/video-feature-executor.service";
11
+ import { createCreationsRepository } from "../../../../creations/infrastructure/adapters";
12
+ import type { WizardScenarioData } from "../../presentation/hooks/useWizardGeneration";
15
13
 
16
14
  declare const __DEV__: boolean;
17
15
 
@@ -52,7 +50,7 @@ async function executeImageGeneration(
52
50
  });
53
51
  }
54
52
 
55
- const { providerRegistry } = await import("../../../../infrastructure/services/provider-registry.service");
53
+ const { providerRegistry } = await import("../../../../../infrastructure/services/provider-registry.service");
56
54
 
57
55
  const provider = providerRegistry.getActiveProvider();
58
56
  if (!provider || !provider.isInitialized()) {
@@ -179,29 +177,29 @@ async function buildGenerationInput(
179
177
 
180
178
  // For image generation, enhance prompt with style selections
181
179
  if (outputType === "image") {
182
- const selections: CoupleFeatureSelection = {};
180
+ const styleEnhancements: string[] = [];
183
181
 
184
182
  // Romantic mood (multi-select array)
185
183
  const romanticMoods = wizardData.selection_romantic_mood as string[] | undefined;
186
184
  if (romanticMoods && romanticMoods.length > 0) {
187
- selections.romanticMoods = romanticMoods;
185
+ styleEnhancements.push(`Mood: ${romanticMoods.join(", ")}`);
188
186
  }
189
187
 
190
188
  // Art style (single select)
191
189
  const artStyle = wizardData.selection_art_style as string | undefined;
192
190
  if (artStyle && artStyle !== "original") {
193
- selections.artStyle = artStyle;
191
+ styleEnhancements.push(`Art style: ${artStyle}`);
194
192
  }
195
193
 
196
194
  // Artist style (single select)
197
195
  const artist = wizardData.selection_artist_style as string | undefined;
198
196
  if (artist && artist !== "original") {
199
- selections.artist = artist;
197
+ styleEnhancements.push(`Artist style: ${artist}`);
200
198
  }
201
199
 
202
200
  // Enhance prompt with selected styles
203
- if (Object.keys(selections).length > 0) {
204
- prompt = enhanceCouplePrompt(prompt, selections);
201
+ if (styleEnhancements.length > 0) {
202
+ prompt = `${prompt}. ${styleEnhancements.join(", ")}`;
205
203
  }
206
204
 
207
205
  return {
@@ -247,7 +245,7 @@ export interface CreateWizardStrategyOptions {
247
245
  export const createWizardStrategy = (
248
246
  options: CreateWizardStrategyOptions,
249
247
  ): GenerationStrategy<WizardGenerationInput, WizardGenerationResult> => {
250
- const { scenario, wizardData, collectionName = "creations" } = options;
248
+ const { scenario, collectionName = "creations" } = options;
251
249
  const repository = createCreationsRepository(collectionName);
252
250
  const outputType = scenario.outputType || "video";
253
251
  const videoFeatureType = getVideoFeatureType(scenario.id);
@@ -7,7 +7,7 @@
7
7
  import { useState, useCallback } from "react";
8
8
  import * as ImagePicker from "expo-image-picker";
9
9
  import { Alert } from "react-native";
10
- import type { UploadedImage } from "../../../../features/partner-upload/domain/types";
10
+ import type { UploadedImage } from "../../../../../presentation/hooks/generation/useAIGenerateState";
11
11
 
12
12
  export interface PhotoUploadConfig {
13
13
  readonly maxFileSizeMB?: number;
@@ -52,7 +52,7 @@ export const usePhotoUploadState = ({
52
52
 
53
53
  // Pick image
54
54
  const result = await ImagePicker.launchImageLibraryAsync({
55
- mediaTypes: "images" as any,
55
+ mediaTypes: ImagePicker.MediaTypeOptions.Images,
56
56
  allowsEditing: true,
57
57
  aspect: [1, 1],
58
58
  quality: 0.8,
@@ -4,8 +4,8 @@
4
4
  */
5
5
 
6
6
  import { useEffect, useRef, useMemo } from "react";
7
- import { useGenerationOrchestrator } from "../../../../presentation/hooks/generation";
8
- import type { AlertMessages } from "../../../../presentation/hooks/generation/types";
7
+ import { useGenerationOrchestrator } from "../../../../../presentation/hooks/generation";
8
+ import type { AlertMessages } from "../../../../../presentation/hooks/generation/types";
9
9
  import { createWizardStrategy, buildWizardInput } from "../../infrastructure/strategies";
10
10
 
11
11
  declare const __DEV__: boolean;
@@ -4,7 +4,7 @@
4
4
  * Supports overrides for customization
5
5
  */
6
6
 
7
- import type { WizardFeatureConfig } from "../../wizard/domain/entities/wizard-config.types";
7
+ import type { WizardFeatureConfig } from "../../generation/wizard/domain/entities/wizard-config.types";
8
8
 
9
9
  /**
10
10
  * Feature Type Classification
package/src/index.ts CHANGED
@@ -72,7 +72,7 @@ export {
72
72
  useGeneration, usePendingJobs, useBackgroundGeneration,
73
73
  useGenerationFlow, useAIFeatureCallbacks,
74
74
  useAIGenerateState, AIGenerateStep,
75
- useGenerationOrchestrator, useImageGeneration, useVideoGeneration, useAIFeatureGeneration,
75
+ useGenerationOrchestrator, useImageGeneration, useVideoGeneration,
76
76
  createGenerationError, getAlertMessage, parseError,
77
77
  } from "./presentation/hooks";
78
78
 
@@ -30,7 +30,7 @@ export async function generateSynchronously<T = string>(
30
30
  ): Promise<GenerationResult<T>> {
31
31
  // Check user ID if required
32
32
  if (config.checkCredits && !input.userId) {
33
- return createErrorResult("user_id_required");
33
+ return createErrorResult("user_id_required", config.model || "unknown");
34
34
  }
35
35
 
36
36
  // Check credits if configured
@@ -40,7 +40,7 @@ export async function generateSynchronously<T = string>(
40
40
  input.type || "generation",
41
41
  );
42
42
  if (!hasCredits) {
43
- return createErrorResult("insufficient_credits");
43
+ return createErrorResult("insufficient_credits", config.model || "unknown");
44
44
  }
45
45
  }
46
46
 
@@ -50,6 +50,7 @@ export async function generateSynchronously<T = string>(
50
50
  if (!moderationResult.allowed) {
51
51
  return createErrorResult(
52
52
  moderationResult.error || "content_policy_violation",
53
+ config.model || "unknown",
53
54
  );
54
55
  }
55
56
  }
@@ -9,7 +9,6 @@ export { useGenerationOrchestrator } from "./orchestrator";
9
9
  // Generic feature hooks
10
10
  export { useImageGeneration } from "./useImageGeneration";
11
11
  export { useVideoGeneration } from "./useVideoGeneration";
12
- export { useAIFeatureGeneration } from "./useAIFeatureGeneration";
13
12
 
14
13
  // Types
15
14
  export type {
@@ -70,9 +70,14 @@ export const useGenerationOrchestrator = <TInput, TResult>(
70
70
 
71
71
  const offlineStore = useOfflineStore();
72
72
  const { showError, showSuccess } = useAlert();
73
- const defaultCredits = useDeductCredit({ userId, onCreditsExhausted }) as {
74
- checkCredits: (amount: number) => Promise<boolean>;
75
- deductCredit: (amount: number) => Promise<void>;
73
+ const creditHook = useDeductCredit({ userId, onCreditsExhausted });
74
+
75
+ // Wrap credit hook to match expected interface
76
+ const defaultCredits = {
77
+ checkCredits: creditHook.checkCredits,
78
+ deductCredit: async (amount: number) => {
79
+ await creditHook.deductCredit(amount);
80
+ }
76
81
  };
77
82
 
78
83
  // Use provided credit callbacks or default to useDeductCredit hook
@@ -12,6 +12,9 @@ export interface UploadedImage {
12
12
  uri: string;
13
13
  previewUrl?: string;
14
14
  name?: string;
15
+ width?: number;
16
+ height?: number;
17
+ fileSize?: number;
15
18
  }
16
19
 
17
20
  import { useState, useCallback } from "react";
@@ -7,7 +7,6 @@ export {
7
7
  useGenerationOrchestrator,
8
8
  useImageGeneration,
9
9
  useVideoGeneration,
10
- useAIFeatureGeneration,
11
10
  createGenerationError,
12
11
  getAlertMessage,
13
12
  parseError,
@@ -4,10 +4,6 @@
4
4
  */
5
5
 
6
6
  import type { ReactNode } from "react";
7
- import type {
8
- BaseSingleImageHookReturn,
9
- BaseDualImageHookReturn,
10
- } from "../../../features/image-to-image/domain/types";
11
7
  import type {
12
8
  ModalTranslations,
13
9
  BaseLayoutTranslations,
@@ -24,6 +20,36 @@ import type {
24
20
  SingleImageWithPromptFeatureState,
25
21
  } from "./feature-states";
26
22
 
23
+ /**
24
+ * Base hook return for single image features
25
+ */
26
+ export interface BaseSingleImageHookReturn {
27
+ readonly imageUri: string | null;
28
+ readonly processedUrl: string | null;
29
+ readonly isProcessing: boolean;
30
+ readonly progress: number;
31
+ selectImage(): Promise<void>;
32
+ process(): Promise<void>;
33
+ save(): Promise<void>;
34
+ reset(): void;
35
+ }
36
+
37
+ /**
38
+ * Base hook return for dual image features
39
+ */
40
+ export interface BaseDualImageHookReturn {
41
+ readonly sourceImageUri: string | null;
42
+ readonly targetImageUri: string | null;
43
+ readonly processedUrl: string | null;
44
+ readonly isProcessing: boolean;
45
+ readonly progress: number;
46
+ selectSourceImage(): Promise<void>;
47
+ selectTargetImage(): Promise<void>;
48
+ process(): Promise<void>;
49
+ save(): Promise<void>;
50
+ reset(): void;
51
+ }
52
+
27
53
  /**
28
54
  * Single image feature layout props
29
55
  * Note: No modal - shows fullscreen progress when processing (FutureUS pattern)
@@ -1,107 +0,0 @@
1
- /**
2
- * Generic Step Renderer
3
- * Renders any step type based on configuration
4
- * NO feature-specific code! Works for ALL features!
5
- */
6
-
7
- import React from "react";
8
- import { StepType } from "../../../../domain/entities/flow-config.types";
9
- import type { StepDefinition } from "../../../../domain/entities/flow-config.types";
10
- import type {
11
- WizardStepConfig,
12
- PhotoUploadStepConfig,
13
- TextInputStepConfig,
14
- SelectionStepConfig,
15
- } from "../../domain/entities/wizard-config.types";
16
-
17
- // Import generic step components (will create these)
18
- import { PhotoUploadStep } from "../../presentation/steps/PhotoUploadStep";
19
- import { TextInputStep } from "../../presentation/steps/TextInputStep";
20
- import { SelectionStep } from "../../presentation/steps/SelectionStep";
21
-
22
- export interface StepRendererProps {
23
- readonly step: StepDefinition;
24
- readonly onContinue: (data: Record<string, unknown>) => void;
25
- readonly onBack: () => void;
26
- readonly t: (key: string) => string;
27
- readonly translations?: Record<string, string>;
28
- }
29
-
30
- /**
31
- * Render a step based on its type and configuration
32
- * This is the ONLY renderer needed for ALL features!
33
- */
34
- export const renderStep = (props: StepRendererProps): React.ReactElement | null => {
35
- const { step, onContinue, onBack, t, translations } = props;
36
-
37
- if (typeof __DEV__ !== "undefined" && __DEV__) {
38
- console.log("[StepRenderer] Rendering step", {
39
- stepId: step.id,
40
- stepType: step.type,
41
- hasConfig: !!step.config,
42
- });
43
- }
44
-
45
- const wizardConfig = step.config as WizardStepConfig | undefined;
46
-
47
- switch (step.type) {
48
- case StepType.PARTNER_UPLOAD: {
49
- // This handles ALL photo uploads (couple, face-swap, image-to-video, etc.)
50
- const photoConfig = wizardConfig as PhotoUploadStepConfig;
51
- return (
52
- <PhotoUploadStep
53
- key={step.id}
54
- config={photoConfig}
55
- onContinue={(imageData) => {
56
- onContinue({ [`photo_${step.id}`]: imageData });
57
- }}
58
- onBack={onBack}
59
- t={t}
60
- translations={translations}
61
- />
62
- );
63
- }
64
-
65
- case StepType.TEXT_INPUT: {
66
- const textConfig = wizardConfig as TextInputStepConfig;
67
- return (
68
- <TextInputStep
69
- config={textConfig}
70
- onContinue={(text) => {
71
- onContinue({ text });
72
- }}
73
- onBack={onBack}
74
- t={t}
75
- translations={translations}
76
- />
77
- );
78
- }
79
-
80
- case StepType.FEATURE_SELECTION: {
81
- const selectionConfig = wizardConfig as SelectionStepConfig;
82
- return (
83
- <SelectionStep
84
- config={selectionConfig}
85
- onContinue={(selected) => {
86
- onContinue({ [`selection_${step.id}`]: selected });
87
- }}
88
- onBack={onBack}
89
- t={t}
90
- translations={translations}
91
- />
92
- );
93
- }
94
-
95
- case StepType.SCENARIO_PREVIEW:
96
- case StepType.GENERATING:
97
- case StepType.RESULT_PREVIEW:
98
- // These are handled by parent wizard component
99
- return null;
100
-
101
- default:
102
- if (typeof __DEV__ !== "undefined" && __DEV__) {
103
- console.warn("[StepRenderer] Unknown step type", step.type);
104
- }
105
- return null;
106
- }
107
- };