@umituz/react-native-ai-generation-content 1.17.86 → 1.17.87
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 +3 -3
- 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
|
@@ -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>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ImagePickerBox Component
|
|
3
|
-
* Generic image picker box with
|
|
3
|
+
* Generic image picker box with solid color design
|
|
4
4
|
* Props-driven for 100+ apps compatibility
|
|
5
5
|
*/
|
|
6
6
|
|
|
@@ -17,14 +17,12 @@ import {
|
|
|
17
17
|
useAppDesignTokens,
|
|
18
18
|
AtomicIcon,
|
|
19
19
|
} from "@umituz/react-native-design-system";
|
|
20
|
-
import { LinearGradient } from "expo-linear-gradient";
|
|
21
20
|
|
|
22
21
|
export interface ImagePickerBoxProps {
|
|
23
22
|
readonly imageUri: string | null;
|
|
24
23
|
readonly isDisabled?: boolean;
|
|
25
24
|
readonly onPress: () => void;
|
|
26
25
|
readonly placeholderText: string;
|
|
27
|
-
readonly gradientColors?: readonly [string, string, ...string[]];
|
|
28
26
|
readonly variant?: "portrait" | "square" | "landscape";
|
|
29
27
|
readonly size?: "sm" | "md" | "lg";
|
|
30
28
|
readonly uploadIcon?: string;
|
|
@@ -44,7 +42,6 @@ export const ImagePickerBox: React.FC<ImagePickerBoxProps> = ({
|
|
|
44
42
|
isDisabled = false,
|
|
45
43
|
onPress,
|
|
46
44
|
placeholderText,
|
|
47
|
-
gradientColors = ["#667eea", "#764ba2"],
|
|
48
45
|
variant = "portrait",
|
|
49
46
|
size = "md",
|
|
50
47
|
uploadIcon = "cloud-upload-outline",
|
|
@@ -70,42 +67,57 @@ export const ImagePickerBox: React.FC<ImagePickerBoxProps> = ({
|
|
|
70
67
|
{imageUri ? (
|
|
71
68
|
<View style={styles.imageContainer}>
|
|
72
69
|
<Image source={{ uri: imageUri }} style={styles.image} />
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
<View
|
|
71
|
+
style={[
|
|
72
|
+
styles.imageOverlay,
|
|
73
|
+
{ backgroundColor: tokens.colors.modalOverlay },
|
|
74
|
+
]}
|
|
76
75
|
>
|
|
77
76
|
<View
|
|
78
77
|
style={[
|
|
79
78
|
styles.editBadge,
|
|
80
|
-
{ backgroundColor:
|
|
79
|
+
{ backgroundColor: tokens.colors.primary },
|
|
81
80
|
]}
|
|
82
81
|
>
|
|
83
82
|
<AtomicIcon
|
|
84
83
|
name={editIcon}
|
|
85
84
|
customSize={Math.round(16 * multiplier)}
|
|
86
|
-
customColor=
|
|
85
|
+
customColor={tokens.colors.textInverse}
|
|
87
86
|
/>
|
|
88
87
|
</View>
|
|
89
|
-
</
|
|
88
|
+
</View>
|
|
90
89
|
</View>
|
|
91
90
|
) : (
|
|
92
|
-
<
|
|
91
|
+
<View
|
|
92
|
+
style={[
|
|
93
|
+
styles.placeholder,
|
|
94
|
+
{ backgroundColor: tokens.colors.primary },
|
|
95
|
+
]}
|
|
96
|
+
>
|
|
93
97
|
<View style={styles.placeholderContent}>
|
|
94
|
-
<View
|
|
98
|
+
<View
|
|
99
|
+
style={[
|
|
100
|
+
styles.uploadIconContainer,
|
|
101
|
+
{ backgroundColor: tokens.colors.surface },
|
|
102
|
+
]}
|
|
103
|
+
>
|
|
95
104
|
<AtomicIcon
|
|
96
105
|
name={uploadIcon}
|
|
97
106
|
customSize={iconSize}
|
|
98
|
-
customColor=
|
|
107
|
+
customColor={tokens.colors.primary}
|
|
99
108
|
/>
|
|
100
109
|
</View>
|
|
101
110
|
<AtomicText
|
|
102
111
|
type="bodyMedium"
|
|
103
|
-
style={[
|
|
112
|
+
style={[
|
|
113
|
+
styles.placeholderText,
|
|
114
|
+
{ color: tokens.colors.textInverse },
|
|
115
|
+
]}
|
|
104
116
|
>
|
|
105
117
|
{placeholderText}
|
|
106
118
|
</AtomicText>
|
|
107
119
|
</View>
|
|
108
|
-
</
|
|
120
|
+
</View>
|
|
109
121
|
)}
|
|
110
122
|
</TouchableOpacity>
|
|
111
123
|
</View>
|
|
@@ -153,7 +165,6 @@ const styles = StyleSheet.create({
|
|
|
153
165
|
paddingHorizontal: 16,
|
|
154
166
|
},
|
|
155
167
|
uploadIconContainer: {
|
|
156
|
-
backgroundColor: "rgba(255,255,255,0.2)",
|
|
157
168
|
borderRadius: 40,
|
|
158
169
|
padding: 16,
|
|
159
170
|
marginBottom: 12,
|
|
@@ -53,7 +53,10 @@ export const SettingsSheet: React.FC<SettingsSheetProps> = ({
|
|
|
53
53
|
animationType="slide"
|
|
54
54
|
onRequestClose={onClose}
|
|
55
55
|
>
|
|
56
|
-
<Pressable
|
|
56
|
+
<Pressable
|
|
57
|
+
style={[styles.backdrop, { backgroundColor: tokens.colors.modalOverlay }]}
|
|
58
|
+
onPress={handleBackdropPress}
|
|
59
|
+
>
|
|
57
60
|
<Pressable
|
|
58
61
|
style={[
|
|
59
62
|
styles.sheet,
|
|
@@ -102,7 +105,6 @@ export const SettingsSheet: React.FC<SettingsSheetProps> = ({
|
|
|
102
105
|
const styles = StyleSheet.create({
|
|
103
106
|
backdrop: {
|
|
104
107
|
flex: 1,
|
|
105
|
-
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
106
108
|
justifyContent: "flex-end",
|
|
107
109
|
},
|
|
108
110
|
sheet: {
|
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
AtomicIcon,
|
|
12
12
|
useAppDesignTokens,
|
|
13
13
|
} from "@umituz/react-native-design-system";
|
|
14
|
-
import { LinearGradient } from "expo-linear-gradient";
|
|
15
14
|
import type { ResultImageConfig } from "../../types/result-config.types";
|
|
16
15
|
import { DEFAULT_RESULT_CONFIG } from "../../types/result-config.types";
|
|
17
16
|
|
|
@@ -45,12 +44,12 @@ export const ResultImageCard: React.FC<ResultImageCardProps> = ({
|
|
|
45
44
|
|
|
46
45
|
const badgeBackground = useMemo(() => {
|
|
47
46
|
if (cfg.badgeStyle === "light") {
|
|
48
|
-
return
|
|
47
|
+
return tokens.colors.surface;
|
|
49
48
|
} else if (cfg.badgeStyle === "dark") {
|
|
50
|
-
return
|
|
49
|
+
return tokens.colors.modalOverlay;
|
|
51
50
|
}
|
|
52
|
-
return
|
|
53
|
-
}, [cfg.badgeStyle]);
|
|
51
|
+
return tokens.colors.primary;
|
|
52
|
+
}, [cfg.badgeStyle, tokens]);
|
|
54
53
|
|
|
55
54
|
const styles = useMemo(
|
|
56
55
|
() =>
|
|
@@ -76,24 +75,17 @@ export const ResultImageCard: React.FC<ResultImageCardProps> = ({
|
|
|
76
75
|
gap: 4,
|
|
77
76
|
paddingHorizontal: 10,
|
|
78
77
|
paddingVertical: 5,
|
|
79
|
-
backgroundColor: badgeBackground
|
|
78
|
+
backgroundColor: badgeBackground,
|
|
80
79
|
borderRadius: 12,
|
|
81
80
|
overflow: "hidden",
|
|
82
81
|
},
|
|
83
|
-
gradientBadge: {
|
|
84
|
-
flexDirection: "row",
|
|
85
|
-
alignItems: "center",
|
|
86
|
-
gap: 4,
|
|
87
|
-
paddingHorizontal: 10,
|
|
88
|
-
paddingVertical: 5,
|
|
89
|
-
},
|
|
90
82
|
badgeText: {
|
|
91
83
|
fontSize: 10,
|
|
92
84
|
fontWeight: "700",
|
|
93
85
|
color:
|
|
94
86
|
cfg.badgeStyle === "light"
|
|
95
87
|
? tokens.colors.textPrimary
|
|
96
|
-
:
|
|
88
|
+
: tokens.colors.textInverse,
|
|
97
89
|
letterSpacing: 0.5,
|
|
98
90
|
},
|
|
99
91
|
}),
|
|
@@ -104,35 +96,20 @@ export const ResultImageCard: React.FC<ResultImageCardProps> = ({
|
|
|
104
96
|
if (!cfg.showBadge) return null;
|
|
105
97
|
|
|
106
98
|
const iconColor =
|
|
107
|
-
cfg.badgeStyle === "light"
|
|
99
|
+
cfg.badgeStyle === "light"
|
|
100
|
+
? tokens.colors.primary
|
|
101
|
+
: tokens.colors.textInverse;
|
|
108
102
|
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
return (
|
|
104
|
+
<View style={styles.badge}>
|
|
111
105
|
<AtomicIcon
|
|
112
106
|
name={cfg.badgeIcon ?? "sparkles"}
|
|
113
107
|
size="xs"
|
|
114
108
|
customColor={iconColor}
|
|
115
109
|
/>
|
|
116
110
|
<AtomicText style={styles.badgeText}>{badgeText}</AtomicText>
|
|
117
|
-
|
|
111
|
+
</View>
|
|
118
112
|
);
|
|
119
|
-
|
|
120
|
-
if (cfg.badgeStyle === "gradient") {
|
|
121
|
-
return (
|
|
122
|
-
<View style={styles.badge}>
|
|
123
|
-
<LinearGradient
|
|
124
|
-
colors={[tokens.colors.primary, tokens.colors.secondary]}
|
|
125
|
-
start={{ x: 0, y: 0 }}
|
|
126
|
-
end={{ x: 1, y: 0 }}
|
|
127
|
-
style={styles.gradientBadge}
|
|
128
|
-
>
|
|
129
|
-
{badgeContent}
|
|
130
|
-
</LinearGradient>
|
|
131
|
-
</View>
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
return <View style={styles.badge}>{badgeContent}</View>;
|
|
136
113
|
};
|
|
137
114
|
|
|
138
115
|
return (
|