@umituz/react-native-ai-generation-content 1.17.242 → 1.17.243
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 +3 -3
- package/src/domains/result-preview/presentation/components/RecentCreationsSection.tsx +180 -0
- package/src/domains/result-preview/presentation/components/ResultImageCard.tsx +3 -3
- package/src/domains/result-preview/presentation/components/ResultPreviewScreen.tsx +13 -0
- package/src/domains/result-preview/presentation/components/index.ts +1 -0
- package/src/domains/result-preview/presentation/types/result-preview.types.ts +22 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.243",
|
|
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",
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@umituz/react-native-auth": "latest",
|
|
41
|
-
"@umituz/react-native-design-system": "latest",
|
|
42
41
|
"@umituz/react-native-filesystem": "latest",
|
|
43
42
|
"@umituz/react-native-firebase": "latest",
|
|
44
43
|
"@umituz/react-native-tanstack": "latest"
|
|
@@ -63,7 +62,7 @@
|
|
|
63
62
|
"@types/react": "~19.1.10",
|
|
64
63
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
65
64
|
"@typescript-eslint/parser": "^8.0.0",
|
|
66
|
-
"@umituz/react-native-design-system": "
|
|
65
|
+
"@umituz/react-native-design-system": "^2.6.126",
|
|
67
66
|
"@umituz/react-native-filesystem": "latest",
|
|
68
67
|
"@umituz/react-native-firebase": "latest",
|
|
69
68
|
"@umituz/react-native-haptics": "latest",
|
|
@@ -80,6 +79,7 @@
|
|
|
80
79
|
"expo-haptics": "^15.0.8",
|
|
81
80
|
"expo-image": "^3.0.11",
|
|
82
81
|
"expo-localization": "^17.0.8",
|
|
82
|
+
"expo-media-library": "^18.2.1",
|
|
83
83
|
"expo-network": "^8.0.8",
|
|
84
84
|
"expo-sharing": "^14.0.8",
|
|
85
85
|
"expo-video": "^3.0.15",
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recent Creations Section Component
|
|
3
|
+
* Displays recent creations in a grid layout
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { useMemo, useCallback } from "react";
|
|
7
|
+
import { StyleSheet, View, TouchableOpacity, FlatList } from "react-native";
|
|
8
|
+
import {
|
|
9
|
+
AtomicText,
|
|
10
|
+
AtomicImage,
|
|
11
|
+
AtomicIcon,
|
|
12
|
+
useAppDesignTokens,
|
|
13
|
+
} from "@umituz/react-native-design-system";
|
|
14
|
+
import type { RecentCreation } from "../types/result-preview.types";
|
|
15
|
+
|
|
16
|
+
interface RecentCreationsSectionProps {
|
|
17
|
+
readonly recentCreations: readonly RecentCreation[];
|
|
18
|
+
readonly onViewAll?: () => void;
|
|
19
|
+
readonly onCreationPress?: (creation: RecentCreation) => void;
|
|
20
|
+
readonly title: string;
|
|
21
|
+
readonly viewAllLabel: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const RecentCreationsSection: React.FC<RecentCreationsSectionProps> = ({
|
|
25
|
+
recentCreations,
|
|
26
|
+
onViewAll,
|
|
27
|
+
onCreationPress,
|
|
28
|
+
title,
|
|
29
|
+
viewAllLabel,
|
|
30
|
+
}) => {
|
|
31
|
+
const tokens = useAppDesignTokens();
|
|
32
|
+
|
|
33
|
+
const styles = useMemo(
|
|
34
|
+
() =>
|
|
35
|
+
StyleSheet.create({
|
|
36
|
+
container: {
|
|
37
|
+
marginTop: tokens.spacing.xl,
|
|
38
|
+
paddingHorizontal: tokens.spacing.md,
|
|
39
|
+
},
|
|
40
|
+
header: {
|
|
41
|
+
flexDirection: "row",
|
|
42
|
+
justifyContent: "space-between",
|
|
43
|
+
alignItems: "center",
|
|
44
|
+
marginBottom: tokens.spacing.md,
|
|
45
|
+
},
|
|
46
|
+
title: {
|
|
47
|
+
fontSize: 20,
|
|
48
|
+
fontWeight: "700",
|
|
49
|
+
color: tokens.colors.textPrimary,
|
|
50
|
+
},
|
|
51
|
+
viewAllButton: {
|
|
52
|
+
paddingHorizontal: tokens.spacing.sm,
|
|
53
|
+
paddingVertical: tokens.spacing.xs,
|
|
54
|
+
},
|
|
55
|
+
viewAllText: {
|
|
56
|
+
fontSize: 12,
|
|
57
|
+
fontWeight: "700",
|
|
58
|
+
color: tokens.colors.primary,
|
|
59
|
+
textTransform: "uppercase",
|
|
60
|
+
letterSpacing: 0.5,
|
|
61
|
+
},
|
|
62
|
+
grid: {
|
|
63
|
+
gap: tokens.spacing.md,
|
|
64
|
+
},
|
|
65
|
+
creationItem: {
|
|
66
|
+
flex: 1,
|
|
67
|
+
marginHorizontal: tokens.spacing.xs,
|
|
68
|
+
},
|
|
69
|
+
imageContainer: {
|
|
70
|
+
width: "100%",
|
|
71
|
+
aspectRatio: 4 / 5,
|
|
72
|
+
borderRadius: tokens.borders.radius.md,
|
|
73
|
+
overflow: "hidden",
|
|
74
|
+
backgroundColor: tokens.colors.backgroundSecondary,
|
|
75
|
+
position: "relative",
|
|
76
|
+
},
|
|
77
|
+
image: {
|
|
78
|
+
width: "100%",
|
|
79
|
+
height: "100%",
|
|
80
|
+
},
|
|
81
|
+
favoriteIcon: {
|
|
82
|
+
position: "absolute",
|
|
83
|
+
bottom: 8,
|
|
84
|
+
right: 8,
|
|
85
|
+
backgroundColor: "rgba(0, 0, 0, 0.6)",
|
|
86
|
+
borderRadius: tokens.borders.radius.full,
|
|
87
|
+
padding: 6,
|
|
88
|
+
},
|
|
89
|
+
creationInfo: {
|
|
90
|
+
marginTop: tokens.spacing.xs,
|
|
91
|
+
},
|
|
92
|
+
creationTitle: {
|
|
93
|
+
fontSize: 14,
|
|
94
|
+
fontWeight: "700",
|
|
95
|
+
color: tokens.colors.textPrimary,
|
|
96
|
+
marginBottom: 2,
|
|
97
|
+
},
|
|
98
|
+
creationDate: {
|
|
99
|
+
fontSize: 12,
|
|
100
|
+
color: tokens.colors.textSecondary,
|
|
101
|
+
},
|
|
102
|
+
divider: {
|
|
103
|
+
height: 1,
|
|
104
|
+
backgroundColor: tokens.colors.border,
|
|
105
|
+
marginBottom: tokens.spacing.lg,
|
|
106
|
+
marginHorizontal: tokens.spacing.lg,
|
|
107
|
+
},
|
|
108
|
+
columnWrapper: {
|
|
109
|
+
justifyContent: "space-between",
|
|
110
|
+
},
|
|
111
|
+
}),
|
|
112
|
+
[tokens],
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
const handleCreationPress = useCallback((creation: RecentCreation) => {
|
|
116
|
+
onCreationPress?.(creation);
|
|
117
|
+
}, [onCreationPress]);
|
|
118
|
+
|
|
119
|
+
const renderItem = useCallback(({ item }: { item: RecentCreation }) => (
|
|
120
|
+
<TouchableOpacity
|
|
121
|
+
style={styles.creationItem}
|
|
122
|
+
onPress={() => handleCreationPress(item)}
|
|
123
|
+
activeOpacity={0.7}
|
|
124
|
+
>
|
|
125
|
+
<View style={styles.imageContainer}>
|
|
126
|
+
<AtomicImage
|
|
127
|
+
source={{ uri: item.imageUrl }}
|
|
128
|
+
style={styles.image}
|
|
129
|
+
rounded
|
|
130
|
+
/>
|
|
131
|
+
{item.isFavorite && (
|
|
132
|
+
<View style={styles.favoriteIcon}>
|
|
133
|
+
<AtomicIcon name="heart" size="xs" color="error" />
|
|
134
|
+
</View>
|
|
135
|
+
)}
|
|
136
|
+
</View>
|
|
137
|
+
<View style={styles.creationInfo}>
|
|
138
|
+
<AtomicText style={styles.creationTitle} numberOfLines={1}>
|
|
139
|
+
{item.title}
|
|
140
|
+
</AtomicText>
|
|
141
|
+
<AtomicText style={styles.creationDate}>
|
|
142
|
+
{item.date}
|
|
143
|
+
</AtomicText>
|
|
144
|
+
</View>
|
|
145
|
+
</TouchableOpacity>
|
|
146
|
+
), [styles, handleCreationPress]);
|
|
147
|
+
|
|
148
|
+
if (!recentCreations || recentCreations.length === 0) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return (
|
|
153
|
+
<>
|
|
154
|
+
<View style={styles.divider} />
|
|
155
|
+
<View style={styles.container}>
|
|
156
|
+
<View style={styles.header}>
|
|
157
|
+
<AtomicText style={styles.title}>{title}</AtomicText>
|
|
158
|
+
{onViewAll && (
|
|
159
|
+
<TouchableOpacity
|
|
160
|
+
style={styles.viewAllButton}
|
|
161
|
+
onPress={onViewAll}
|
|
162
|
+
activeOpacity={0.7}
|
|
163
|
+
>
|
|
164
|
+
<AtomicText style={styles.viewAllText}>{viewAllLabel}</AtomicText>
|
|
165
|
+
</TouchableOpacity>
|
|
166
|
+
)}
|
|
167
|
+
</View>
|
|
168
|
+
<FlatList
|
|
169
|
+
data={recentCreations}
|
|
170
|
+
renderItem={renderItem}
|
|
171
|
+
keyExtractor={(item) => item.id}
|
|
172
|
+
numColumns={2}
|
|
173
|
+
columnWrapperStyle={styles.columnWrapper}
|
|
174
|
+
scrollEnabled={false}
|
|
175
|
+
showsVerticalScrollIndicator={false}
|
|
176
|
+
/>
|
|
177
|
+
</View>
|
|
178
|
+
</>
|
|
179
|
+
);
|
|
180
|
+
};
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React, { useMemo } from "react";
|
|
7
|
-
import { StyleSheet, View
|
|
7
|
+
import { StyleSheet, View } from "react-native";
|
|
8
8
|
import { AtomicImage, useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
9
9
|
import type { ResultImageCardProps } from "../types/result-preview.types";
|
|
10
10
|
|
|
@@ -20,8 +20,8 @@ export const ResultImageCard: React.FC<ResultImageCardProps> = ({
|
|
|
20
20
|
StyleSheet.create({
|
|
21
21
|
container: {
|
|
22
22
|
width: "100%",
|
|
23
|
-
aspectRatio:
|
|
24
|
-
borderRadius: rounded ? tokens.borders.radius.
|
|
23
|
+
aspectRatio: 3 / 4,
|
|
24
|
+
borderRadius: rounded ? tokens.borders.radius.xl : 0,
|
|
25
25
|
overflow: "hidden",
|
|
26
26
|
backgroundColor: tokens.colors.backgroundSecondary,
|
|
27
27
|
},
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from "@umituz/react-native-design-system";
|
|
14
14
|
import { ResultImageCard } from "./ResultImageCard";
|
|
15
15
|
import { ResultActionBar } from "./ResultActionBar";
|
|
16
|
+
import { RecentCreationsSection } from "./RecentCreationsSection";
|
|
16
17
|
import type { ResultPreviewScreenProps } from "../types/result-preview.types";
|
|
17
18
|
|
|
18
19
|
export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
|
|
@@ -24,6 +25,9 @@ export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
|
|
|
24
25
|
onTryAgain,
|
|
25
26
|
onNavigateBack,
|
|
26
27
|
onRate,
|
|
28
|
+
recentCreations,
|
|
29
|
+
onViewAll,
|
|
30
|
+
onCreationPress,
|
|
27
31
|
translations,
|
|
28
32
|
style,
|
|
29
33
|
}) => {
|
|
@@ -98,6 +102,15 @@ export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
|
|
|
98
102
|
rateButtonText={translations.rateButton}
|
|
99
103
|
/>
|
|
100
104
|
</View>
|
|
105
|
+
{recentCreations && recentCreations.length > 0 && translations.recentCreations && translations.viewAll && (
|
|
106
|
+
<RecentCreationsSection
|
|
107
|
+
recentCreations={recentCreations}
|
|
108
|
+
onViewAll={onViewAll}
|
|
109
|
+
onCreationPress={onCreationPress}
|
|
110
|
+
title={translations.recentCreations}
|
|
111
|
+
viewAllLabel={translations.viewAll}
|
|
112
|
+
/>
|
|
113
|
+
)}
|
|
101
114
|
</View>
|
|
102
115
|
</ScreenLayout>
|
|
103
116
|
);
|
|
@@ -79,6 +79,17 @@ export interface ResultActionBarProps {
|
|
|
79
79
|
rateButtonText?: string;
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Recent creation item
|
|
84
|
+
*/
|
|
85
|
+
export interface RecentCreation {
|
|
86
|
+
readonly id: string;
|
|
87
|
+
readonly imageUrl: string;
|
|
88
|
+
readonly title: string;
|
|
89
|
+
readonly date: string;
|
|
90
|
+
readonly isFavorite?: boolean;
|
|
91
|
+
}
|
|
92
|
+
|
|
82
93
|
/**
|
|
83
94
|
* Result preview screen props
|
|
84
95
|
*/
|
|
@@ -94,6 +105,12 @@ export interface ResultPreviewScreenProps {
|
|
|
94
105
|
onTryAgain: () => void;
|
|
95
106
|
onNavigateBack: () => void;
|
|
96
107
|
onRate?: () => void;
|
|
108
|
+
/** Recent creations to display */
|
|
109
|
+
recentCreations?: readonly RecentCreation[];
|
|
110
|
+
/** Navigate to all creations */
|
|
111
|
+
onViewAll?: () => void;
|
|
112
|
+
/** View a specific creation */
|
|
113
|
+
onCreationPress?: (creation: RecentCreation) => void;
|
|
97
114
|
/** Translations */
|
|
98
115
|
translations: ResultPreviewTranslations;
|
|
99
116
|
/** Optional custom style */
|
|
@@ -118,8 +135,12 @@ export interface ResultPreviewTranslations {
|
|
|
118
135
|
sharing: string;
|
|
119
136
|
/** Try again button */
|
|
120
137
|
tryAnother: string;
|
|
121
|
-
/** Rate button
|
|
138
|
+
/** Rate button */
|
|
122
139
|
rateButton?: string;
|
|
140
|
+
/** Recent creations section title */
|
|
141
|
+
recentCreations?: string;
|
|
142
|
+
/** View all button */
|
|
143
|
+
viewAll?: string;
|
|
123
144
|
}
|
|
124
145
|
|
|
125
146
|
/**
|