@umituz/react-native-ai-generation-content 1.27.8 → 1.27.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 (83) hide show
  1. package/package.json +1 -1
  2. package/src/domains/generation/wizard/infrastructure/strategies/image-generation.strategy.ts +3 -30
  3. package/src/domains/generation/wizard/infrastructure/strategies/video-generation.strategy.ts +3 -30
  4. package/src/domains/generation/wizard/infrastructure/strategies/wizard-strategy.constants.ts +0 -2
  5. package/src/features/image-to-video/README.md +414 -0
  6. package/src/features/image-to-video/domain/constants/animation.constants.ts +47 -0
  7. package/src/features/image-to-video/domain/constants/duration.constants.ts +13 -0
  8. package/src/features/image-to-video/domain/constants/form.constants.ts +22 -0
  9. package/src/features/image-to-video/domain/constants/index.ts +23 -0
  10. package/src/features/image-to-video/domain/constants/music.constants.ts +53 -0
  11. package/src/features/image-to-video/domain/index.ts +5 -0
  12. package/src/features/image-to-video/domain/types/animation.types.ts +20 -0
  13. package/src/features/image-to-video/domain/types/config.types.ts +56 -0
  14. package/src/features/image-to-video/domain/types/duration.types.ts +11 -0
  15. package/src/features/image-to-video/domain/types/form.types.ts +35 -0
  16. package/src/features/image-to-video/domain/types/image-to-video.types.ts +122 -0
  17. package/src/features/image-to-video/domain/types/index.ts +39 -0
  18. package/src/features/image-to-video/domain/types/music.types.ts +21 -0
  19. package/src/features/image-to-video/index.ts +116 -0
  20. package/src/features/image-to-video/infrastructure/index.ts +1 -0
  21. package/src/features/image-to-video/infrastructure/services/image-to-video-executor.ts +165 -0
  22. package/src/features/image-to-video/infrastructure/services/index.ts +5 -0
  23. package/src/features/image-to-video/presentation/components/AddMoreCard.tsx +52 -0
  24. package/src/features/image-to-video/presentation/components/AnimationStyleSelector.tsx +135 -0
  25. package/src/features/image-to-video/presentation/components/DurationSelector.tsx +110 -0
  26. package/src/features/image-to-video/presentation/components/EmptyGridState.tsx +69 -0
  27. package/src/features/image-to-video/presentation/components/GridImageItem.tsx +64 -0
  28. package/src/features/image-to-video/presentation/components/ImageSelectionGrid.styles.ts +84 -0
  29. package/src/features/image-to-video/presentation/components/ImageSelectionGrid.tsx +77 -0
  30. package/src/features/image-to-video/presentation/components/ImageSelectionGrid.types.ts +18 -0
  31. package/src/features/image-to-video/presentation/components/MusicMoodSelector.tsx +181 -0
  32. package/src/features/image-to-video/presentation/components/index.ts +30 -0
  33. package/src/features/image-to-video/presentation/hooks/index.ts +27 -0
  34. package/src/features/image-to-video/presentation/hooks/useFormState.ts +116 -0
  35. package/src/features/image-to-video/presentation/hooks/useGeneration.ts +85 -0
  36. package/src/features/image-to-video/presentation/hooks/useGenerationExecution.ts +143 -0
  37. package/src/features/image-to-video/presentation/hooks/useImageToVideoFeature.ts +107 -0
  38. package/src/features/image-to-video/presentation/hooks/useImageToVideoForm.ts +119 -0
  39. package/src/features/image-to-video/presentation/hooks/useImageToVideoValidation.ts +46 -0
  40. package/src/features/image-to-video/presentation/index.ts +5 -0
  41. package/src/features/text-to-image/README.md +394 -0
  42. package/src/features/text-to-image/domain/constants/index.ts +25 -0
  43. package/src/features/text-to-image/domain/constants/options.constants.ts +39 -0
  44. package/src/features/text-to-image/domain/constants/styles.constants.ts +34 -0
  45. package/src/features/text-to-image/domain/index.ts +7 -0
  46. package/src/features/text-to-image/domain/types/config.types.ts +75 -0
  47. package/src/features/text-to-image/domain/types/form.types.ts +58 -0
  48. package/src/features/text-to-image/domain/types/index.ts +38 -0
  49. package/src/features/text-to-image/domain/types/text-to-image.types.ts +58 -0
  50. package/src/features/text-to-image/index.ts +116 -0
  51. package/src/features/text-to-image/infrastructure/index.ts +1 -0
  52. package/src/features/text-to-image/infrastructure/services/index.ts +5 -0
  53. package/src/features/text-to-image/infrastructure/services/text-to-image-executor.ts +147 -0
  54. package/src/features/text-to-image/presentation/components/index.ts +30 -0
  55. package/src/features/text-to-image/presentation/hooks/index.ts +30 -0
  56. package/src/features/text-to-image/presentation/hooks/useFormState.ts +103 -0
  57. package/src/features/text-to-image/presentation/hooks/useGeneration.ts +134 -0
  58. package/src/features/text-to-image/presentation/hooks/useTextToImageFeature.ts +111 -0
  59. package/src/features/text-to-image/presentation/hooks/useTextToImageForm.ts +58 -0
  60. package/src/features/text-to-image/presentation/index.ts +7 -0
  61. package/src/features/text-to-video/README.md +412 -0
  62. package/src/features/text-to-video/domain/index.ts +1 -0
  63. package/src/features/text-to-video/domain/types/callback.types.ts +69 -0
  64. package/src/features/text-to-video/domain/types/component.types.ts +106 -0
  65. package/src/features/text-to-video/domain/types/config.types.ts +61 -0
  66. package/src/features/text-to-video/domain/types/index.ts +56 -0
  67. package/src/features/text-to-video/domain/types/request.types.ts +36 -0
  68. package/src/features/text-to-video/domain/types/state.types.ts +53 -0
  69. package/src/features/text-to-video/index.ts +68 -0
  70. package/src/features/text-to-video/infrastructure/index.ts +1 -0
  71. package/src/features/text-to-video/infrastructure/services/index.ts +5 -0
  72. package/src/features/text-to-video/infrastructure/services/text-to-video-executor.ts +141 -0
  73. package/src/features/text-to-video/presentation/components/FrameSelector.tsx +153 -0
  74. package/src/features/text-to-video/presentation/components/GenerationTabs.tsx +73 -0
  75. package/src/features/text-to-video/presentation/components/HeroSection.tsx +61 -0
  76. package/src/features/text-to-video/presentation/components/HintCarousel.tsx +96 -0
  77. package/src/features/text-to-video/presentation/components/OptionsPanel.tsx +121 -0
  78. package/src/features/text-to-video/presentation/components/index.ts +10 -0
  79. package/src/features/text-to-video/presentation/hooks/index.ts +17 -0
  80. package/src/features/text-to-video/presentation/hooks/useTextToVideoFeature.ts +187 -0
  81. package/src/features/text-to-video/presentation/hooks/useTextToVideoForm.ts +134 -0
  82. package/src/features/text-to-video/presentation/index.ts +7 -0
  83. package/src/index.ts +5 -0
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Animation Style Selector Component
3
+ * Generic component for animation style selection
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, TouchableOpacity, StyleSheet } from "react-native";
8
+ import {
9
+ AtomicText,
10
+ AtomicIcon,
11
+ useAppDesignTokens,
12
+ } from "@umituz/react-native-design-system";
13
+ import type { AnimationStyle, AnimationStyleId } from "../../domain/types";
14
+
15
+ export interface AnimationStyleSelectorProps {
16
+ styles: AnimationStyle[];
17
+ selectedStyle: AnimationStyleId;
18
+ onStyleSelect: (styleId: AnimationStyleId) => void;
19
+ label: string;
20
+ }
21
+
22
+ export const AnimationStyleSelector: React.FC<AnimationStyleSelectorProps> = ({
23
+ styles,
24
+ selectedStyle,
25
+ onStyleSelect,
26
+ label,
27
+ }) => {
28
+ const tokens = useAppDesignTokens();
29
+
30
+ return (
31
+ <View style={componentStyles.section}>
32
+ <AtomicText
33
+ type="bodyMedium"
34
+ style={[componentStyles.label, { color: tokens.colors.textPrimary }]}
35
+ >
36
+ {label}
37
+ </AtomicText>
38
+ {styles.map((style) => {
39
+ const isSelected = selectedStyle === style.id;
40
+ return (
41
+ <TouchableOpacity
42
+ key={style.id}
43
+ style={[
44
+ componentStyles.card,
45
+ {
46
+ backgroundColor: isSelected
47
+ ? tokens.colors.primary + "20"
48
+ : tokens.colors.surface,
49
+ borderColor: isSelected
50
+ ? tokens.colors.primary
51
+ : tokens.colors.borderLight,
52
+ },
53
+ ]}
54
+ onPress={() => onStyleSelect(style.id)}
55
+ activeOpacity={0.7}
56
+ >
57
+ <View style={componentStyles.cardContent}>
58
+ <View
59
+ style={[
60
+ componentStyles.iconContainer,
61
+ {
62
+ backgroundColor: isSelected
63
+ ? tokens.colors.primary
64
+ : tokens.colors.primary + "20",
65
+ },
66
+ ]}
67
+ >
68
+ <AtomicIcon
69
+ name={style.icon as never}
70
+ size="md"
71
+ color={isSelected ? "onSurface" : "primary"}
72
+ />
73
+ </View>
74
+ <View style={componentStyles.textContainer}>
75
+ <AtomicText
76
+ type="bodyMedium"
77
+ style={[
78
+ componentStyles.styleName,
79
+ { color: tokens.colors.textPrimary },
80
+ ]}
81
+ >
82
+ {style.name}
83
+ </AtomicText>
84
+ <AtomicText
85
+ type="labelSmall"
86
+ style={{ color: tokens.colors.textSecondary }}
87
+ >
88
+ {style.description}
89
+ </AtomicText>
90
+ </View>
91
+ {isSelected && (
92
+ <AtomicIcon name="checkmark-outline" size="md" color="primary" />
93
+ )}
94
+ </View>
95
+ </TouchableOpacity>
96
+ );
97
+ })}
98
+ </View>
99
+ );
100
+ };
101
+
102
+ const componentStyles = StyleSheet.create({
103
+ section: {
104
+ padding: 16,
105
+ marginBottom: 8,
106
+ },
107
+ label: {
108
+ fontWeight: "600",
109
+ marginBottom: 12,
110
+ },
111
+ card: {
112
+ padding: 16,
113
+ borderRadius: 12,
114
+ borderWidth: 2,
115
+ marginBottom: 12,
116
+ },
117
+ cardContent: {
118
+ flexDirection: "row",
119
+ alignItems: "center",
120
+ },
121
+ iconContainer: {
122
+ width: 48,
123
+ height: 48,
124
+ borderRadius: 24,
125
+ alignItems: "center",
126
+ justifyContent: "center",
127
+ },
128
+ textContainer: {
129
+ flex: 1,
130
+ marginLeft: 12,
131
+ },
132
+ styleName: {
133
+ fontWeight: "600",
134
+ },
135
+ });
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Duration Selector Component
3
+ * Generic component for video duration selection
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, TouchableOpacity, StyleSheet } from "react-native";
8
+ import {
9
+ AtomicText,
10
+ useAppDesignTokens,
11
+ } from "@umituz/react-native-design-system";
12
+ import type { VideoDuration, DurationOption } from "../../domain/types";
13
+
14
+ export interface DurationSelectorProps {
15
+ options: DurationOption[];
16
+ selectedDuration: VideoDuration;
17
+ onDurationSelect: (duration: VideoDuration) => void;
18
+ label: string;
19
+ imageCount: number;
20
+ totalVideoLabel: string;
21
+ }
22
+
23
+ export const DurationSelector: React.FC<DurationSelectorProps> = ({
24
+ options,
25
+ selectedDuration,
26
+ onDurationSelect,
27
+ label,
28
+ imageCount,
29
+ totalVideoLabel,
30
+ }) => {
31
+ const tokens = useAppDesignTokens();
32
+
33
+ return (
34
+ <View style={componentStyles.section}>
35
+ <AtomicText
36
+ type="bodyMedium"
37
+ style={[componentStyles.label, { color: tokens.colors.textPrimary }]}
38
+ >
39
+ {label}
40
+ </AtomicText>
41
+ <View style={componentStyles.grid}>
42
+ {options.map((option) => {
43
+ const isSelected = selectedDuration === option.value;
44
+ return (
45
+ <TouchableOpacity
46
+ key={option.value}
47
+ style={[
48
+ componentStyles.button,
49
+ {
50
+ backgroundColor: isSelected
51
+ ? tokens.colors.primary
52
+ : tokens.colors.surface,
53
+ borderColor: isSelected
54
+ ? tokens.colors.primary
55
+ : tokens.colors.borderLight,
56
+ },
57
+ ]}
58
+ onPress={() => onDurationSelect(option.value)}
59
+ activeOpacity={0.7}
60
+ >
61
+ <AtomicText
62
+ type="bodyMedium"
63
+ style={{
64
+ color: isSelected
65
+ ? tokens.colors.textInverse
66
+ : tokens.colors.textPrimary,
67
+ fontWeight: isSelected ? "600" : "400",
68
+ }}
69
+ >
70
+ {option.label ?? `${option.value}s`}
71
+ </AtomicText>
72
+ </TouchableOpacity>
73
+ );
74
+ })}
75
+ </View>
76
+ <AtomicText
77
+ type="labelSmall"
78
+ style={[componentStyles.hint, { color: tokens.colors.textSecondary }]}
79
+ >
80
+ {totalVideoLabel.replace("{duration}", String(imageCount * selectedDuration))}
81
+ </AtomicText>
82
+ </View>
83
+ );
84
+ };
85
+
86
+ const componentStyles = StyleSheet.create({
87
+ section: {
88
+ padding: 16,
89
+ marginBottom: 8,
90
+ },
91
+ label: {
92
+ fontWeight: "600",
93
+ marginBottom: 12,
94
+ },
95
+ grid: {
96
+ flexDirection: "row",
97
+ gap: 12,
98
+ },
99
+ button: {
100
+ flex: 1,
101
+ paddingVertical: 16,
102
+ borderRadius: 12,
103
+ borderWidth: 1,
104
+ alignItems: "center",
105
+ justifyContent: "center",
106
+ },
107
+ hint: {
108
+ marginTop: 8,
109
+ },
110
+ });
@@ -0,0 +1,69 @@
1
+ /**
2
+ * EmptyGridState Component
3
+ * Displays empty state when no images are selected
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, TouchableOpacity } from "react-native";
8
+ import {
9
+ AtomicText,
10
+ AtomicIcon,
11
+ useAppDesignTokens,
12
+ } from "@umituz/react-native-design-system";
13
+ import type { ImageSelectionGridStyles } from "./ImageSelectionGrid.styles";
14
+ import type { ImageSelectionGridTranslations } from "./ImageSelectionGrid.types";
15
+
16
+ interface EmptyGridStateProps {
17
+ styles: ImageSelectionGridStyles;
18
+ maxImages: number;
19
+ translations: ImageSelectionGridTranslations;
20
+ onSelectImages: () => void;
21
+ }
22
+
23
+ export function EmptyGridState({
24
+ styles,
25
+ maxImages,
26
+ translations,
27
+ onSelectImages,
28
+ }: EmptyGridStateProps) {
29
+ const tokens = useAppDesignTokens();
30
+
31
+ return (
32
+ <View style={styles.section}>
33
+ <AtomicText
34
+ type="bodyMedium"
35
+ style={[styles.label, { color: tokens.colors.textPrimary }]}
36
+ >
37
+ {translations.selectedImages} (0/{maxImages})
38
+ </AtomicText>
39
+ <TouchableOpacity
40
+ style={[
41
+ styles.uploadBox,
42
+ {
43
+ backgroundColor: tokens.colors.surface,
44
+ borderColor: tokens.colors.borderLight,
45
+ },
46
+ ]}
47
+ onPress={onSelectImages}
48
+ activeOpacity={0.7}
49
+ >
50
+ <AtomicIcon name="cloud-upload-outline" size="xl" color="primary" />
51
+ <AtomicText
52
+ type="bodyMedium"
53
+ style={[
54
+ styles.uploadText,
55
+ { color: tokens.colors.primary },
56
+ ]}
57
+ >
58
+ {translations.selectImages}
59
+ </AtomicText>
60
+ <AtomicText
61
+ type="labelSmall"
62
+ style={{ color: tokens.colors.textSecondary }}
63
+ >
64
+ {translations.chooseUpTo.replace("{max}", String(maxImages))}
65
+ </AtomicText>
66
+ </TouchableOpacity>
67
+ </View>
68
+ );
69
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * GridImageItem Component
3
+ * Displays a single image in the grid with remove button and badge
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, TouchableOpacity, Image } from "react-native";
8
+ import {
9
+ AtomicIcon,
10
+ AtomicText,
11
+ useAppDesignTokens,
12
+ } from "@umituz/react-native-design-system";
13
+ import type { ImageSelectionGridStyles } from "./ImageSelectionGrid.styles";
14
+
15
+ interface GridImageItemProps {
16
+ styles: ImageSelectionGridStyles;
17
+ uri: string;
18
+ index: number;
19
+ onRemove: () => void;
20
+ }
21
+
22
+ export function GridImageItem({
23
+ styles,
24
+ uri,
25
+ index,
26
+ onRemove,
27
+ }: GridImageItemProps) {
28
+ const tokens = useAppDesignTokens();
29
+
30
+ return (
31
+ <View style={styles.imageCard}>
32
+ <Image
33
+ source={{ uri }}
34
+ style={styles.imagePreview}
35
+ resizeMode="cover"
36
+ />
37
+ <TouchableOpacity
38
+ style={[
39
+ styles.removeButton,
40
+ { backgroundColor: tokens.colors.error },
41
+ ]}
42
+ onPress={onRemove}
43
+ >
44
+ <AtomicIcon name="close-circle" size="sm" color="onSurface" />
45
+ </TouchableOpacity>
46
+ <View
47
+ style={[
48
+ styles.imageBadge,
49
+ { backgroundColor: tokens.colors.primary },
50
+ ]}
51
+ >
52
+ <AtomicText
53
+ type="labelSmall"
54
+ style={[
55
+ styles.badgeText,
56
+ { color: tokens.colors.textInverse },
57
+ ]}
58
+ >
59
+ {index + 1}
60
+ </AtomicText>
61
+ </View>
62
+ </View>
63
+ );
64
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * ImageSelectionGrid Styles
3
+ */
4
+
5
+ import { StyleSheet } from "react-native";
6
+ import type { DesignTokens } from "@umituz/react-native-design-system";
7
+
8
+ export function createImageSelectionGridStyles(_tokens: DesignTokens) {
9
+ return StyleSheet.create({
10
+ section: {
11
+ padding: 16,
12
+ marginBottom: 8,
13
+ },
14
+ label: {
15
+ fontWeight: "600",
16
+ marginBottom: 12,
17
+ },
18
+ uploadBox: {
19
+ padding: 48,
20
+ borderRadius: 16,
21
+ alignItems: "center",
22
+ justifyContent: "center",
23
+ borderWidth: 2,
24
+ borderStyle: "dashed",
25
+ },
26
+ uploadText: {
27
+ fontWeight: "600",
28
+ marginTop: 12,
29
+ },
30
+ scroll: {
31
+ marginHorizontal: -16,
32
+ paddingHorizontal: 16,
33
+ },
34
+ imageCard: {
35
+ width: 120,
36
+ height: 120,
37
+ borderRadius: 12,
38
+ marginRight: 12,
39
+ position: "relative",
40
+ },
41
+ imagePreview: {
42
+ width: "100%",
43
+ height: "100%",
44
+ borderRadius: 12,
45
+ },
46
+ removeButton: {
47
+ position: "absolute",
48
+ top: 6,
49
+ right: 6,
50
+ width: 24,
51
+ height: 24,
52
+ borderRadius: 12,
53
+ alignItems: "center",
54
+ justifyContent: "center",
55
+ },
56
+ imageBadge: {
57
+ position: "absolute",
58
+ bottom: 6,
59
+ left: 6,
60
+ width: 24,
61
+ height: 24,
62
+ borderRadius: 12,
63
+ alignItems: "center",
64
+ justifyContent: "center",
65
+ },
66
+ badgeText: {
67
+ fontSize: 10,
68
+ },
69
+ addMoreCard: {
70
+ width: 120,
71
+ height: 120,
72
+ borderRadius: 12,
73
+ alignItems: "center",
74
+ justifyContent: "center",
75
+ borderWidth: 2,
76
+ borderStyle: "dashed",
77
+ },
78
+ addMoreText: {
79
+ marginTop: 4,
80
+ },
81
+ });
82
+ }
83
+
84
+ export type ImageSelectionGridStyles = ReturnType<typeof createImageSelectionGridStyles>;
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Image Selection Grid Component
3
+ * Generic component for image selection display
4
+ */
5
+
6
+ import React, { useMemo } from "react";
7
+ import { View, ScrollView } from "react-native";
8
+ import {
9
+ AtomicText,
10
+ useAppDesignTokens,
11
+ } from "@umituz/react-native-design-system";
12
+ import { EmptyGridState } from "./EmptyGridState";
13
+ import { GridImageItem } from "./GridImageItem";
14
+ import { AddMoreCard } from "./AddMoreCard";
15
+ import { createImageSelectionGridStyles } from "./ImageSelectionGrid.styles";
16
+ import type { ImageSelectionGridProps } from "./ImageSelectionGrid.types";
17
+
18
+ export const ImageSelectionGrid: React.FC<ImageSelectionGridProps> = ({
19
+ images,
20
+ maxImages,
21
+ onSelectImages,
22
+ onRemoveImage,
23
+ translations,
24
+ }) => {
25
+ const tokens = useAppDesignTokens();
26
+ const styles = useMemo(
27
+ () => createImageSelectionGridStyles(tokens),
28
+ [tokens]
29
+ );
30
+
31
+ if (images.length === 0) {
32
+ return (
33
+ <EmptyGridState
34
+ styles={styles}
35
+ maxImages={maxImages}
36
+ translations={translations}
37
+ onSelectImages={onSelectImages}
38
+ />
39
+ );
40
+ }
41
+
42
+ return (
43
+ <View style={styles.section}>
44
+ <AtomicText
45
+ type="bodyMedium"
46
+ style={[styles.label, { color: tokens.colors.textPrimary }]}
47
+ >
48
+ {translations.selectedImages} ({images.length}/{maxImages})
49
+ </AtomicText>
50
+ <ScrollView
51
+ horizontal
52
+ showsHorizontalScrollIndicator={false}
53
+ style={styles.scroll}
54
+ >
55
+ {images.map((uri, index) => (
56
+ <GridImageItem
57
+ key={index}
58
+ styles={styles}
59
+ uri={uri}
60
+ index={index}
61
+ onRemove={() => onRemoveImage(index)}
62
+ />
63
+ ))}
64
+
65
+ {images.length < maxImages && (
66
+ <AddMoreCard
67
+ styles={styles}
68
+ addMoreText={translations.addMore}
69
+ onPress={onSelectImages}
70
+ />
71
+ )}
72
+ </ScrollView>
73
+ </View>
74
+ );
75
+ };
76
+
77
+ export type { ImageSelectionGridProps, ImageSelectionGridTranslations } from "./ImageSelectionGrid.types";
@@ -0,0 +1,18 @@
1
+ /**
2
+ * ImageSelectionGrid Type Definitions
3
+ */
4
+
5
+ export interface ImageSelectionGridTranslations {
6
+ selectedImages: string;
7
+ selectImages: string;
8
+ chooseUpTo: string;
9
+ addMore: string;
10
+ }
11
+
12
+ export interface ImageSelectionGridProps {
13
+ images: string[];
14
+ maxImages: number;
15
+ onSelectImages: () => void;
16
+ onRemoveImage: (index: number) => void;
17
+ translations: ImageSelectionGridTranslations;
18
+ }