@umituz/react-native-ai-generation-content 1.17.86 → 1.17.88
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 +2 -2
- package/src/domains/creations/index.ts +6 -3
- package/src/domains/creations/presentation/components/CreationBadges.tsx +3 -3
- package/src/domains/creations/presentation/components/CreationDetail/DetailStory.tsx +5 -8
- package/src/domains/creations/presentation/components/CreationThumbnail.tsx +1 -1
- package/src/domains/creations/presentation/components/index.ts +0 -3
- package/src/domains/creations/presentation/screens/CreationDetailScreen.tsx +5 -4
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +2 -11
- package/src/domains/creations/presentation/utils/filterUtils.ts +18 -1
- package/src/domains/flashcard-generation/FlashcardGenerationService.ts +85 -311
- package/src/domains/flashcard-generation/builders/flashcard-prompt.builder.ts +55 -0
- package/src/domains/flashcard-generation/parsers/flashcard-response.parser.ts +68 -0
- package/src/domains/flashcard-generation/types/flashcard.types.ts +56 -0
- package/src/domains/flashcard-generation/validators/flashcard.validator.ts +67 -0
- package/src/features/image-to-video/presentation/components/MusicMoodSelector.tsx +3 -3
- package/src/features/replace-background/presentation/components/ResultDisplay.tsx +1 -2
- package/src/features/script-generator/presentation/components/ScriptDisplay.tsx +3 -4
- package/src/features/text-to-image/domain/constants/index.ts +3 -3
- package/src/features/text-to-image/domain/constants/options.constants.ts +12 -25
- package/src/features/text-to-image/index.ts +12 -4
- package/src/features/text-to-image/presentation/hooks/index.ts +8 -0
- package/src/features/text-to-image/presentation/hooks/useTextToImageCallbacksBuilder.ts +200 -0
- package/src/features/text-to-video/presentation/components/HeroSection.tsx +2 -8
- package/src/features/text-to-video/presentation/components/OptionsPanel.tsx +3 -5
- package/src/presentation/components/AIGenerationForm.tsx +0 -1
- package/src/presentation/components/AIGenerationHero.tsx +27 -24
- package/src/presentation/components/GenerationProgressContent.tsx +4 -2
- package/src/presentation/components/PhotoUploadCard/PhotoUploadCard.tsx +12 -26
- package/src/presentation/components/StylePresetsGrid.tsx +5 -3
- package/src/presentation/components/buttons/GenerateButton.tsx +39 -102
- package/src/presentation/components/headers/FeatureHeader.tsx +15 -9
- package/src/presentation/components/image-picker/DualImagePicker.tsx +0 -6
- package/src/presentation/components/image-picker/ImagePickerBox.tsx +27 -16
- package/src/presentation/components/modals/SettingsSheet.tsx +4 -2
- package/src/presentation/components/result/ResultImageCard.tsx +12 -35
- package/src/presentation/components/result/ResultStoryCard.tsx +10 -16
- package/src/domains/creations/presentation/components/CreationsProvider.tsx +0 -56
|
@@ -35,7 +35,7 @@ export const OptionsPanel: React.FC<OptionsPanelProps> = ({
|
|
|
35
35
|
<View
|
|
36
36
|
style={[styles.badge, { backgroundColor: tokens.colors.success }]}
|
|
37
37
|
>
|
|
38
|
-
<AtomicText type="labelSmall" style={styles.badgeText}>
|
|
38
|
+
<AtomicText type="labelSmall" style={[styles.badgeText, { color: tokens.colors.textInverse }]}>
|
|
39
39
|
{soundBadge}
|
|
40
40
|
</AtomicText>
|
|
41
41
|
</View>
|
|
@@ -55,7 +55,7 @@ export const OptionsPanel: React.FC<OptionsPanelProps> = ({
|
|
|
55
55
|
<TouchableOpacity
|
|
56
56
|
style={[
|
|
57
57
|
styles.controlButton,
|
|
58
|
-
|
|
58
|
+
{ backgroundColor: professionalMode ? tokens.colors.surface : tokens.colors.surfaceVariant },
|
|
59
59
|
]}
|
|
60
60
|
onPress={() => onProfessionalModeToggle(!professionalMode)}
|
|
61
61
|
>
|
|
@@ -67,7 +67,7 @@ export const OptionsPanel: React.FC<OptionsPanelProps> = ({
|
|
|
67
67
|
</AtomicText>
|
|
68
68
|
</TouchableOpacity>
|
|
69
69
|
|
|
70
|
-
<TouchableOpacity style={[styles.controlButton, styles.durationButton]}>
|
|
70
|
+
<TouchableOpacity style={[styles.controlButton, styles.durationButton, { backgroundColor: tokens.colors.surfaceVariant }]}>
|
|
71
71
|
<AtomicText type="labelMedium" color="textSecondary">
|
|
72
72
|
{duration}s
|
|
73
73
|
</AtomicText>
|
|
@@ -101,7 +101,6 @@ const styles = StyleSheet.create({
|
|
|
101
101
|
borderRadius: 4,
|
|
102
102
|
},
|
|
103
103
|
badgeText: {
|
|
104
|
-
color: "#000",
|
|
105
104
|
fontWeight: "bold",
|
|
106
105
|
fontSize: 10,
|
|
107
106
|
},
|
|
@@ -113,7 +112,6 @@ const styles = StyleSheet.create({
|
|
|
113
112
|
paddingHorizontal: 16,
|
|
114
113
|
paddingVertical: 10,
|
|
115
114
|
borderRadius: 8,
|
|
116
|
-
backgroundColor: "rgba(255, 255, 255, 0.05)",
|
|
117
115
|
alignItems: "center",
|
|
118
116
|
justifyContent: "center",
|
|
119
117
|
},
|
|
@@ -131,7 +131,6 @@ export const AIGenerationForm: React.FC<AIGenerationFormProps> = ({
|
|
|
131
131
|
isDisabled={onPromptChange ? !prompt?.trim() : false}
|
|
132
132
|
text={translations.generateButton}
|
|
133
133
|
processingText={translations.generatingButton}
|
|
134
|
-
variant="solid"
|
|
135
134
|
icon={generateButtonProps?.icon || "sparkles-outline"}
|
|
136
135
|
costLabel={generateButtonProps?.costLabel}
|
|
137
136
|
accessoryRight={generateButtonProps?.accessoryRight}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HeroSection Component
|
|
3
|
-
* Generic hero section with
|
|
3
|
+
* Generic hero section with solid background and optional icon
|
|
4
4
|
* Props-driven for 100+ apps compatibility
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import React from "react";
|
|
8
8
|
import { View, StyleSheet, type ViewStyle } from "react-native";
|
|
9
|
-
import { LinearGradient } from "expo-linear-gradient";
|
|
10
9
|
import {
|
|
11
10
|
AtomicText,
|
|
12
11
|
AtomicIcon,
|
|
@@ -17,7 +16,6 @@ export interface AIGenerationHeroProps {
|
|
|
17
16
|
readonly title: string;
|
|
18
17
|
readonly subtitle?: string;
|
|
19
18
|
readonly iconName?: string;
|
|
20
|
-
readonly gradientColors?: readonly [string, string, ...string[]];
|
|
21
19
|
readonly style?: ViewStyle;
|
|
22
20
|
}
|
|
23
21
|
|
|
@@ -25,38 +23,47 @@ export const AIGenerationHero: React.FC<AIGenerationHeroProps> = ({
|
|
|
25
23
|
title,
|
|
26
24
|
subtitle,
|
|
27
25
|
iconName,
|
|
28
|
-
gradientColors = ["#00FF88", "#10B981"],
|
|
29
26
|
style,
|
|
30
27
|
}) => {
|
|
31
28
|
const tokens = useAppDesignTokens();
|
|
32
29
|
|
|
33
|
-
const finalColors = gradientColors || [
|
|
34
|
-
tokens.colors.secondary ?? tokens.colors.info,
|
|
35
|
-
tokens.colors.primary,
|
|
36
|
-
];
|
|
37
|
-
|
|
38
30
|
return (
|
|
39
31
|
<View style={[styles.container, style]}>
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
<View
|
|
33
|
+
style={[
|
|
34
|
+
styles.heroBackground,
|
|
35
|
+
{ backgroundColor: tokens.colors.primary },
|
|
36
|
+
]}
|
|
45
37
|
>
|
|
46
38
|
{iconName && (
|
|
47
|
-
<View
|
|
48
|
-
|
|
39
|
+
<View
|
|
40
|
+
style={[
|
|
41
|
+
styles.iconWrapper,
|
|
42
|
+
{ backgroundColor: tokens.colors.surface },
|
|
43
|
+
]}
|
|
44
|
+
>
|
|
45
|
+
<AtomicIcon
|
|
46
|
+
name={iconName}
|
|
47
|
+
size="xl"
|
|
48
|
+
customColor={tokens.colors.primary}
|
|
49
|
+
/>
|
|
49
50
|
</View>
|
|
50
51
|
)}
|
|
51
|
-
<AtomicText
|
|
52
|
+
<AtomicText
|
|
53
|
+
type="headlineSmall"
|
|
54
|
+
style={[styles.title, { color: tokens.colors.textInverse }]}
|
|
55
|
+
>
|
|
52
56
|
{title}
|
|
53
57
|
</AtomicText>
|
|
54
58
|
{subtitle && (
|
|
55
|
-
<AtomicText
|
|
59
|
+
<AtomicText
|
|
60
|
+
type="bodyMedium"
|
|
61
|
+
style={[styles.subtitle, { color: tokens.colors.textInverse }]}
|
|
62
|
+
>
|
|
56
63
|
{subtitle}
|
|
57
64
|
</AtomicText>
|
|
58
65
|
)}
|
|
59
|
-
</
|
|
66
|
+
</View>
|
|
60
67
|
</View>
|
|
61
68
|
);
|
|
62
69
|
};
|
|
@@ -68,7 +75,7 @@ const styles = StyleSheet.create({
|
|
|
68
75
|
borderRadius: 20,
|
|
69
76
|
overflow: "hidden",
|
|
70
77
|
},
|
|
71
|
-
|
|
78
|
+
heroBackground: {
|
|
72
79
|
padding: 32,
|
|
73
80
|
alignItems: "center",
|
|
74
81
|
justifyContent: "center",
|
|
@@ -77,20 +84,16 @@ const styles = StyleSheet.create({
|
|
|
77
84
|
width: 80,
|
|
78
85
|
height: 80,
|
|
79
86
|
borderRadius: 40,
|
|
80
|
-
backgroundColor: "rgba(255, 255, 255, 0.2)",
|
|
81
87
|
alignItems: "center",
|
|
82
88
|
justifyContent: "center",
|
|
83
89
|
marginBottom: 16,
|
|
84
90
|
},
|
|
85
91
|
title: {
|
|
86
|
-
color: "#FFFFFF",
|
|
87
92
|
textAlign: "center",
|
|
88
93
|
fontWeight: "700",
|
|
89
94
|
},
|
|
90
95
|
subtitle: {
|
|
91
|
-
color: "#FFFFFF",
|
|
92
96
|
textAlign: "center",
|
|
93
97
|
marginTop: 8,
|
|
94
|
-
opacity: 0.9,
|
|
95
98
|
},
|
|
96
99
|
});
|
|
@@ -110,7 +110,10 @@ export const GenerationProgressContent: React.FC<
|
|
|
110
110
|
]}
|
|
111
111
|
onPress={onDismiss}
|
|
112
112
|
>
|
|
113
|
-
<AtomicText
|
|
113
|
+
<AtomicText
|
|
114
|
+
type="bodyMedium"
|
|
115
|
+
style={[styles.dismissText, { color: tokens.colors.textInverse }]}
|
|
116
|
+
>
|
|
114
117
|
{dismissLabel || "OK"}
|
|
115
118
|
</AtomicText>
|
|
116
119
|
</TouchableOpacity>
|
|
@@ -155,7 +158,6 @@ const styles = StyleSheet.create({
|
|
|
155
158
|
alignItems: "center",
|
|
156
159
|
},
|
|
157
160
|
dismissText: {
|
|
158
|
-
color: "#FFFFFF",
|
|
159
161
|
fontWeight: "600",
|
|
160
162
|
},
|
|
161
163
|
});
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
type ViewStyle,
|
|
16
16
|
type StyleProp,
|
|
17
17
|
} from "react-native";
|
|
18
|
-
import { LinearGradient } from "expo-linear-gradient";
|
|
19
18
|
import {
|
|
20
19
|
AtomicText,
|
|
21
20
|
AtomicIcon,
|
|
@@ -83,12 +82,12 @@ export const PhotoUploadCard: React.FC<PhotoUploadCardProps> = ({
|
|
|
83
82
|
|
|
84
83
|
const borderColor = useMemo(() => {
|
|
85
84
|
if (!cfg.showValidationStatus) {
|
|
86
|
-
return
|
|
85
|
+
return tokens.colors.borderLight;
|
|
87
86
|
}
|
|
88
87
|
if (isValidating) return tokens.colors.primary;
|
|
89
88
|
if (isValid === true) return tokens.colors.success;
|
|
90
89
|
if (isValid === false) return tokens.colors.error;
|
|
91
|
-
return
|
|
90
|
+
return tokens.colors.borderLight;
|
|
92
91
|
}, [isValidating, isValid, tokens, cfg.showValidationStatus]);
|
|
93
92
|
|
|
94
93
|
const styles = useMemo(
|
|
@@ -120,14 +119,8 @@ export const PhotoUploadCard: React.FC<PhotoUploadCardProps> = ({
|
|
|
120
119
|
alignItems: "center",
|
|
121
120
|
marginBottom: 20,
|
|
122
121
|
borderWidth: 2,
|
|
123
|
-
borderColor:
|
|
124
|
-
|
|
125
|
-
iconGradient: {
|
|
126
|
-
width: 88,
|
|
127
|
-
height: 88,
|
|
128
|
-
borderRadius: 44,
|
|
129
|
-
justifyContent: "center",
|
|
130
|
-
alignItems: "center",
|
|
122
|
+
borderColor: tokens.colors.borderLight,
|
|
123
|
+
backgroundColor: tokens.colors.surfaceSecondary,
|
|
131
124
|
},
|
|
132
125
|
title: {
|
|
133
126
|
fontSize: 20,
|
|
@@ -150,7 +143,8 @@ export const PhotoUploadCard: React.FC<PhotoUploadCardProps> = ({
|
|
|
150
143
|
},
|
|
151
144
|
imageOverlay: {
|
|
152
145
|
...StyleSheet.absoluteFillObject,
|
|
153
|
-
backgroundColor:
|
|
146
|
+
backgroundColor: tokens.colors.modalOverlay,
|
|
147
|
+
opacity: 0.3,
|
|
154
148
|
},
|
|
155
149
|
changeButton: {
|
|
156
150
|
position: "absolute",
|
|
@@ -185,7 +179,7 @@ export const PhotoUploadCard: React.FC<PhotoUploadCardProps> = ({
|
|
|
185
179
|
height: 100,
|
|
186
180
|
borderRadius: 50,
|
|
187
181
|
borderWidth: 2,
|
|
188
|
-
borderColor:
|
|
182
|
+
borderColor: tokens.colors.borderLight,
|
|
189
183
|
},
|
|
190
184
|
}),
|
|
191
185
|
[tokens, imageUri, cfg],
|
|
@@ -226,19 +220,11 @@ export const PhotoUploadCard: React.FC<PhotoUploadCardProps> = ({
|
|
|
226
220
|
) : (
|
|
227
221
|
<View style={styles.placeholder}>
|
|
228
222
|
<View style={styles.iconCircle}>
|
|
229
|
-
<
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
style={styles.iconGradient}
|
|
235
|
-
>
|
|
236
|
-
<AtomicIcon
|
|
237
|
-
name={(icon as string) || "camera"}
|
|
238
|
-
size={cfg.iconSize}
|
|
239
|
-
customColor={tokens.colors.primary}
|
|
240
|
-
/>
|
|
241
|
-
</LinearGradient>
|
|
223
|
+
<AtomicIcon
|
|
224
|
+
name={(icon as string) || "camera"}
|
|
225
|
+
size={cfg.iconSize}
|
|
226
|
+
customColor={tokens.colors.primary}
|
|
227
|
+
/>
|
|
242
228
|
</View>
|
|
243
229
|
<AtomicText style={styles.title}>
|
|
244
230
|
{title || translations.tapToUpload}
|
|
@@ -47,7 +47,10 @@ export const StylePresetsGrid: React.FC<StylePresetsGridProps> = ({
|
|
|
47
47
|
key={preset.id}
|
|
48
48
|
style={[
|
|
49
49
|
styles.card,
|
|
50
|
-
{
|
|
50
|
+
{
|
|
51
|
+
backgroundColor: tokens.colors.surface,
|
|
52
|
+
borderColor: tokens.colors.border,
|
|
53
|
+
},
|
|
51
54
|
]}
|
|
52
55
|
onPress={() => onPresetPress(preset)}
|
|
53
56
|
disabled={disabled}
|
|
@@ -58,7 +61,7 @@ export const StylePresetsGrid: React.FC<StylePresetsGridProps> = ({
|
|
|
58
61
|
<View
|
|
59
62
|
style={[
|
|
60
63
|
styles.badge,
|
|
61
|
-
{ backgroundColor: tokens.colors.
|
|
64
|
+
{ backgroundColor: tokens.colors.surfaceVariant },
|
|
62
65
|
]}
|
|
63
66
|
>
|
|
64
67
|
<AtomicText
|
|
@@ -109,7 +112,6 @@ const styles = StyleSheet.create({
|
|
|
109
112
|
padding: 16,
|
|
110
113
|
borderRadius: 16,
|
|
111
114
|
borderWidth: 1,
|
|
112
|
-
borderColor: "rgba(0,0,0,0.05)",
|
|
113
115
|
},
|
|
114
116
|
cardHeader: {
|
|
115
117
|
flexDirection: "row",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GenerateButton Component
|
|
3
|
-
* Generic AI generation button
|
|
3
|
+
* Generic AI generation button using design system tokens
|
|
4
4
|
* Props-driven for 100+ apps compatibility
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
AtomicIcon,
|
|
13
13
|
AtomicSpinner,
|
|
14
14
|
} from "@umituz/react-native-design-system";
|
|
15
|
-
import { LinearGradient } from "expo-linear-gradient";
|
|
16
15
|
|
|
17
16
|
export interface GenerateButtonProps {
|
|
18
17
|
readonly isDisabled?: boolean;
|
|
@@ -20,8 +19,6 @@ export interface GenerateButtonProps {
|
|
|
20
19
|
readonly onPress: () => void;
|
|
21
20
|
readonly text: string;
|
|
22
21
|
readonly processingText?: string;
|
|
23
|
-
readonly variant?: "gradient" | "solid";
|
|
24
|
-
readonly gradientColors?: readonly [string, string, ...string[]];
|
|
25
22
|
readonly icon?: string;
|
|
26
23
|
readonly iconSize?: number;
|
|
27
24
|
readonly costLabel?: string;
|
|
@@ -36,10 +33,8 @@ export const GenerateButton: React.FC<GenerateButtonProps> = ({
|
|
|
36
33
|
onPress,
|
|
37
34
|
text,
|
|
38
35
|
processingText,
|
|
39
|
-
variant = "gradient",
|
|
40
|
-
gradientColors = ["#FF6B9D", "#C74375", "#FF6B9D"],
|
|
41
36
|
icon = "sparkles",
|
|
42
|
-
iconSize =
|
|
37
|
+
iconSize = 20,
|
|
43
38
|
costLabel,
|
|
44
39
|
accessoryRight,
|
|
45
40
|
onAccessoryRightPress,
|
|
@@ -50,79 +45,48 @@ export const GenerateButton: React.FC<GenerateButtonProps> = ({
|
|
|
50
45
|
const displayText = isProcessing && processingText ? processingText : text;
|
|
51
46
|
const finalDisplayText = costLabel ? `${displayText} (${costLabel})` : displayText;
|
|
52
47
|
|
|
53
|
-
if (variant === "solid") {
|
|
54
|
-
return (
|
|
55
|
-
<View style={[styles.solidContainer, { marginTop: tokens.spacing.xl }, style]}>
|
|
56
|
-
<View style={styles.row}>
|
|
57
|
-
<TouchableOpacity
|
|
58
|
-
onPress={onPress}
|
|
59
|
-
disabled={disabled}
|
|
60
|
-
activeOpacity={0.8}
|
|
61
|
-
style={[
|
|
62
|
-
styles.solidButton,
|
|
63
|
-
{
|
|
64
|
-
backgroundColor: disabled
|
|
65
|
-
? tokens.colors.surfaceSecondary
|
|
66
|
-
: tokens.colors.primary,
|
|
67
|
-
flex: 1,
|
|
68
|
-
},
|
|
69
|
-
]}
|
|
70
|
-
>
|
|
71
|
-
<View style={styles.buttonContent}>
|
|
72
|
-
{isProcessing ? (
|
|
73
|
-
<AtomicSpinner size="sm" color="white" />
|
|
74
|
-
) : (
|
|
75
|
-
<AtomicIcon name={icon} customSize={20} customColor="#FFFFFF" />
|
|
76
|
-
)}
|
|
77
|
-
<AtomicText type="bodyLarge" style={styles.solidButtonText}>
|
|
78
|
-
{finalDisplayText}
|
|
79
|
-
</AtomicText>
|
|
80
|
-
</View>
|
|
81
|
-
</TouchableOpacity>
|
|
82
|
-
{accessoryRight && (
|
|
83
|
-
<TouchableOpacity
|
|
84
|
-
onPress={onAccessoryRightPress}
|
|
85
|
-
style={[styles.accessory, { backgroundColor: tokens.colors.surfaceSecondary }]}
|
|
86
|
-
>
|
|
87
|
-
{accessoryRight}
|
|
88
|
-
</TouchableOpacity>
|
|
89
|
-
)}
|
|
90
|
-
</View>
|
|
91
|
-
</View>
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
48
|
return (
|
|
96
|
-
<View style={[styles.
|
|
49
|
+
<View style={[styles.container, { marginTop: tokens.spacing.xl }, style]}>
|
|
97
50
|
<View style={styles.row}>
|
|
98
51
|
<TouchableOpacity
|
|
99
52
|
onPress={onPress}
|
|
100
53
|
disabled={disabled}
|
|
101
|
-
activeOpacity={0.
|
|
102
|
-
style={[
|
|
54
|
+
activeOpacity={0.8}
|
|
55
|
+
style={[
|
|
56
|
+
styles.button,
|
|
57
|
+
{
|
|
58
|
+
backgroundColor: disabled
|
|
59
|
+
? tokens.colors.surfaceSecondary
|
|
60
|
+
: tokens.colors.primary,
|
|
61
|
+
borderRadius: tokens.borderRadius.lg,
|
|
62
|
+
flex: 1,
|
|
63
|
+
},
|
|
64
|
+
]}
|
|
103
65
|
>
|
|
104
|
-
<
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
{finalDisplayText}
|
|
118
|
-
</AtomicText>
|
|
119
|
-
</View>
|
|
120
|
-
</LinearGradient>
|
|
66
|
+
<View style={styles.buttonContent}>
|
|
67
|
+
{isProcessing ? (
|
|
68
|
+
<AtomicSpinner size="sm" color={tokens.colors.textInverse} />
|
|
69
|
+
) : (
|
|
70
|
+
<AtomicIcon name={icon} customSize={iconSize} customColor={tokens.colors.textInverse} />
|
|
71
|
+
)}
|
|
72
|
+
<AtomicText
|
|
73
|
+
type="bodyLarge"
|
|
74
|
+
style={[styles.buttonText, { color: tokens.colors.textInverse }]}
|
|
75
|
+
>
|
|
76
|
+
{finalDisplayText}
|
|
77
|
+
</AtomicText>
|
|
78
|
+
</View>
|
|
121
79
|
</TouchableOpacity>
|
|
122
80
|
{accessoryRight && (
|
|
123
81
|
<TouchableOpacity
|
|
124
82
|
onPress={onAccessoryRightPress}
|
|
125
|
-
style={[
|
|
83
|
+
style={[
|
|
84
|
+
styles.accessory,
|
|
85
|
+
{
|
|
86
|
+
backgroundColor: tokens.colors.surfaceSecondary,
|
|
87
|
+
borderRadius: tokens.borderRadius.lg,
|
|
88
|
+
},
|
|
89
|
+
]}
|
|
126
90
|
>
|
|
127
91
|
{accessoryRight}
|
|
128
92
|
</TouchableOpacity>
|
|
@@ -133,35 +97,15 @@ export const GenerateButton: React.FC<GenerateButtonProps> = ({
|
|
|
133
97
|
};
|
|
134
98
|
|
|
135
99
|
const styles = StyleSheet.create({
|
|
136
|
-
|
|
137
|
-
alignItems: "center",
|
|
100
|
+
container: {
|
|
138
101
|
paddingHorizontal: 16,
|
|
139
102
|
},
|
|
140
|
-
|
|
141
|
-
paddingHorizontal: 16,
|
|
142
|
-
},
|
|
143
|
-
buttonWrapper: {
|
|
144
|
-
width: "100%",
|
|
145
|
-
maxWidth: 320,
|
|
146
|
-
borderRadius: 30,
|
|
147
|
-
},
|
|
148
|
-
gradientButton: {
|
|
149
|
-
paddingVertical: 18,
|
|
150
|
-
paddingHorizontal: 32,
|
|
151
|
-
borderRadius: 30,
|
|
152
|
-
alignItems: "center",
|
|
153
|
-
justifyContent: "center",
|
|
154
|
-
},
|
|
155
|
-
solidButton: {
|
|
156
|
-
borderRadius: 16,
|
|
103
|
+
button: {
|
|
157
104
|
paddingVertical: 16,
|
|
158
105
|
paddingHorizontal: 24,
|
|
159
106
|
alignItems: "center",
|
|
160
107
|
justifyContent: "center",
|
|
161
108
|
},
|
|
162
|
-
disabledButton: {
|
|
163
|
-
opacity: 0.5,
|
|
164
|
-
},
|
|
165
109
|
buttonContent: {
|
|
166
110
|
flexDirection: "row",
|
|
167
111
|
alignItems: "center",
|
|
@@ -175,19 +119,12 @@ const styles = StyleSheet.create({
|
|
|
175
119
|
width: "100%",
|
|
176
120
|
},
|
|
177
121
|
accessory: {
|
|
178
|
-
width:
|
|
179
|
-
height:
|
|
180
|
-
borderRadius: 16,
|
|
122
|
+
width: 56,
|
|
123
|
+
height: 56,
|
|
181
124
|
alignItems: "center",
|
|
182
125
|
justifyContent: "center",
|
|
183
126
|
},
|
|
184
|
-
|
|
185
|
-
color: "#FFFFFF",
|
|
186
|
-
fontWeight: "700",
|
|
187
|
-
fontSize: 18,
|
|
188
|
-
},
|
|
189
|
-
solidButtonText: {
|
|
190
|
-
color: "#FFFFFF",
|
|
127
|
+
buttonText: {
|
|
191
128
|
fontWeight: "600",
|
|
192
129
|
},
|
|
193
130
|
});
|
|
@@ -11,34 +11,41 @@ import {
|
|
|
11
11
|
AtomicText,
|
|
12
12
|
useAppDesignTokens,
|
|
13
13
|
} from "@umituz/react-native-design-system";
|
|
14
|
-
import { LinearGradient } from "expo-linear-gradient";
|
|
15
14
|
|
|
16
15
|
export interface FeatureHeaderProps {
|
|
17
16
|
readonly imageSource: ImageSourcePropType;
|
|
18
17
|
readonly description: string;
|
|
19
|
-
readonly gradientColors?: readonly [string, string, ...string[]];
|
|
20
18
|
readonly minHeight?: number;
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
export const FeatureHeader: React.FC<FeatureHeaderProps> = ({
|
|
24
22
|
imageSource,
|
|
25
23
|
description,
|
|
26
|
-
gradientColors = ["rgba(0,0,0,0.3)", "rgba(0,0,0,0.1)", "rgba(0,0,0,0.4)"],
|
|
27
24
|
minHeight = 200,
|
|
28
25
|
}) => {
|
|
29
26
|
const tokens = useAppDesignTokens();
|
|
30
27
|
|
|
31
28
|
return (
|
|
32
29
|
<>
|
|
33
|
-
<View
|
|
30
|
+
<View
|
|
31
|
+
style={[
|
|
32
|
+
styles.headerContainer,
|
|
33
|
+
{ borderColor: tokens.colors.border },
|
|
34
|
+
]}
|
|
35
|
+
>
|
|
34
36
|
<ImageBackground
|
|
35
37
|
source={imageSource}
|
|
36
38
|
style={[styles.heroImage, { minHeight }]}
|
|
37
39
|
imageStyle={styles.heroImageStyle}
|
|
38
40
|
>
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
<View
|
|
42
|
+
style={[
|
|
43
|
+
styles.overlay,
|
|
44
|
+
{
|
|
45
|
+
minHeight,
|
|
46
|
+
backgroundColor: tokens.colors.modalOverlay,
|
|
47
|
+
},
|
|
48
|
+
]}
|
|
42
49
|
/>
|
|
43
50
|
</ImageBackground>
|
|
44
51
|
</View>
|
|
@@ -65,7 +72,6 @@ const styles = StyleSheet.create({
|
|
|
65
72
|
borderRadius: 20,
|
|
66
73
|
overflow: "hidden",
|
|
67
74
|
borderWidth: 1,
|
|
68
|
-
borderColor: "rgba(255, 255, 255, 0.1)",
|
|
69
75
|
},
|
|
70
76
|
heroImage: {
|
|
71
77
|
width: "100%",
|
|
@@ -73,7 +79,7 @@ const styles = StyleSheet.create({
|
|
|
73
79
|
heroImageStyle: {
|
|
74
80
|
borderRadius: 20,
|
|
75
81
|
},
|
|
76
|
-
|
|
82
|
+
overlay: {
|
|
77
83
|
flex: 1,
|
|
78
84
|
},
|
|
79
85
|
description: {
|
|
@@ -17,8 +17,6 @@ export interface DualImagePickerProps {
|
|
|
17
17
|
readonly onSelectTarget: () => void;
|
|
18
18
|
readonly sourcePlaceholder: string;
|
|
19
19
|
readonly targetPlaceholder: string;
|
|
20
|
-
readonly sourceGradient?: ImagePickerBoxProps["gradientColors"];
|
|
21
|
-
readonly targetGradient?: ImagePickerBoxProps["gradientColors"];
|
|
22
20
|
readonly variant?: ImagePickerBoxProps["variant"];
|
|
23
21
|
readonly layout?: "horizontal" | "vertical";
|
|
24
22
|
}
|
|
@@ -31,8 +29,6 @@ export const DualImagePicker: React.FC<DualImagePickerProps> = ({
|
|
|
31
29
|
onSelectTarget,
|
|
32
30
|
sourcePlaceholder,
|
|
33
31
|
targetPlaceholder,
|
|
34
|
-
sourceGradient = ["#667eea", "#764ba2"],
|
|
35
|
-
targetGradient = ["#f093fb", "#f5576c"],
|
|
36
32
|
variant = "portrait",
|
|
37
33
|
layout = "horizontal",
|
|
38
34
|
}) => {
|
|
@@ -53,7 +49,6 @@ export const DualImagePicker: React.FC<DualImagePickerProps> = ({
|
|
|
53
49
|
isDisabled={isDisabled}
|
|
54
50
|
onPress={onSelectSource}
|
|
55
51
|
placeholderText={sourcePlaceholder}
|
|
56
|
-
gradientColors={sourceGradient}
|
|
57
52
|
variant={variant}
|
|
58
53
|
/>
|
|
59
54
|
</View>
|
|
@@ -64,7 +59,6 @@ export const DualImagePicker: React.FC<DualImagePickerProps> = ({
|
|
|
64
59
|
isDisabled={isDisabled}
|
|
65
60
|
onPress={onSelectTarget}
|
|
66
61
|
placeholderText={targetPlaceholder}
|
|
67
|
-
gradientColors={targetGradient}
|
|
68
62
|
variant={variant}
|
|
69
63
|
/>
|
|
70
64
|
</View>
|