@umituz/react-native-ai-generation-content 1.16.0 → 1.17.1

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 (116) hide show
  1. package/package.json +13 -14
  2. package/src/domains/creations/domain/entities/Creation.ts +33 -2
  3. package/src/domains/creations/domain/entities/index.ts +1 -1
  4. package/src/domains/creations/domain/types/creation-categories.ts +133 -0
  5. package/src/domains/creations/domain/types/creation-filter.ts +131 -0
  6. package/src/domains/creations/domain/types/creation-types.ts +63 -0
  7. package/src/domains/creations/domain/types/index.ts +44 -0
  8. package/src/domains/creations/domain/utils/creation-helpers.ts +134 -0
  9. package/src/domains/creations/domain/utils/index.ts +8 -0
  10. package/src/domains/creations/domain/utils/preview-helpers.ts +84 -0
  11. package/src/domains/creations/domain/utils/status-helpers.ts +90 -0
  12. package/src/domains/creations/index.ts +95 -21
  13. package/src/domains/creations/infrastructure/repositories/CreationsRepository.ts +14 -1
  14. package/src/domains/creations/presentation/components/CreationActions.tsx +120 -0
  15. package/src/domains/creations/presentation/components/CreationBadges.tsx +111 -0
  16. package/src/domains/creations/presentation/components/CreationCard.tsx +201 -102
  17. package/src/domains/creations/presentation/components/CreationPreview.tsx +117 -0
  18. package/src/domains/creations/presentation/components/CreationsFilterBar.tsx +254 -0
  19. package/src/domains/creations/presentation/components/CreationsGrid.tsx +121 -68
  20. package/src/domains/creations/presentation/components/index.ts +23 -3
  21. package/src/domains/creations/presentation/hooks/index.ts +1 -0
  22. package/src/domains/creations/presentation/hooks/useAdvancedFilter.ts +262 -0
  23. package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +5 -6
  24. package/src/features/ai-hug/domain/index.ts +5 -0
  25. package/src/features/ai-hug/domain/types/ai-hug.types.ts +72 -0
  26. package/src/features/ai-hug/domain/types/index.ts +14 -0
  27. package/src/features/ai-hug/index.ts +27 -0
  28. package/src/features/ai-hug/infrastructure/index.ts +5 -0
  29. package/src/features/ai-hug/infrastructure/services/ai-hug-executor.ts +96 -0
  30. package/src/features/ai-hug/infrastructure/services/index.ts +6 -0
  31. package/src/features/ai-hug/presentation/hooks/index.ts +9 -0
  32. package/src/features/ai-hug/presentation/hooks/useAIHugFeature.ts +157 -0
  33. package/src/features/ai-hug/presentation/index.ts +5 -0
  34. package/src/features/ai-kiss/domain/index.ts +5 -0
  35. package/src/features/ai-kiss/domain/types/ai-kiss.types.ts +72 -0
  36. package/src/features/ai-kiss/domain/types/index.ts +14 -0
  37. package/src/features/ai-kiss/index.ts +27 -0
  38. package/src/features/ai-kiss/infrastructure/index.ts +5 -0
  39. package/src/features/ai-kiss/infrastructure/services/ai-kiss-executor.ts +96 -0
  40. package/src/features/ai-kiss/infrastructure/services/index.ts +6 -0
  41. package/src/features/ai-kiss/presentation/hooks/index.ts +9 -0
  42. package/src/features/ai-kiss/presentation/hooks/useAIKissFeature.ts +157 -0
  43. package/src/features/ai-kiss/presentation/index.ts +5 -0
  44. package/src/features/anime-selfie/domain/index.ts +5 -0
  45. package/src/features/anime-selfie/domain/types/anime-selfie.types.ts +72 -0
  46. package/src/features/anime-selfie/domain/types/index.ts +15 -0
  47. package/src/features/anime-selfie/index.ts +28 -0
  48. package/src/features/anime-selfie/infrastructure/index.ts +5 -0
  49. package/src/features/anime-selfie/infrastructure/services/anime-selfie-executor.ts +95 -0
  50. package/src/features/anime-selfie/infrastructure/services/index.ts +6 -0
  51. package/src/features/anime-selfie/presentation/hooks/index.ts +9 -0
  52. package/src/features/anime-selfie/presentation/hooks/useAnimeSelfieFeature.ts +138 -0
  53. package/src/features/anime-selfie/presentation/index.ts +5 -0
  54. package/src/features/background/domain/types/index.ts +15 -0
  55. package/src/features/background/domain/types/replace-background.types.ts +82 -0
  56. package/src/features/background/index.ts +31 -3
  57. package/src/features/background/infrastructure/index.ts +5 -0
  58. package/src/features/background/infrastructure/services/index.ts +6 -0
  59. package/src/features/background/infrastructure/services/replace-background-executor.ts +95 -0
  60. package/src/features/background/presentation/hooks/index.ts +6 -1
  61. package/src/features/background/presentation/hooks/useReplaceBackgroundFeature.ts +160 -0
  62. package/src/features/face-swap/domain/index.ts +5 -0
  63. package/src/features/face-swap/domain/types/face-swap.types.ts +72 -0
  64. package/src/features/face-swap/domain/types/index.ts +14 -0
  65. package/src/features/face-swap/index.ts +27 -1
  66. package/src/features/face-swap/infrastructure/index.ts +5 -0
  67. package/src/features/face-swap/infrastructure/services/face-swap-executor.ts +96 -0
  68. package/src/features/face-swap/infrastructure/services/index.ts +6 -0
  69. package/src/features/face-swap/presentation/hooks/index.ts +9 -0
  70. package/src/features/face-swap/presentation/hooks/useFaceSwapFeature.ts +157 -0
  71. package/src/features/face-swap/presentation/index.ts +5 -0
  72. package/src/features/photo-restoration/domain/index.ts +1 -0
  73. package/src/features/photo-restoration/domain/types/index.ts +10 -0
  74. package/src/features/photo-restoration/domain/types/photo-restore.types.ts +71 -0
  75. package/src/features/photo-restoration/index.ts +34 -1
  76. package/src/features/photo-restoration/infrastructure/index.ts +1 -0
  77. package/src/features/photo-restoration/infrastructure/services/index.ts +2 -0
  78. package/src/features/photo-restoration/infrastructure/services/photo-restore-executor.ts +98 -0
  79. package/src/features/photo-restoration/presentation/components/PhotoRestoreFeature.tsx +175 -0
  80. package/src/features/photo-restoration/presentation/components/PhotoRestoreResultView.tsx +98 -0
  81. package/src/features/photo-restoration/presentation/components/index.ts +4 -0
  82. package/src/features/photo-restoration/presentation/hooks/index.ts +5 -0
  83. package/src/features/photo-restoration/presentation/hooks/usePhotoRestoreFeature.ts +137 -0
  84. package/src/features/photo-restoration/presentation/index.ts +2 -0
  85. package/src/features/remove-background/domain/index.ts +5 -0
  86. package/src/features/remove-background/domain/types/index.ts +14 -0
  87. package/src/features/remove-background/domain/types/remove-background.types.ts +69 -0
  88. package/src/features/remove-background/index.ts +27 -0
  89. package/src/features/remove-background/infrastructure/index.ts +5 -0
  90. package/src/features/remove-background/infrastructure/services/index.ts +6 -0
  91. package/src/features/remove-background/infrastructure/services/remove-background-executor.ts +95 -0
  92. package/src/features/remove-background/presentation/hooks/index.ts +9 -0
  93. package/src/features/remove-background/presentation/hooks/useRemoveBackgroundFeature.ts +137 -0
  94. package/src/features/remove-background/presentation/index.ts +5 -0
  95. package/src/features/remove-object/domain/index.ts +5 -0
  96. package/src/features/remove-object/domain/types/index.ts +14 -0
  97. package/src/features/remove-object/domain/types/remove-object.types.ts +77 -0
  98. package/src/features/remove-object/index.ts +27 -0
  99. package/src/features/remove-object/infrastructure/index.ts +5 -0
  100. package/src/features/remove-object/infrastructure/services/index.ts +6 -0
  101. package/src/features/remove-object/infrastructure/services/remove-object-executor.ts +99 -0
  102. package/src/features/remove-object/presentation/hooks/index.ts +9 -0
  103. package/src/features/remove-object/presentation/hooks/useRemoveObjectFeature.ts +168 -0
  104. package/src/features/remove-object/presentation/index.ts +5 -0
  105. package/src/features/upscaling/domain/types/index.ts +0 -1
  106. package/src/features/upscaling/domain/types/upscale.types.ts +14 -0
  107. package/src/features/upscaling/index.ts +3 -11
  108. package/src/features/upscaling/infrastructure/services/index.ts +1 -6
  109. package/src/features/upscaling/infrastructure/services/upscale-executor.ts +64 -30
  110. package/src/features/upscaling/presentation/hooks/useUpscaleFeature.ts +12 -7
  111. package/src/index.ts +45 -0
  112. package/src/types/jsx.d.ts +19 -0
  113. package/src/features/face-swap/domain/entities.ts +0 -48
  114. package/src/features/photo-restoration/domain/entities.ts +0 -48
  115. package/src/features/upscaling/domain/types/provider.types.ts +0 -23
  116. package/src/features/upscaling/infrastructure/services/upscale-provider-registry.ts +0 -77
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Preview Helpers
3
+ * Utility functions for creation preview/thumbnail extraction
4
+ */
5
+
6
+ import type { CreationOutput } from "../entities/Creation";
7
+
8
+ // Re-export for convenience
9
+ export type { CreationOutput } from "../entities/Creation";
10
+
11
+ /**
12
+ * Get preview URL from creation output
13
+ * Priority: thumbnailUrl > imageUrl > first imageUrls item > videoUrl > null
14
+ */
15
+ export function getPreviewUrl(output?: CreationOutput): string | null {
16
+ if (!output) return null;
17
+
18
+ return (
19
+ output.thumbnailUrl ||
20
+ output.imageUrl ||
21
+ output.imageUrls?.[0] ||
22
+ output.videoUrl ||
23
+ null
24
+ );
25
+ }
26
+
27
+ /**
28
+ * Get all available media URLs from creation output
29
+ */
30
+ export function getAllMediaUrls(output?: CreationOutput): string[] {
31
+ if (!output) return [];
32
+
33
+ const urls: string[] = [];
34
+
35
+ if (output.imageUrl) urls.push(output.imageUrl);
36
+ if (output.imageUrls) urls.push(...output.imageUrls);
37
+ if (output.videoUrl) urls.push(output.videoUrl);
38
+ if (output.audioUrl) urls.push(output.audioUrl);
39
+
40
+ return urls;
41
+ }
42
+
43
+ /**
44
+ * Check if creation has downloadable content
45
+ */
46
+ export function hasDownloadableContent(output?: CreationOutput): boolean {
47
+ if (!output) return false;
48
+
49
+ return !!(
50
+ output.imageUrl ||
51
+ (output.imageUrls && output.imageUrls.length > 0) ||
52
+ output.videoUrl ||
53
+ output.audioUrl
54
+ );
55
+ }
56
+
57
+ /**
58
+ * Check if creation has video content
59
+ */
60
+ export function hasVideoContent(output?: CreationOutput): boolean {
61
+ return !!output?.videoUrl;
62
+ }
63
+
64
+ /**
65
+ * Check if creation has audio content
66
+ */
67
+ export function hasAudioContent(output?: CreationOutput): boolean {
68
+ return !!output?.audioUrl;
69
+ }
70
+
71
+ /**
72
+ * Get primary media URL (for download/share)
73
+ */
74
+ export function getPrimaryMediaUrl(output?: CreationOutput): string | null {
75
+ if (!output) return null;
76
+
77
+ return (
78
+ output.videoUrl ||
79
+ output.imageUrl ||
80
+ output.imageUrls?.[0] ||
81
+ output.audioUrl ||
82
+ null
83
+ );
84
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Status Helpers
3
+ * Utility functions for creation status
4
+ */
5
+
6
+ import type { CreationStatus } from "../types";
7
+
8
+ /**
9
+ * Design system color keys for status
10
+ */
11
+ export type StatusColorKey = "success" | "primary" | "warning" | "error" | "textSecondary";
12
+
13
+ /**
14
+ * Get design system color key for status
15
+ */
16
+ export function getStatusColorKey(status: CreationStatus): StatusColorKey {
17
+ switch (status) {
18
+ case "completed":
19
+ return "success";
20
+ case "processing":
21
+ return "primary";
22
+ case "queued":
23
+ return "warning";
24
+ case "pending":
25
+ return "warning";
26
+ case "failed":
27
+ return "error";
28
+ default:
29
+ return "textSecondary";
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Get status color from colors object
35
+ */
36
+ export function getStatusColor(
37
+ status: CreationStatus,
38
+ colors: Record<string, string>,
39
+ ): string {
40
+ const key = getStatusColorKey(status);
41
+ return colors[key] || colors.textSecondary;
42
+ }
43
+
44
+ /**
45
+ * Get i18n key for status text
46
+ */
47
+ export function getStatusTextKey(status: CreationStatus): string {
48
+ return `creations.status.${status}`;
49
+ }
50
+
51
+ /**
52
+ * Get default status text (fallback)
53
+ */
54
+ export function getStatusText(status: CreationStatus): string {
55
+ switch (status) {
56
+ case "completed":
57
+ return "Completed";
58
+ case "processing":
59
+ return "In Progress";
60
+ case "queued":
61
+ return "Queued";
62
+ case "pending":
63
+ return "Pending";
64
+ case "failed":
65
+ return "Failed";
66
+ default:
67
+ return status;
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Check if creation is in progress
73
+ */
74
+ export function isInProgress(status: CreationStatus): boolean {
75
+ return status === "processing" || status === "pending" || status === "queued";
76
+ }
77
+
78
+ /**
79
+ * Check if creation is completed
80
+ */
81
+ export function isCompleted(status: CreationStatus): boolean {
82
+ return status === "completed";
83
+ }
84
+
85
+ /**
86
+ * Check if creation has failed
87
+ */
88
+ export function isFailed(status: CreationStatus): boolean {
89
+ return status === "failed";
90
+ }
@@ -1,25 +1,77 @@
1
1
  /**
2
- * @umituz/react-native-ai-creations
3
- *
2
+ * Creations Domain
4
3
  * AI-generated creations gallery with filtering, sharing, and management
5
- *
6
- * Architecture:
7
- * - Extends BaseRepository from @umituz/react-native-firestore
8
- * - Fully dynamic path structure (configurable per app)
9
- * - Fully dynamic document mapping (configurable per app)
10
- * - App-agnostic: Works with any app, no app-specific code
11
- *
12
- * This package is designed to be used across hundreds of apps.
13
- *
14
- * Usage:
15
- * import {
16
- * CreationsGalleryScreen,
17
- * CreationsHomeCard,
18
- * useCreations,
19
- * createCreationsRepository,
20
- * } from '@umituz/react-native-ai-creations';
21
4
  */
22
5
 
6
+ // eslint-disable-next-line no-console
7
+ if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] creations/index.ts - Module loading");
8
+
9
+ // =============================================================================
10
+ // DOMAIN LAYER - Types
11
+ // =============================================================================
12
+
13
+ export type {
14
+ CreationTypeId,
15
+ CreationStatus,
16
+ CreationCategory,
17
+ CreationFilter,
18
+ FilterOption,
19
+ CreationStats,
20
+ } from "./domain/types";
21
+
22
+ export {
23
+ ALL_CREATION_STATUSES,
24
+ ALL_CREATION_CATEGORIES,
25
+ ALL_CREATION_TYPES,
26
+ IMAGE_CREATION_TYPES,
27
+ VIDEO_CREATION_TYPES,
28
+ VOICE_CREATION_TYPES,
29
+ DEFAULT_CREATION_FILTER,
30
+ MEDIA_FILTER_OPTIONS,
31
+ STATUS_FILTER_OPTIONS,
32
+ getTypesForCategory,
33
+ getCategoryForType,
34
+ isTypeInCategory,
35
+ isVideoCreationType,
36
+ isImageCreationType,
37
+ isVoiceCreationType,
38
+ getMediaTypeForCreation,
39
+ calculateCreationStats,
40
+ } from "./domain/types";
41
+
42
+ // =============================================================================
43
+ // DOMAIN LAYER - Utils
44
+ // =============================================================================
45
+
46
+ export {
47
+ // Status helpers
48
+ getStatusColorKey,
49
+ getStatusColor,
50
+ getStatusTextKey,
51
+ getStatusText,
52
+ isInProgress,
53
+ isCompleted,
54
+ isFailed,
55
+ type StatusColorKey,
56
+ // Preview helpers
57
+ getPreviewUrl,
58
+ getAllMediaUrls,
59
+ hasDownloadableContent,
60
+ hasVideoContent,
61
+ hasAudioContent,
62
+ getPrimaryMediaUrl,
63
+ type CreationOutput,
64
+ // Creation helpers
65
+ getTypeIcon,
66
+ getTypeTextKey,
67
+ getTypeText,
68
+ getCreationTitle,
69
+ filterBySearch,
70
+ sortCreations,
71
+ truncateText,
72
+ type IconName,
73
+ } from "./domain/utils";
74
+
23
75
  // =============================================================================
24
76
  // DOMAIN LAYER - Entities
25
77
  // =============================================================================
@@ -28,7 +80,7 @@ export type { Creation, CreationDocument } from "./domain/entities";
28
80
  export { mapDocumentToCreation } from "./domain/entities";
29
81
 
30
82
  // =============================================================================
31
- // DOMAIN LAYER - Value Objects
83
+ // DOMAIN LAYER - Config
32
84
  // =============================================================================
33
85
 
34
86
  export type {
@@ -65,15 +117,37 @@ export type { ICreationsStorageService } from "./domain/services/ICreationsStora
65
117
  export { useCreations } from "./presentation/hooks/useCreations";
66
118
  export { useDeleteCreation } from "./presentation/hooks/useDeleteCreation";
67
119
  export { useCreationsFilter } from "./presentation/hooks/useCreationsFilter";
120
+ export { useAdvancedFilter } from "./presentation/hooks/useAdvancedFilter";
68
121
 
69
122
  // =============================================================================
70
123
  // PRESENTATION LAYER - Components
71
124
  // =============================================================================
72
125
 
126
+ // Core Components
127
+ export { CreationPreview } from "./presentation/components/CreationPreview";
128
+ export { CreationBadges } from "./presentation/components/CreationBadges";
129
+ export {
130
+ CreationActions,
131
+ type CreationAction,
132
+ } from "./presentation/components/CreationActions";
133
+ export {
134
+ CreationCard,
135
+ type CreationCardData,
136
+ type CreationCardCallbacks,
137
+ } from "./presentation/components/CreationCard";
73
138
  export { CreationThumbnail } from "./presentation/components/CreationThumbnail";
74
- export { CreationCard } from "./presentation/components/CreationCard";
75
- export { CreationsHomeCard } from "./presentation/components/CreationsHomeCard";
139
+
140
+ // Filter Components
76
141
  export { FilterChips } from "./presentation/components/FilterChips";
142
+ export {
143
+ CreationsFilterBar,
144
+ createMediaFilterButtons,
145
+ createStatusFilterButtons,
146
+ type FilterButton,
147
+ } from "./presentation/components/CreationsFilterBar";
148
+
149
+ // Gallery Components
150
+ export { CreationsHomeCard } from "./presentation/components/CreationsHomeCard";
77
151
  export { EmptyState } from "./presentation/components/EmptyState";
78
152
  export {
79
153
  CreationsProvider,
@@ -1,3 +1,6 @@
1
+ // eslint-disable-next-line no-console
2
+ if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] CreationsRepository.ts - Module loading");
3
+
1
4
  import { BaseRepository, FirestorePathResolver } from "@umituz/react-native-firebase";
2
5
  import type { ICreationsRepository } from "../../domain/repositories/ICreationsRepository";
3
6
  import type { Creation } from "../../domain/entities/Creation";
@@ -36,13 +39,23 @@ export class CreationsRepository
36
39
  collectionName: string,
37
40
  options?: RepositoryOptions,
38
41
  ) {
42
+ // eslint-disable-next-line no-console
43
+ if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] CreationsRepository - Constructor start");
39
44
  super();
40
45
 
41
46
  const documentMapper = options?.documentMapper ?? mapDocumentToCreation;
42
47
 
43
- this.pathResolver = new FirestorePathResolver(collectionName, this.getDb());
48
+ // eslint-disable-next-line no-console
49
+ if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] CreationsRepository - Getting db");
50
+ const db = this.getDb();
51
+ // eslint-disable-next-line no-console
52
+ if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] CreationsRepository - db:", db ? "available" : "null");
53
+
54
+ this.pathResolver = new FirestorePathResolver(collectionName, db);
44
55
  this.fetcher = new CreationsFetcher(this.pathResolver, documentMapper);
45
56
  this.writer = new CreationsWriter(this.pathResolver);
57
+ // eslint-disable-next-line no-console
58
+ if (typeof __DEV__ !== "undefined" && __DEV__) console.log("📍 [LIFECYCLE] CreationsRepository - Constructor end");
46
59
  }
47
60
 
48
61
  async getAll(userId: string): Promise<Creation[]> {
@@ -0,0 +1,120 @@
1
+ /**
2
+ * CreationActions Component
3
+ * Flexible action buttons for creations
4
+ */
5
+
6
+ import React, { useMemo } from "react";
7
+ import {
8
+ View,
9
+ StyleSheet,
10
+ TouchableOpacity,
11
+ ActivityIndicator,
12
+ } from "react-native";
13
+ import {
14
+ useAppDesignTokens,
15
+ AtomicIcon,
16
+ } from "@umituz/react-native-design-system";
17
+
18
+ export interface CreationAction {
19
+ /** Unique action identifier */
20
+ id: string;
21
+ /** Icon name */
22
+ icon: string;
23
+ /** Icon color (design system color key) */
24
+ color?: "primary" | "secondary" | "error" | "success" | "textInverse";
25
+ /** Show loading state */
26
+ loading?: boolean;
27
+ /** Disabled state */
28
+ disabled?: boolean;
29
+ /** Use filled background (primary color) */
30
+ filled?: boolean;
31
+ /** Action handler */
32
+ onPress: () => void;
33
+ }
34
+
35
+ interface CreationActionsProps {
36
+ /** Array of actions to display */
37
+ readonly actions: CreationAction[];
38
+ /** Button size */
39
+ readonly size?: "sm" | "md" | "lg";
40
+ /** Layout direction */
41
+ readonly direction?: "row" | "column";
42
+ }
43
+
44
+ const SIZES = {
45
+ sm: { button: 28, icon: "xs" as const },
46
+ md: { button: 36, icon: "sm" as const },
47
+ lg: { button: 44, icon: "md" as const },
48
+ };
49
+
50
+ export function CreationActions({
51
+ actions,
52
+ size = "md",
53
+ direction = "row",
54
+ }: CreationActionsProps) {
55
+ const tokens = useAppDesignTokens();
56
+ const sizeConfig = SIZES[size];
57
+
58
+ const styles = useMemo(
59
+ () =>
60
+ StyleSheet.create({
61
+ container: {
62
+ flexDirection: direction,
63
+ gap: 8,
64
+ },
65
+ actionButton: {
66
+ width: sizeConfig.button,
67
+ height: sizeConfig.button,
68
+ borderRadius: sizeConfig.button / 2,
69
+ borderWidth: 1,
70
+ alignItems: "center",
71
+ justifyContent: "center",
72
+ backgroundColor: tokens.colors.surface,
73
+ borderColor: tokens.colors.borderLight,
74
+ },
75
+ actionButtonFilled: {
76
+ backgroundColor: tokens.colors.primary,
77
+ borderWidth: 0,
78
+ },
79
+ actionButtonDisabled: {
80
+ opacity: 0.5,
81
+ },
82
+ }),
83
+ [tokens, sizeConfig, direction]
84
+ );
85
+
86
+ if (actions.length === 0) {
87
+ return null;
88
+ }
89
+
90
+ return (
91
+ <View style={styles.container}>
92
+ {actions.map((action) => (
93
+ <TouchableOpacity
94
+ key={action.id}
95
+ style={[
96
+ styles.actionButton,
97
+ action.filled && styles.actionButtonFilled,
98
+ action.disabled && styles.actionButtonDisabled,
99
+ ]}
100
+ onPress={action.onPress}
101
+ disabled={action.disabled || action.loading}
102
+ activeOpacity={0.7}
103
+ >
104
+ {action.loading ? (
105
+ <ActivityIndicator
106
+ size="small"
107
+ color={action.filled ? tokens.colors.textInverse : tokens.colors.primary}
108
+ />
109
+ ) : (
110
+ <AtomicIcon
111
+ name={action.icon}
112
+ size={sizeConfig.icon}
113
+ color={action.color || (action.filled ? "textInverse" : "primary")}
114
+ />
115
+ )}
116
+ </TouchableOpacity>
117
+ ))}
118
+ </View>
119
+ );
120
+ }
@@ -0,0 +1,111 @@
1
+ /**
2
+ * CreationBadges Component
3
+ * Displays status and type badges overlay
4
+ */
5
+
6
+ import React, { useMemo } from "react";
7
+ import { View, StyleSheet, Text } from "react-native";
8
+ import {
9
+ useAppDesignTokens,
10
+ AtomicIcon,
11
+ } from "@umituz/react-native-design-system";
12
+ import type { CreationStatus, CreationTypeId } from "../../domain/types";
13
+ import { getStatusColorKey, getStatusText, getTypeIcon, getTypeText } from "../../domain/utils";
14
+
15
+ interface CreationBadgesProps {
16
+ /** Creation status */
17
+ readonly status: CreationStatus;
18
+ /** Creation type */
19
+ readonly type?: CreationTypeId;
20
+ /** Show status badge */
21
+ readonly showStatus?: boolean;
22
+ /** Show type badge */
23
+ readonly showType?: boolean;
24
+ /** Custom status text (for i18n) */
25
+ readonly statusText?: string;
26
+ /** Custom type text (for i18n) */
27
+ readonly typeText?: string;
28
+ }
29
+
30
+ export function CreationBadges({
31
+ status,
32
+ type,
33
+ showStatus = true,
34
+ showType = true,
35
+ statusText,
36
+ typeText,
37
+ }: CreationBadgesProps) {
38
+ const tokens = useAppDesignTokens();
39
+ const colorKey = getStatusColorKey(status);
40
+ const statusColor = (tokens.colors as unknown as Record<string, string>)[colorKey] || tokens.colors.textSecondary;
41
+ const displayStatusText = statusText || getStatusText(status);
42
+ const displayTypeText = typeText || (type ? getTypeText(type) : "");
43
+ const typeIcon = type ? getTypeIcon(type) : "image";
44
+
45
+ const styles = useMemo(
46
+ () =>
47
+ StyleSheet.create({
48
+ statusBadge: {
49
+ position: "absolute",
50
+ top: 8,
51
+ right: 8,
52
+ flexDirection: "row",
53
+ alignItems: "center",
54
+ paddingHorizontal: 8,
55
+ paddingVertical: 4,
56
+ borderRadius: 12,
57
+ backgroundColor: statusColor + "20",
58
+ },
59
+ statusDot: {
60
+ width: 6,
61
+ height: 6,
62
+ borderRadius: 3,
63
+ marginRight: 4,
64
+ backgroundColor: statusColor,
65
+ },
66
+ statusText: {
67
+ fontSize: 10,
68
+ fontWeight: "600",
69
+ textTransform: "capitalize",
70
+ color: statusColor,
71
+ },
72
+ typeBadge: {
73
+ position: "absolute",
74
+ top: 8,
75
+ left: 8,
76
+ flexDirection: "row",
77
+ alignItems: "center",
78
+ paddingHorizontal: 8,
79
+ paddingVertical: 4,
80
+ borderRadius: 12,
81
+ backgroundColor: "rgba(0,0,0,0.6)",
82
+ gap: 4,
83
+ },
84
+ typeText: {
85
+ fontSize: 10,
86
+ fontWeight: "600",
87
+ color: "white",
88
+ textTransform: "capitalize",
89
+ },
90
+ }),
91
+ [statusColor]
92
+ );
93
+
94
+ return (
95
+ <>
96
+ {showStatus && (
97
+ <View style={styles.statusBadge}>
98
+ <View style={styles.statusDot} />
99
+ <Text style={styles.statusText}>{displayStatusText}</Text>
100
+ </View>
101
+ )}
102
+
103
+ {showType && type && (
104
+ <View style={styles.typeBadge}>
105
+ <AtomicIcon name={typeIcon} color="textInverse" size="xs" />
106
+ <Text style={styles.typeText}>{displayTypeText}</Text>
107
+ </View>
108
+ )}
109
+ </>
110
+ );
111
+ }