@umituz/react-native-ai-generation-content 1.17.252 → 1.17.254

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 (31) hide show
  1. package/package.json +1 -1
  2. package/src/features/love-message/domain/constants.ts +162 -0
  3. package/src/features/love-message/domain/types.ts +58 -0
  4. package/src/features/love-message/index.ts +35 -0
  5. package/src/features/love-message/infrastructure/persistence/PartnerProfileRepository.ts +58 -0
  6. package/src/features/love-message/infrastructure/prompts/messagePromptBuilder.ts +109 -0
  7. package/src/features/love-message/infrastructure/services/LoveMessageService.ts +35 -0
  8. package/src/features/love-message/presentation/components/CategoryGrid.tsx +87 -0
  9. package/src/features/love-message/presentation/components/DetailsInput.tsx +74 -0
  10. package/src/features/love-message/presentation/components/ExploreHeader.tsx +67 -0
  11. package/src/features/love-message/presentation/components/FieldInput.tsx +83 -0
  12. package/src/features/love-message/presentation/components/GeneratorHeader.tsx +90 -0
  13. package/src/features/love-message/presentation/components/LoveMessageHeroSection.tsx +114 -0
  14. package/src/features/love-message/presentation/components/MessageListItem.tsx +76 -0
  15. package/src/features/love-message/presentation/components/MessageResult.tsx +105 -0
  16. package/src/features/love-message/presentation/components/PartnerInput.tsx +78 -0
  17. package/src/features/love-message/presentation/components/ProgressDots.tsx +48 -0
  18. package/src/features/love-message/presentation/components/StepDetails.tsx +23 -0
  19. package/src/features/love-message/presentation/components/StepPartner.tsx +116 -0
  20. package/src/features/love-message/presentation/components/StepVibe.tsx +30 -0
  21. package/src/features/love-message/presentation/components/ToneSelector.tsx +99 -0
  22. package/src/features/love-message/presentation/components/TrendingSection.tsx +130 -0
  23. package/src/features/love-message/presentation/components/TypeSelector.tsx +98 -0
  24. package/src/features/love-message/presentation/hooks/useLoveMessageGenerator.ts +111 -0
  25. package/src/features/love-message/presentation/hooks/usePartnerProfile.ts +46 -0
  26. package/src/features/love-message/presentation/navigation/LoveMessageStack.tsx +40 -0
  27. package/src/features/love-message/presentation/screens/LoveMessageExploreScreen.tsx +89 -0
  28. package/src/features/love-message/presentation/screens/LoveMessageGeneratorScreen.tsx +128 -0
  29. package/src/features/love-message/presentation/screens/MessageListScreen.tsx +99 -0
  30. package/src/features/love-message/presentation/screens/PartnerProfileScreen.tsx +100 -0
  31. package/src/index.ts +1 -0
@@ -0,0 +1,83 @@
1
+ /**
2
+ * FieldInput Component
3
+ */
4
+
5
+ import React from "react";
6
+ import { View, TextInput, StyleSheet } from "react-native";
7
+ import {
8
+ AtomicText,
9
+ useAppDesignTokens,
10
+ } from "@umituz/react-native-design-system";
11
+
12
+ interface FieldInputProps {
13
+ label: string;
14
+ value: string | undefined;
15
+ onChange: (text: string) => void;
16
+ placeholder: string;
17
+ multiline?: boolean;
18
+ }
19
+
20
+ export const FieldInput: React.FC<FieldInputProps> = ({
21
+ label,
22
+ value,
23
+ onChange,
24
+ placeholder,
25
+ multiline = false,
26
+ }) => {
27
+ const tokens = useAppDesignTokens();
28
+
29
+ return (
30
+ <View style={styles.field}>
31
+ <AtomicText type="labelLarge" color="textPrimary" style={styles.label}>
32
+ {label}
33
+ </AtomicText>
34
+ <View
35
+ style={[
36
+ styles.inputContainer,
37
+ multiline && styles.textAreaContainer,
38
+ {
39
+ backgroundColor: tokens.colors.surface,
40
+ borderColor: tokens.colors.borderLight,
41
+ },
42
+ ]}
43
+ >
44
+ <TextInput
45
+ value={value}
46
+ onChangeText={onChange}
47
+ placeholder={placeholder}
48
+ placeholderTextColor={tokens.colors.textTertiary}
49
+ multiline={multiline}
50
+ numberOfLines={multiline ? 4 : 1}
51
+ style={[styles.input, { color: tokens.colors.textPrimary }]}
52
+ selectionColor={tokens.colors.primary}
53
+ textAlignVertical={multiline ? "top" : "center"}
54
+ />
55
+ </View>
56
+ </View>
57
+ );
58
+ };
59
+
60
+ const styles = StyleSheet.create({
61
+ field: {
62
+ marginBottom: 24,
63
+ },
64
+ label: {
65
+ marginBottom: 10,
66
+ marginLeft: 4,
67
+ },
68
+ inputContainer: {
69
+ borderRadius: 16,
70
+ borderWidth: 1.5,
71
+ paddingHorizontal: 16,
72
+ height: 56,
73
+ justifyContent: "center",
74
+ },
75
+ textAreaContainer: {
76
+ height: 120,
77
+ paddingVertical: 12,
78
+ },
79
+ input: {
80
+ fontSize: 16,
81
+ padding: 0,
82
+ },
83
+ });
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Generator Header Component
3
+ */
4
+
5
+ import React from "react";
6
+ import { View, Pressable, StyleSheet } from "react-native";
7
+ import {
8
+ AtomicText,
9
+ AtomicIcon,
10
+ useAppDesignTokens,
11
+ useSafeAreaInsets,
12
+ } from "@umituz/react-native-design-system";
13
+ import { useLocalization } from "@umituz/react-native-localization";
14
+
15
+ interface GeneratorHeaderProps {
16
+ currentStep: number;
17
+ partnerName: string;
18
+ onBack: () => void;
19
+ onNext: () => void;
20
+ onGenerate: () => void;
21
+ isGenerating: boolean;
22
+ }
23
+
24
+ export const GeneratorHeader: React.FC<GeneratorHeaderProps> = ({
25
+ currentStep,
26
+ partnerName,
27
+ onBack,
28
+ onNext,
29
+ onGenerate,
30
+ isGenerating,
31
+ }) => {
32
+ const tokens = useAppDesignTokens();
33
+ const { top } = useSafeAreaInsets();
34
+ const { t } = useLocalization();
35
+
36
+ const isResultStep = currentStep === 3;
37
+ const isDetailsStep = currentStep === 2;
38
+ const isPartnerStep = currentStep === 0;
39
+
40
+ return (
41
+ <View style={[styles.header, { paddingTop: top + 10 }]}>
42
+ <Pressable onPress={onBack} style={styles.backBtn}>
43
+ <AtomicIcon name="arrow-back" color="textPrimary" size="sm" />
44
+ </Pressable>
45
+
46
+ <AtomicText type="labelLarge" color="textPrimary" style={styles.headerTitle}>
47
+ AI Generator
48
+ </AtomicText>
49
+
50
+ {!isResultStep ? (
51
+ <Pressable
52
+ onPress={isDetailsStep ? onGenerate : onNext}
53
+ disabled={(isPartnerStep && !partnerName.trim()) || isGenerating}
54
+ style={styles.headerActionBtn}
55
+ >
56
+ <AtomicText
57
+ type="labelMedium"
58
+ color={(isPartnerStep && !partnerName.trim()) ? "textTertiary" : "primary"}
59
+ style={{ fontWeight: 'bold' }}
60
+ >
61
+ {isDetailsStep ? t("loveMessage.generate") : t("common.continue") || "Continue"}
62
+ </AtomicText>
63
+ </Pressable>
64
+ ) : (
65
+ <View style={{ width: 44 }} />
66
+ )}
67
+ </View>
68
+ );
69
+ };
70
+
71
+ const styles = StyleSheet.create({
72
+ header: {
73
+ flexDirection: "row",
74
+ justifyContent: "space-between",
75
+ alignItems: "center",
76
+ paddingHorizontal: 16,
77
+ paddingBottom: 10,
78
+ },
79
+ backBtn: {
80
+ padding: 10,
81
+ },
82
+ headerTitle: {
83
+ fontWeight: "800",
84
+ },
85
+ headerActionBtn: {
86
+ padding: 10,
87
+ minWidth: 44,
88
+ alignItems: 'flex-end',
89
+ },
90
+ });
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Hero Section Component
3
+ */
4
+
5
+ import React from "react";
6
+ import { View, Pressable, ImageBackground, StyleSheet } from "react-native";
7
+ import {
8
+ AtomicText,
9
+ AtomicIcon,
10
+ useAppDesignTokens,
11
+ } from "@umituz/react-native-design-system";
12
+ import { useLocalization } from "@umituz/react-native-localization";
13
+
14
+ export const HeroSection: React.FC = () => {
15
+ const tokens = useAppDesignTokens();
16
+ const { t } = useLocalization();
17
+
18
+ return (
19
+ <View style={styles.heroSection}>
20
+ <ImageBackground
21
+ source={{ uri: 'https://images.unsplash.com/photo-1518621736915-f3b1c41bfd00?q=80&w=600&auto=format&fit=crop' }}
22
+ style={styles.heroImage}
23
+ imageStyle={styles.heroImageBorder}
24
+ >
25
+ <View style={styles.heroOverlay}>
26
+ <View style={[styles.glassCard, { backgroundColor: `${tokens.colors.surface}B0` }]}>
27
+ <View style={styles.quoteHeader}>
28
+ <AtomicText type="labelSmall" color="primary" style={styles.quoteTag}>
29
+ {t("loveMessage.explore.heroTag")}
30
+ </AtomicText>
31
+ <AtomicIcon name="quote-outline" color="primary" size="xs" />
32
+ </View>
33
+ <AtomicText type="bodyMedium" color="textPrimary" style={styles.quoteText}>
34
+ {`"Love is not about how many days, months, or years you have been together, but about how much you love each other every single day."`}
35
+ </AtomicText>
36
+ <View style={styles.heroActions}>
37
+ <Pressable style={[styles.shareBtn, { backgroundColor: tokens.colors.primary }]}>
38
+ <AtomicIcon name="share-social-outline" color="onPrimary" size="xs" />
39
+ <AtomicText type="labelSmall" color="onPrimary" style={styles.shareText}>
40
+ {t("loveMessage.explore.shareNow")}
41
+ </AtomicText>
42
+ </Pressable>
43
+ <Pressable style={[styles.favBtn, { backgroundColor: `${tokens.colors.textPrimary}15` }]}>
44
+ <AtomicIcon name="heart-outline" color="textPrimary" size="xs" />
45
+ </Pressable>
46
+ </View>
47
+ </View>
48
+ </View>
49
+ </ImageBackground>
50
+ </View>
51
+ );
52
+ };
53
+
54
+ const styles = StyleSheet.create({
55
+ heroSection: {
56
+ paddingHorizontal: 16,
57
+ marginBottom: 32,
58
+ },
59
+ heroImage: {
60
+ width: '100%',
61
+ height: 300,
62
+ justifyContent: 'flex-end',
63
+ },
64
+ heroImageBorder: {
65
+ borderRadius: 24,
66
+ },
67
+ heroOverlay: {
68
+ padding: 12,
69
+ },
70
+ glassCard: {
71
+ borderRadius: 20,
72
+ padding: 16,
73
+ borderWidth: 1,
74
+ borderColor: 'rgba(255,255,255,0.1)',
75
+ },
76
+ quoteHeader: {
77
+ flexDirection: 'row',
78
+ justifyContent: 'space-between',
79
+ alignItems: 'center',
80
+ marginBottom: 8,
81
+ },
82
+ quoteTag: {
83
+ fontWeight: 'bold',
84
+ letterSpacing: 1,
85
+ },
86
+ quoteText: {
87
+ fontStyle: 'italic',
88
+ lineHeight: 22,
89
+ marginBottom: 16,
90
+ },
91
+ heroActions: {
92
+ flexDirection: 'row',
93
+ gap: 8,
94
+ },
95
+ shareBtn: {
96
+ flex: 1,
97
+ flexDirection: 'row',
98
+ alignItems: 'center',
99
+ justifyContent: 'center',
100
+ height: 40,
101
+ borderRadius: 20,
102
+ gap: 8,
103
+ },
104
+ shareText: {
105
+ fontWeight: 'bold',
106
+ },
107
+ favBtn: {
108
+ width: 44,
109
+ height: 40,
110
+ borderRadius: 20,
111
+ alignItems: 'center',
112
+ justifyContent: 'center',
113
+ },
114
+ });
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Message List Item Component
3
+ */
4
+
5
+ import React from "react";
6
+ import { View, Pressable, ImageBackground, StyleSheet } from "react-native";
7
+ import {
8
+ AtomicText,
9
+ AtomicButton,
10
+ AtomicIcon,
11
+ useAppDesignTokens,
12
+ } from "@umituz/react-native-design-system";
13
+ import { useLocalization } from "@umituz/react-native-localization";
14
+
15
+ interface MessageListItemProps {
16
+ item: any;
17
+ onShare: (text: string) => void;
18
+ }
19
+
20
+ export const MessageListItem: React.FC<MessageListItemProps> = ({ item, onShare }) => {
21
+ const tokens = useAppDesignTokens();
22
+ const { t } = useLocalization();
23
+
24
+ return (
25
+ <View style={[styles.card, { backgroundColor: tokens.colors.surface, borderColor: tokens.colors.borderLight }]}>
26
+ {item.imageUrl && (
27
+ <ImageBackground
28
+ source={{ uri: item.imageUrl }}
29
+ style={styles.cardImage}
30
+ imageStyle={{ borderTopLeftRadius: 16, borderTopRightRadius: 16 }}
31
+ />
32
+ )}
33
+ <View style={styles.cardContent}>
34
+ <AtomicText type="bodyLarge" color="textPrimary" style={styles.messageText}>
35
+ {`"${item.text}"`}
36
+ </AtomicText>
37
+
38
+ <View style={[styles.cardFooter, { borderTopColor: tokens.colors.borderLight }]}>
39
+ <View style={styles.actionRow}>
40
+ <Pressable style={[styles.iconBtn, { backgroundColor: tokens.colors.surfaceSecondary }]}>
41
+ <AtomicIcon name="copy-outline" color="textSecondary" size="xs" />
42
+ </Pressable>
43
+ <Pressable
44
+ onPress={() => onShare(item.text)}
45
+ style={[styles.iconBtn, { backgroundColor: tokens.colors.surfaceSecondary }]}
46
+ >
47
+ <AtomicIcon name="share-social-outline" color="textSecondary" size="xs" />
48
+ </Pressable>
49
+ <Pressable style={[styles.iconBtn, { backgroundColor: tokens.colors.surfaceSecondary }]}>
50
+ <AtomicIcon name="heart-outline" color="textSecondary" size="xs" />
51
+ </Pressable>
52
+ </View>
53
+
54
+ <AtomicButton
55
+ title={t("loveMessage.generator.sendNow")}
56
+ onPress={() => {}}
57
+ variant="primary"
58
+ size="sm"
59
+ style={styles.sendBtn}
60
+ />
61
+ </View>
62
+ </View>
63
+ </View>
64
+ );
65
+ };
66
+
67
+ const styles = StyleSheet.create({
68
+ card: { borderRadius: 16, borderWidth: 1, marginBottom: 20, overflow: 'hidden' },
69
+ cardImage: { width: '100%', height: 180 },
70
+ cardContent: { padding: 20 },
71
+ messageText: { fontStyle: 'italic', lineHeight: 24, marginBottom: 20 },
72
+ cardFooter: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingTop: 16, borderTopWidth: 1 },
73
+ actionRow: { flexDirection: 'row', gap: 8 },
74
+ iconBtn: { width: 36, height: 36, borderRadius: 18, alignItems: 'center', justifyContent: 'center' },
75
+ sendBtn: { minWidth: 100, height: 36, borderRadius: 18 },
76
+ });
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Generated Message Result Component
3
+ */
4
+
5
+ import type { FC } from "react";
6
+ import { View, StyleSheet, Share } from "react-native";
7
+ import {
8
+ AtomicText,
9
+ AtomicButton,
10
+ AtomicIcon,
11
+ useAppDesignTokens,
12
+ } from "@umituz/react-native-design-system";
13
+ import { useLocalization } from "@umituz/react-native-localization";
14
+
15
+ interface MessageResultProps {
16
+ message: string;
17
+ }
18
+
19
+ export const MessageResult: FC<MessageResultProps> = ({ message }) => {
20
+ const tokens = useAppDesignTokens();
21
+ const { t } = useLocalization();
22
+
23
+ if (!message) return null;
24
+
25
+ const handleShare = async () => {
26
+ try {
27
+ await Share.share({
28
+ message: message,
29
+ });
30
+ } catch {
31
+ // Handle error if needed
32
+ }
33
+ };
34
+
35
+ return (
36
+ <View
37
+ style={[
38
+ styles.container,
39
+ {
40
+ backgroundColor: tokens.colors.surface,
41
+ borderColor: tokens.colors.primary,
42
+ },
43
+ ]}
44
+ >
45
+ <View style={styles.header}>
46
+ <View style={styles.titleRow}>
47
+ <AtomicIcon name="sparkles" color="primary" size="sm" />
48
+ <AtomicText type="labelLarge" color="primary" style={styles.title}>
49
+ {t("loveMessage.yourMessage")}
50
+ </AtomicText>
51
+ </View>
52
+ <AtomicButton
53
+ icon="share-social-outline"
54
+ onPress={handleShare}
55
+ variant="text"
56
+ size="sm"
57
+ />
58
+ </View>
59
+ <View
60
+ style={[styles.divider, { backgroundColor: tokens.colors.borderLight }]}
61
+ />
62
+ <AtomicText
63
+ type="bodyLarge"
64
+ color="textPrimary"
65
+ style={styles.messageText}
66
+ >
67
+ {message}
68
+ </AtomicText>
69
+ </View>
70
+ );
71
+ };
72
+
73
+ const styles = StyleSheet.create({
74
+ container: {
75
+ marginTop: 32,
76
+ borderRadius: 24,
77
+ padding: 24,
78
+ borderWidth: 2,
79
+ },
80
+ header: {
81
+ flexDirection: "row",
82
+ justifyContent: "space-between",
83
+ alignItems: "center",
84
+ marginBottom: 16,
85
+ },
86
+ titleRow: {
87
+ flexDirection: "row",
88
+ alignItems: "center",
89
+ },
90
+ title: {
91
+ marginLeft: 8,
92
+ fontWeight: "bold",
93
+ letterSpacing: 0.5,
94
+ },
95
+ divider: {
96
+ height: 1,
97
+ marginBottom: 20,
98
+ opacity: 0.5,
99
+ },
100
+ messageText: {
101
+ lineHeight: 26,
102
+ fontStyle: "italic",
103
+ textAlign: "center",
104
+ },
105
+ });
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Partner Name Input Component
3
+ * Updated with Icon support to match premium design
4
+ */
5
+
6
+ import type { FC } from "react";
7
+ import { View, TextInput, StyleSheet } from "react-native";
8
+ import {
9
+ AtomicText,
10
+ AtomicIcon,
11
+ useAppDesignTokens,
12
+ } from "@umituz/react-native-design-system";
13
+ import { useLocalization } from "@umituz/react-native-localization";
14
+
15
+ interface PartnerInputProps {
16
+ value: string;
17
+ onChangeText: (text: string) => void;
18
+ }
19
+
20
+ export const PartnerInput: FC<PartnerInputProps> = ({
21
+ value,
22
+ onChangeText,
23
+ }) => {
24
+ const tokens = useAppDesignTokens();
25
+ const { t } = useLocalization();
26
+
27
+ return (
28
+ <View style={styles.container}>
29
+ <AtomicText
30
+ type="labelSmall"
31
+ color="textTertiary"
32
+ style={styles.label}
33
+ >
34
+ {t("loveMessage.partnerName").toUpperCase()}
35
+ </AtomicText>
36
+ <View style={[styles.inputWrapper, {
37
+ backgroundColor: tokens.colors.surfaceSecondary,
38
+ }]}>
39
+ <AtomicIcon name="heart" color="primary" size="sm" style={styles.icon} />
40
+ <TextInput
41
+ value={value}
42
+ onChangeText={onChangeText}
43
+ placeholder={t("loveMessage.partnerNamePlaceholder")}
44
+ placeholderTextColor={tokens.colors.textTertiary}
45
+ style={[styles.input, { color: tokens.colors.textPrimary }]}
46
+ selectionColor={tokens.colors.primary}
47
+ />
48
+ </View>
49
+ </View>
50
+ );
51
+ };
52
+
53
+ const styles = StyleSheet.create({
54
+ container: {
55
+ marginBottom: 24,
56
+ },
57
+ label: {
58
+ marginBottom: 8,
59
+ marginLeft: 4,
60
+ fontWeight: 'bold',
61
+ letterSpacing: 1,
62
+ },
63
+ inputWrapper: {
64
+ flexDirection: 'row',
65
+ alignItems: 'center',
66
+ borderRadius: 16,
67
+ paddingHorizontal: 16,
68
+ height: 56,
69
+ },
70
+ icon: {
71
+ marginRight: 12,
72
+ },
73
+ input: {
74
+ flex: 1,
75
+ fontSize: 16,
76
+ padding: 0,
77
+ },
78
+ });
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Step Progress Indicator
3
+ * Simple and premium dot-based progress
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, StyleSheet } from "react-native";
8
+ import { useAppDesignTokens } from "@umituz/react-native-design-system";
9
+
10
+ interface ProgressDotsProps {
11
+ currentStep: number;
12
+ totalSteps: number;
13
+ }
14
+
15
+ export const ProgressDots: React.FC<ProgressDotsProps> = ({ currentStep, totalSteps }) => {
16
+ const tokens = useAppDesignTokens();
17
+
18
+ return (
19
+ <View style={styles.container}>
20
+ {Array.from({ length: totalSteps }).map((_, index) => (
21
+ <View
22
+ key={index}
23
+ style={[
24
+ styles.dot,
25
+ {
26
+ backgroundColor: index <= currentStep ? tokens.colors.primary : tokens.colors.surfaceSecondary,
27
+ width: index === currentStep ? 24 : 8,
28
+ opacity: index <= currentStep ? 1 : 0.5
29
+ }
30
+ ]}
31
+ />
32
+ ))}
33
+ </View>
34
+ );
35
+ };
36
+
37
+ const styles = StyleSheet.create({
38
+ container: {
39
+ flexDirection: 'row',
40
+ justifyContent: 'center',
41
+ gap: 6,
42
+ marginBottom: 24,
43
+ },
44
+ dot: {
45
+ height: 8,
46
+ borderRadius: 4,
47
+ },
48
+ });
@@ -0,0 +1,23 @@
1
+ /**
2
+ * StepDetails Component
3
+ */
4
+
5
+ import React from "react";
6
+ import { View } from "react-native";
7
+ import { DetailsInput } from "./DetailsInput";
8
+
9
+ interface StepDetailsProps {
10
+ details: string;
11
+ setDetails: (text: string) => void;
12
+ }
13
+
14
+ export const StepDetails: React.FC<StepDetailsProps> = ({
15
+ details,
16
+ setDetails,
17
+ }) => {
18
+ return (
19
+ <View>
20
+ <DetailsInput value={details} onChangeText={setDetails} />
21
+ </View>
22
+ );
23
+ };