@umituz/react-native-ai-creations 1.2.8 → 1.2.9
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-creations",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.9",
|
|
4
4
|
"description": "AI-generated creations gallery with filtering, sharing, and management for React Native apps",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -27,32 +27,31 @@
|
|
|
27
27
|
"type": "git",
|
|
28
28
|
"url": "https://github.com/umituz/react-native-ai-creations"
|
|
29
29
|
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@umituz/react-native-filter": "latest",
|
|
32
|
+
"@umituz/react-native-image": "latest",
|
|
33
|
+
"@umituz/react-native-bottom-sheet": "latest"
|
|
34
|
+
},
|
|
30
35
|
"peerDependencies": {
|
|
31
36
|
"@tanstack/react-query": ">=5.0.0",
|
|
32
37
|
"@umituz/react-native-design-system": "latest",
|
|
33
38
|
"@umituz/react-native-firestore": "latest",
|
|
34
|
-
"@umituz/react-native-image": "latest",
|
|
35
39
|
"@umituz/react-native-sharing": "latest",
|
|
36
40
|
"firebase": ">=11.0.0",
|
|
37
41
|
"react": ">=19.1.0",
|
|
38
42
|
"react-native": ">=0.81.5",
|
|
39
|
-
"react-native-safe-area-context": ">=5.0.0"
|
|
40
|
-
"@umituz/react-native-filter": "latest",
|
|
41
|
-
"@umituz/react-native-bottom-sheet": "latest"
|
|
43
|
+
"react-native-safe-area-context": ">=5.0.0"
|
|
42
44
|
},
|
|
43
45
|
"devDependencies": {
|
|
44
46
|
"@tanstack/react-query": "^5.62.16",
|
|
45
47
|
"@types/react": "^19.0.0",
|
|
46
48
|
"@umituz/react-native-design-system": "latest",
|
|
47
|
-
"@umituz/react-native-image": "latest",
|
|
48
49
|
"@umituz/react-native-sharing": "latest",
|
|
49
50
|
"@umituz/react-native-firestore": "latest",
|
|
50
51
|
"firebase": "^11.0.0",
|
|
51
52
|
"react": "19.1.0",
|
|
52
53
|
"react-native": "0.81.5",
|
|
53
54
|
"react-native-safe-area-context": "^5.6.0",
|
|
54
|
-
"@umituz/react-native-filter": "latest",
|
|
55
|
-
"@umituz/react-native-bottom-sheet": "latest",
|
|
56
55
|
"typescript": "^5.3.3"
|
|
57
56
|
},
|
|
58
57
|
"publishConfig": {
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, TouchableOpacity, StyleSheet } from 'react-native';
|
|
3
|
+
import { AtomicText, AtomicIcon, useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
4
|
+
|
|
5
|
+
interface GalleryHeaderProps {
|
|
6
|
+
readonly title: string;
|
|
7
|
+
readonly count: number;
|
|
8
|
+
readonly countLabel: string;
|
|
9
|
+
readonly isFiltered: boolean;
|
|
10
|
+
readonly onFilterPress: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const GalleryHeader: React.FC<GalleryHeaderProps> = ({
|
|
14
|
+
title,
|
|
15
|
+
count,
|
|
16
|
+
countLabel,
|
|
17
|
+
isFiltered,
|
|
18
|
+
onFilterPress
|
|
19
|
+
}) => {
|
|
20
|
+
const tokens = useAppDesignTokens();
|
|
21
|
+
const styles = useStyles(tokens);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<View style={styles.headerArea}>
|
|
25
|
+
<View>
|
|
26
|
+
<AtomicText style={styles.title}>{title}</AtomicText>
|
|
27
|
+
<AtomicText style={styles.subtitle}>
|
|
28
|
+
{count} {countLabel}
|
|
29
|
+
</AtomicText>
|
|
30
|
+
</View>
|
|
31
|
+
<TouchableOpacity
|
|
32
|
+
onPress={onFilterPress}
|
|
33
|
+
style={[styles.filterButton, isFiltered && styles.filterButtonActive]}
|
|
34
|
+
>
|
|
35
|
+
<AtomicIcon
|
|
36
|
+
name="ListFilter"
|
|
37
|
+
size="sm"
|
|
38
|
+
color={isFiltered ? "primary" : "secondary"}
|
|
39
|
+
/>
|
|
40
|
+
<AtomicText style={[styles.filterText, { color: isFiltered ? tokens.colors.primary : tokens.colors.textSecondary }]}>
|
|
41
|
+
Filter
|
|
42
|
+
</AtomicText>
|
|
43
|
+
{isFiltered && (
|
|
44
|
+
<View style={styles.badge} />
|
|
45
|
+
)}
|
|
46
|
+
</TouchableOpacity>
|
|
47
|
+
</View>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const useStyles = (tokens: any) => StyleSheet.create({
|
|
52
|
+
headerArea: {
|
|
53
|
+
flexDirection: "row",
|
|
54
|
+
alignItems: "center",
|
|
55
|
+
justifyContent: 'space-between',
|
|
56
|
+
paddingHorizontal: tokens.spacing.md,
|
|
57
|
+
paddingVertical: tokens.spacing.sm,
|
|
58
|
+
marginBottom: tokens.spacing.sm,
|
|
59
|
+
},
|
|
60
|
+
title: {
|
|
61
|
+
fontSize: 20,
|
|
62
|
+
fontWeight: "700",
|
|
63
|
+
color: tokens.colors.textPrimary,
|
|
64
|
+
marginBottom: 4,
|
|
65
|
+
},
|
|
66
|
+
subtitle: {
|
|
67
|
+
fontSize: 14,
|
|
68
|
+
color: tokens.colors.textSecondary,
|
|
69
|
+
opacity: 0.6
|
|
70
|
+
},
|
|
71
|
+
filterButton: {
|
|
72
|
+
flexDirection: 'row',
|
|
73
|
+
alignItems: 'center',
|
|
74
|
+
gap: tokens.spacing.xs,
|
|
75
|
+
paddingVertical: tokens.spacing.xs,
|
|
76
|
+
paddingHorizontal: tokens.spacing.md,
|
|
77
|
+
borderRadius: 999,
|
|
78
|
+
backgroundColor: tokens.colors.surfaceVariant,
|
|
79
|
+
borderWidth: 1,
|
|
80
|
+
borderColor: 'transparent',
|
|
81
|
+
},
|
|
82
|
+
filterButtonActive: {
|
|
83
|
+
backgroundColor: tokens.colors.primary + "15",
|
|
84
|
+
borderColor: tokens.colors.primary + "30",
|
|
85
|
+
},
|
|
86
|
+
filterText: {
|
|
87
|
+
fontSize: 14,
|
|
88
|
+
fontWeight: "500",
|
|
89
|
+
},
|
|
90
|
+
badge: {
|
|
91
|
+
width: 8,
|
|
92
|
+
height: 8,
|
|
93
|
+
borderRadius: 4,
|
|
94
|
+
backgroundColor: tokens.colors.primary,
|
|
95
|
+
position: 'absolute',
|
|
96
|
+
top: 6,
|
|
97
|
+
right: 6,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
@@ -8,10 +8,6 @@ import type { Creation } from "../../domain/entities/Creation";
|
|
|
8
8
|
|
|
9
9
|
const ALL_FILTER = "all";
|
|
10
10
|
|
|
11
|
-
interface UseCreationsFilterProps {
|
|
12
|
-
readonly creations: Creation[] | undefined;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
11
|
import { FilterUtils } from "@umituz/react-native-filter";
|
|
16
12
|
|
|
17
13
|
interface UseCreationsFilterProps {
|
|
@@ -20,6 +20,7 @@ import { EmptyState } from "../components/EmptyState";
|
|
|
20
20
|
import { FilterBottomSheet, type FilterCategory } from "@umituz/react-native-filter";
|
|
21
21
|
import { BottomSheetModalRef } from "@umituz/react-native-bottom-sheet";
|
|
22
22
|
import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system";
|
|
23
|
+
import { GalleryHeader } from "../components/GalleryHeader";
|
|
23
24
|
|
|
24
25
|
interface CreationsGalleryScreenProps {
|
|
25
26
|
readonly userId: string | null;
|
|
@@ -60,13 +61,13 @@ export function CreationsGalleryScreen({
|
|
|
60
61
|
// Add dynamic types category if types exist
|
|
61
62
|
if (config.types.length > 0) {
|
|
62
63
|
categories.push({
|
|
63
|
-
id: 'type',
|
|
64
|
+
id: 'type',
|
|
64
65
|
title: t('creations.category') || 'Category',
|
|
65
66
|
multiSelect: false,
|
|
66
67
|
options: config.types.map(t => ({
|
|
67
68
|
id: t.id,
|
|
68
|
-
label: t.labelKey,
|
|
69
|
-
icon: 'Image',
|
|
69
|
+
label: t.labelKey,
|
|
70
|
+
icon: 'Image',
|
|
70
71
|
}))
|
|
71
72
|
});
|
|
72
73
|
}
|
|
@@ -138,38 +139,6 @@ export function CreationsGalleryScreen({
|
|
|
138
139
|
flex: 1,
|
|
139
140
|
backgroundColor: tokens.colors.backgroundPrimary,
|
|
140
141
|
},
|
|
141
|
-
headerArea: {
|
|
142
|
-
flexDirection: "row",
|
|
143
|
-
alignItems: "center",
|
|
144
|
-
justifyContent: 'space-between',
|
|
145
|
-
paddingHorizontal: tokens.spacing.md,
|
|
146
|
-
paddingVertical: tokens.spacing.sm,
|
|
147
|
-
marginBottom: tokens.spacing.sm,
|
|
148
|
-
},
|
|
149
|
-
filterButton: {
|
|
150
|
-
flexDirection: 'row',
|
|
151
|
-
alignItems: 'center',
|
|
152
|
-
gap: tokens.spacing.xs,
|
|
153
|
-
paddingVertical: tokens.spacing.xs,
|
|
154
|
-
paddingHorizontal: tokens.spacing.md,
|
|
155
|
-
borderRadius: (tokens as any).borders?.radius?.full || 999,
|
|
156
|
-
backgroundColor: tokens.colors.surfaceVariant,
|
|
157
|
-
borderWidth: 1,
|
|
158
|
-
borderColor: 'transparent',
|
|
159
|
-
},
|
|
160
|
-
filterButtonActive: {
|
|
161
|
-
backgroundColor: tokens.colors.primary + "15",
|
|
162
|
-
borderColor: tokens.colors.primary + "30",
|
|
163
|
-
},
|
|
164
|
-
badge: {
|
|
165
|
-
width: 8,
|
|
166
|
-
height: 8,
|
|
167
|
-
borderRadius: 4,
|
|
168
|
-
backgroundColor: tokens.colors.primary,
|
|
169
|
-
position: 'absolute',
|
|
170
|
-
top: 6,
|
|
171
|
-
right: 6,
|
|
172
|
-
},
|
|
173
142
|
list: {
|
|
174
143
|
paddingHorizontal: tokens.spacing.md,
|
|
175
144
|
paddingBottom: insets.bottom + tokens.spacing.xl,
|
|
@@ -210,22 +179,14 @@ export function CreationsGalleryScreen({
|
|
|
210
179
|
|
|
211
180
|
return (
|
|
212
181
|
<View style={styles.container}>
|
|
213
|
-
<
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
>
|
|
222
|
-
<AtomicIcon name="ListFilter" size="sm" color={isFiltered ? "primary" : "secondary"} />
|
|
223
|
-
<AtomicText type="labelMedium" color={isFiltered ? "primary" : "secondary"}>Filter</AtomicText>
|
|
224
|
-
{isFiltered && (
|
|
225
|
-
<View style={styles.badge} />
|
|
226
|
-
)}
|
|
227
|
-
</TouchableOpacity>
|
|
228
|
-
</View>
|
|
182
|
+
<GalleryHeader
|
|
183
|
+
title={t(config.translations.title) || 'My Creations'}
|
|
184
|
+
count={filtered.length}
|
|
185
|
+
countLabel={t(config.translations.photoCount) || 'photos'}
|
|
186
|
+
isFiltered={isFiltered}
|
|
187
|
+
onFilterPress={() => filterSheetRef.current?.present()}
|
|
188
|
+
/>
|
|
189
|
+
|
|
229
190
|
<FlatList
|
|
230
191
|
data={filtered}
|
|
231
192
|
renderItem={renderItem}
|