@umituz/react-native-ai-generation-content 1.12.8 → 1.12.10

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-generation-content",
3
- "version": "1.12.8",
3
+ "version": "1.12.10",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -16,8 +16,8 @@
16
16
  "src"
17
17
  ],
18
18
  "scripts": {
19
- "typecheck": "echo 'TypeScript validation passed'",
20
- "lint": "echo 'Lint passed'",
19
+ "typecheck": "tsc --noEmit",
20
+ "lint": "eslint src --ext .ts,.tsx --max-warnings 0",
21
21
  "lint:fix": "eslint src --ext .ts,.tsx --fix"
22
22
  },
23
23
  "keywords": [
@@ -41,7 +41,6 @@
41
41
  "@react-navigation/native": ">=6.0.0",
42
42
  "@tanstack/react-query": ">=5.0.0",
43
43
  "@umituz/react-native-animation": "latest",
44
- "@umituz/react-native-bottom-sheet": "latest",
45
44
  "@umituz/react-native-design-system": "latest",
46
45
  "@umituz/react-native-firebase": "latest",
47
46
  "@umituz/react-native-image": "latest",
@@ -62,7 +61,6 @@
62
61
  "@typescript-eslint/eslint-plugin": "^7.0.0",
63
62
  "@typescript-eslint/parser": "^7.0.0",
64
63
  "@umituz/react-native-animation": "latest",
65
- "@umituz/react-native-bottom-sheet": "latest",
66
64
  "@umituz/react-native-design-system": "latest",
67
65
  "@umituz/react-native-firebase": "latest",
68
66
  "@umituz/react-native-image": "latest",
@@ -73,7 +71,7 @@
73
71
  "firebase": "^11.1.0",
74
72
  "react": "19.1.0",
75
73
  "react-native": "0.81.5",
76
- "react-native-safe-area-context": "^4.0.0",
74
+ "react-native-safe-area-context": "^5.6.2",
77
75
  "typescript": "^5.3.0",
78
76
  "zustand": "^5.0.2"
79
77
  },
@@ -41,7 +41,7 @@ export type PathBuilder = (userId: string) => string[];
41
41
  */
42
42
  export type DocumentMapper = (id: string, data: CreationDocument) => Creation;
43
43
 
44
- import type { FilterCategory } from "@umituz/react-native-bottom-sheet";
44
+ import type { FilterCategory } from "@umituz/react-native-design-system";
45
45
 
46
46
  export interface CreationsConfig {
47
47
  readonly collectionName: string;
@@ -0,0 +1,77 @@
1
+ import React, { useMemo } from "react";
2
+ import { View, StyleSheet, ActivityIndicator } from "react-native";
3
+ import { useAppDesignTokens } from "@umituz/react-native-design-system";
4
+ import { EmptyState } from "./EmptyState";
5
+ import type { CreationsConfig } from "../../domain/value-objects/CreationsConfig";
6
+
7
+ interface CreationsGalleryEmptyStateProps {
8
+ readonly isLoading: boolean;
9
+ readonly hasCreations: boolean;
10
+ readonly config: CreationsConfig;
11
+ readonly t: (key: string) => string;
12
+ readonly emptyActionLabel?: string;
13
+ readonly onEmptyAction?: () => void;
14
+ readonly clearFilters: () => void;
15
+ }
16
+
17
+ export const CreationsGalleryEmptyState: React.FC<CreationsGalleryEmptyStateProps> = ({
18
+ isLoading,
19
+ hasCreations,
20
+ config,
21
+ t,
22
+ emptyActionLabel,
23
+ onEmptyAction,
24
+ clearFilters,
25
+ }) => {
26
+ const tokens = useAppDesignTokens();
27
+ const styles = useStyles(tokens);
28
+
29
+ return useMemo(() => {
30
+ // 1. Loading State
31
+ if (isLoading && !hasCreations) {
32
+ return (
33
+ <View style={styles.centerContainer}>
34
+ <ActivityIndicator size="large" color={tokens.colors.primary} />
35
+ </View>
36
+ );
37
+ }
38
+
39
+ // 2. System Empty State (User has NO creations at all)
40
+ // We check 'hasCreations' which represents the full list presence
41
+ if (!hasCreations) {
42
+ return (
43
+ <View style={styles.centerContainer}>
44
+ <EmptyState
45
+ title={t(config.translations.empty)}
46
+ description={t(config.translations.emptyDescription)}
47
+ actionLabel={emptyActionLabel}
48
+ onAction={onEmptyAction}
49
+ />
50
+ </View>
51
+ );
52
+ }
53
+
54
+ // 3. Filter Empty State (User has creations, but filter returns none)
55
+ // This component is rendered when the list is empty, but hasCreations is true.
56
+ return (
57
+ <View style={styles.centerContainer}>
58
+ <EmptyState
59
+ title={t("common.no_results") || "No results"}
60
+ description={t("common.no_results_description") || "Try changing your filters"}
61
+ actionLabel={t("common.clear_all") || "Clear All"}
62
+ onAction={clearFilters}
63
+ />
64
+ </View>
65
+ );
66
+ }, [isLoading, hasCreations, config, t, emptyActionLabel, onEmptyAction, clearFilters, styles.centerContainer, tokens.colors.primary]);
67
+ };
68
+
69
+ const useStyles = (tokens: any) => StyleSheet.create({
70
+ centerContainer: {
71
+ flex: 1,
72
+ justifyContent: 'center',
73
+ alignItems: 'center',
74
+ minHeight: 400,
75
+ paddingHorizontal: tokens.spacing.xl
76
+ },
77
+ });
@@ -1,7 +1,6 @@
1
1
  import React, { forwardRef, useCallback, useMemo } from 'react';
2
2
  import { View, StyleSheet, TouchableOpacity, ScrollView } from 'react-native';
3
- import { BottomSheetModal, BottomSheetModalRef } from '@umituz/react-native-bottom-sheet';
4
- import { useAppDesignTokens, AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
3
+ import { BottomSheetModal, type BottomSheetModalRef, useAppDesignTokens, AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
5
4
 
6
5
  export interface FilterOption {
7
6
  id: string;
@@ -10,6 +10,7 @@ export { CreationCard } from "./CreationCard";
10
10
  export { CreationThumbnail } from "./CreationThumbnail";
11
11
  export { CreationImageViewer } from "./CreationImageViewer";
12
12
  export { CreationsGrid } from "./CreationsGrid";
13
+ export { CreationsGalleryEmptyState } from "./CreationsGalleryEmptyState";
13
14
  export { FilterBottomSheet, type FilterCategory, type FilterOption } from "./FilterBottomSheet";
14
15
 
15
16
  // Detail Components
@@ -7,9 +7,8 @@ import { useFocusEffect } from "@react-navigation/native";
7
7
  import { useCreations } from "../hooks/useCreations";
8
8
  import { useDeleteCreation } from "../hooks/useDeleteCreation";
9
9
  import { useCreationsFilter } from "../hooks/useCreationsFilter";
10
- import { useAlert, AlertMode } from "@umituz/react-native-design-system";
11
- import { BottomSheetModalRef } from "@umituz/react-native-bottom-sheet";
12
- import { GalleryHeader, EmptyState, CreationsGrid, FilterBottomSheet, CreationImageViewer, type FilterCategory } from "../components";
10
+ import { useAlert, AlertMode, type BottomSheetModalRef, type FilterCategory } from "@umituz/react-native-design-system";
11
+ import { GalleryHeader, CreationsGrid, FilterBottomSheet, CreationImageViewer, CreationsGalleryEmptyState } from "../components";
13
12
  import { getTranslatedTypes, getFilterCategoriesFromConfig } from "../utils/filterUtils";
14
13
  import type { Creation } from "../../domain/entities/Creation";
15
14
  import type { CreationsConfig } from "../../domain/value-objects/CreationsConfig";
@@ -91,59 +90,8 @@ export function CreationsGalleryScreen({
91
90
  setSelectedCreation(creation);
92
91
  }, []);
93
92
 
94
- const styles = useStyles(tokens);
95
-
96
- // Define empty state content based on state
97
- const renderEmptyComponent = useMemo(() => {
98
- // 1. Loading State
99
- if (isLoading && (!creations || creations?.length === 0)) {
100
- return (
101
- <View style={styles.centerContainer}>
102
- <ActivityIndicator size="large" color={tokens.colors.primary} />
103
- </View>
104
- );
105
- }
106
-
107
- // 2. System Empty State (User has NO creations at all)
108
- // We check 'creations' (the full list)
109
- if (!creations || creations?.length === 0) {
110
- return (
111
- <View style={styles.centerContainer}>
112
- <EmptyState
113
- title={t(config.translations.empty)}
114
- description={t(config.translations.emptyDescription)}
115
- actionLabel={emptyActionLabel}
116
- onAction={onEmptyAction}
117
- />
118
- </View>
119
- );
120
- }
121
-
122
- // 3. Filter Empty State (User has creations, but filter returns none)
123
- // We check 'filtered' (the displayed list)
124
- return (
125
- <View style={styles.centerContainer}>
126
- <EmptyState
127
- title={t("common.no_results") || "No results"}
128
- description={t("common.no_results_description") || "Try changing your filters"}
129
- actionLabel={t("common.clear_all") || "Clear All"}
130
- onAction={clearFilters}
131
- />
132
- </View>
133
- );
134
- }, [isLoading, creations, config, t, emptyActionLabel, onEmptyAction, clearFilters, styles.centerContainer, tokens.colors.primary]);
135
93
 
136
- if (selectedCreation) {
137
- return (
138
- <CreationDetailScreen
139
- creation={selectedCreation}
140
- onClose={() => setSelectedCreation(null)}
141
- onShare={handleShare}
142
- onDelete={handleDelete}
143
- t={t}
144
- />
145
- );
146
- }
94
+ const styles = useStyles(tokens);
147
95
 
148
96
  return (
149
97
  <View style={styles.container}>
@@ -181,7 +129,17 @@ export function CreationsGalleryScreen({
181
129
  onShare={handleShare}
182
130
  onDelete={handleDelete}
183
131
  contentContainerStyle={{ paddingBottom: insets.bottom + tokens.spacing.xl }}
184
- ListEmptyComponent={renderEmptyComponent}
132
+ ListEmptyComponent={
133
+ <CreationsGalleryEmptyState
134
+ isLoading={isLoading}
135
+ hasCreations={!!creations && creations.length > 0}
136
+ config={config}
137
+ t={t}
138
+ emptyActionLabel={emptyActionLabel}
139
+ onEmptyAction={onEmptyAction}
140
+ clearFilters={clearFilters}
141
+ />
142
+ }
185
143
  />
186
144
 
187
145
  <CreationImageViewer
@@ -209,11 +167,4 @@ export function CreationsGalleryScreen({
209
167
 
210
168
  const useStyles = (tokens: any) => StyleSheet.create({
211
169
  container: { flex: 1, backgroundColor: tokens.colors.background },
212
- centerContainer: {
213
- flex: 1,
214
- justifyContent: 'center',
215
- alignItems: 'center',
216
- minHeight: 400,
217
- paddingHorizontal: tokens.spacing.xl
218
- },
219
170
  });
@@ -43,7 +43,7 @@ export const GenerateButton: React.FC<GenerateButtonProps> = memo(
43
43
  <>
44
44
  <AtomicIcon
45
45
  name="sparkles"
46
- size={20}
46
+ size="md"
47
47
  color={disabled ? "surfaceVariant" : "onPrimary"}
48
48
  style={styles.icon}
49
49
  />
@@ -44,7 +44,7 @@ export const ImagePicker: React.FC<ImagePickerProps> = memo(
44
44
  >
45
45
  <AtomicIcon
46
46
  name="image-plus"
47
- size={20}
47
+ size="md"
48
48
  color="onPrimary"
49
49
  />
50
50
  </View>
@@ -65,7 +65,7 @@ export const ImagePicker: React.FC<ImagePickerProps> = memo(
65
65
  >
66
66
  <AtomicIcon
67
67
  name="upload"
68
- size={40}
68
+ size="lg"
69
69
  color="primary"
70
70
  />
71
71
  </View>
@@ -45,7 +45,7 @@ export const ModeSelector: React.FC<ModeSelectorProps> = memo(
45
45
  >
46
46
  <AtomicIcon
47
47
  name={mode.icon}
48
- size={20}
48
+ size="md"
49
49
  color={isActive ? "onPrimary" : "onSurface"}
50
50
  />
51
51
  </TouchableOpacity>
@@ -47,7 +47,7 @@ export const ResultDisplay: React.FC<ResultDisplayProps> = memo(
47
47
  >
48
48
  <AtomicIcon
49
49
  name="refresh-cw"
50
- size={20}
50
+ size="md"
51
51
  color="onSurface"
52
52
  />
53
53
  <AtomicText
@@ -67,7 +67,7 @@ export const ResultDisplay: React.FC<ResultDisplayProps> = memo(
67
67
  >
68
68
  <AtomicIcon
69
69
  name="download"
70
- size={20}
70
+ size="md"
71
71
  color="onPrimary"
72
72
  />
73
73
  <AtomicText
@@ -40,7 +40,7 @@ export const ResultActions: React.FC<ResultActionsProps> = ({
40
40
  <View style={styles.container}>
41
41
  {onRetry && (
42
42
  <TouchableOpacity style={styles.retryButton} onPress={onRetry}>
43
- <AtomicIcon name="refresh" size={18} customColor={tokens.colors.primary} />
43
+ <AtomicIcon name="refresh" size="sm" customColor={tokens.colors.primary} />
44
44
  <AtomicText style={styles.retryText}>{translations.retry}</AtomicText>
45
45
  </TouchableOpacity>
46
46
  )}
@@ -54,7 +54,7 @@ export const ResultActions: React.FC<ResultActionsProps> = ({
54
54
  >
55
55
  <AtomicIcon
56
56
  name={isSharing ? "hourglass" : "share-social"}
57
- size={22}
57
+ size="md"
58
58
  customColor="#fff"
59
59
  />
60
60
  <AtomicText style={styles.shareText}>
@@ -71,7 +71,7 @@ export const ResultActions: React.FC<ResultActionsProps> = ({
71
71
  >
72
72
  <AtomicIcon
73
73
  name={isSaving ? "hourglass" : "download"}
74
- size={22}
74
+ size="md"
75
75
  customColor={tokens.colors.primary}
76
76
  />
77
77
  <AtomicText style={styles.saveText}>{translations.save}</AtomicText>
@@ -29,7 +29,7 @@ export const ResultHeader: React.FC<ResultHeaderProps> = ({ title, date }) => {
29
29
  <View style={styles.badge}>
30
30
  <AtomicIcon
31
31
  name="calendar-outline"
32
- size={14}
32
+ size="sm"
33
33
  customColor={tokens.colors.primary}
34
34
  />
35
35
  <AtomicText style={styles.dateText}>{date}</AtomicText>
@@ -28,7 +28,7 @@ export const ResultImageCard: React.FC<ResultImageCardProps> = ({
28
28
  <View style={styles.frame}>
29
29
  <Image source={{ uri: imageUrl }} style={styles.image} resizeMode="cover" />
30
30
  <View style={styles.badge}>
31
- <AtomicIcon name="sparkles" size={12} customColor="#fff" />
31
+ <AtomicIcon name="sparkles" size="xs" customColor="#fff" />
32
32
  <AtomicText style={styles.badgeText}>{badgeText}</AtomicText>
33
33
  </View>
34
34
  </View>