@umituz/react-native-ai-generation-content 1.12.44 → 1.13.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.
- package/package.json +1 -1
- package/src/domains/creations/presentation/components/CreationCard.tsx +1 -1
- package/src/domains/creations/presentation/components/CreationsProvider.tsx +56 -0
- package/src/domains/creations/presentation/components/GalleryEmptyStates.tsx +70 -5
- package/src/domains/creations/presentation/components/index.ts +1 -0
package/package.json
CHANGED
|
@@ -31,7 +31,7 @@ export function CreationCard({
|
|
|
31
31
|
const tokens = useAppDesignTokens();
|
|
32
32
|
const { translatedTypes, t } = useCreationsProvider();
|
|
33
33
|
|
|
34
|
-
const typeConfig = translatedTypes.find((
|
|
34
|
+
const typeConfig = translatedTypes.find((type) => type.id === creation.type);
|
|
35
35
|
const icon = typeConfig?.icon;
|
|
36
36
|
// Use manual name if available, otherwise use translated label from config
|
|
37
37
|
const label = (creation.metadata?.names as string) || typeConfig?.labelKey || creation.type;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creations Provider
|
|
3
|
+
* Context provider for creations configuration and localization
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { createContext, useContext, useMemo, type ReactNode } from "react";
|
|
7
|
+
import type { CreationsConfig, CreationType } from "../../domain/value-objects/CreationsConfig";
|
|
8
|
+
import { getTranslatedTypes } from "../utils/filterUtils";
|
|
9
|
+
|
|
10
|
+
interface CreationsContextValue {
|
|
11
|
+
config: CreationsConfig;
|
|
12
|
+
t: (key: string) => string;
|
|
13
|
+
translatedTypes: readonly CreationType[];
|
|
14
|
+
getLocalizedTitle: (typeId: string) => string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const CreationsContext = createContext<CreationsContextValue | null>(null);
|
|
18
|
+
|
|
19
|
+
interface CreationsProviderProps {
|
|
20
|
+
config: CreationsConfig;
|
|
21
|
+
t: (key: string) => string;
|
|
22
|
+
children: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function CreationsProvider({ config, t, children }: CreationsProviderProps) {
|
|
26
|
+
const translatedTypes = useMemo(() => getTranslatedTypes(config, t), [config, t]);
|
|
27
|
+
|
|
28
|
+
const getLocalizedTitle = (typeId: string): string => {
|
|
29
|
+
const typeConfig = translatedTypes.find((type) => type.id === typeId);
|
|
30
|
+
return typeConfig?.labelKey || typeId;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const value = useMemo<CreationsContextValue>(
|
|
34
|
+
() => ({
|
|
35
|
+
config,
|
|
36
|
+
t,
|
|
37
|
+
translatedTypes,
|
|
38
|
+
getLocalizedTitle,
|
|
39
|
+
}),
|
|
40
|
+
[config, t, translatedTypes]
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<CreationsContext.Provider value={value}>
|
|
45
|
+
{children}
|
|
46
|
+
</CreationsContext.Provider>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function useCreationsProvider(): CreationsContextValue {
|
|
51
|
+
const context = useContext(CreationsContext);
|
|
52
|
+
if (!context) {
|
|
53
|
+
throw new Error("useCreationsProvider must be used within a CreationsProvider");
|
|
54
|
+
}
|
|
55
|
+
return context;
|
|
56
|
+
}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React from "react";
|
|
7
|
-
import { View,
|
|
8
|
-
import type
|
|
7
|
+
import { View, StyleSheet } from "react-native";
|
|
8
|
+
import { AtomicSkeleton, type DesignTokens } from "@umituz/react-native-design-system";
|
|
9
9
|
import { EmptyState } from "./EmptyState";
|
|
10
10
|
import type { Creation } from "../../domain/entities/Creation";
|
|
11
11
|
|
|
@@ -22,6 +22,42 @@ interface GalleryEmptyStatesProps {
|
|
|
22
22
|
onClearFilters: () => void;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/** Skeleton card matching CreationCard layout */
|
|
26
|
+
function CreationCardSkeleton({ tokens }: { tokens: DesignTokens }) {
|
|
27
|
+
const styles = createSkeletonStyles(tokens);
|
|
28
|
+
return (
|
|
29
|
+
<View style={styles.card}>
|
|
30
|
+
{/* Thumbnail skeleton */}
|
|
31
|
+
<AtomicSkeleton
|
|
32
|
+
pattern="custom"
|
|
33
|
+
custom={[{ width: 100, height: 100, borderRadius: 0 }]}
|
|
34
|
+
/>
|
|
35
|
+
{/* Content skeleton */}
|
|
36
|
+
<View style={styles.content}>
|
|
37
|
+
<View style={styles.textArea}>
|
|
38
|
+
<AtomicSkeleton
|
|
39
|
+
pattern="custom"
|
|
40
|
+
custom={[
|
|
41
|
+
{ width: 120, height: 18, borderRadius: 4, marginBottom: 8 },
|
|
42
|
+
{ width: 100, height: 14, borderRadius: 4 },
|
|
43
|
+
]}
|
|
44
|
+
/>
|
|
45
|
+
</View>
|
|
46
|
+
{/* Action buttons skeleton */}
|
|
47
|
+
<View style={styles.actions}>
|
|
48
|
+
{[1, 2, 3, 4].map((i) => (
|
|
49
|
+
<AtomicSkeleton
|
|
50
|
+
key={i}
|
|
51
|
+
pattern="custom"
|
|
52
|
+
custom={[{ width: 36, height: 36, borderRadius: 18 }]}
|
|
53
|
+
/>
|
|
54
|
+
))}
|
|
55
|
+
</View>
|
|
56
|
+
</View>
|
|
57
|
+
</View>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
25
61
|
export function GalleryEmptyStates({
|
|
26
62
|
isLoading,
|
|
27
63
|
creations,
|
|
@@ -36,11 +72,13 @@ export function GalleryEmptyStates({
|
|
|
36
72
|
}: GalleryEmptyStatesProps) {
|
|
37
73
|
const styles = createStyles(tokens);
|
|
38
74
|
|
|
39
|
-
// 1. Loading State
|
|
75
|
+
// 1. Loading State - Show skeleton cards
|
|
40
76
|
if (isLoading && (!creations || creations?.length === 0)) {
|
|
41
77
|
return (
|
|
42
|
-
<View style={styles.
|
|
43
|
-
|
|
78
|
+
<View style={styles.skeletonContainer}>
|
|
79
|
+
{[1, 2, 3].map((i) => (
|
|
80
|
+
<CreationCardSkeleton key={i} tokens={tokens} />
|
|
81
|
+
))}
|
|
44
82
|
</View>
|
|
45
83
|
);
|
|
46
84
|
}
|
|
@@ -84,4 +122,31 @@ const createStyles = (tokens: DesignTokens) => StyleSheet.create({
|
|
|
84
122
|
minHeight: 400,
|
|
85
123
|
paddingHorizontal: tokens.spacing.xl,
|
|
86
124
|
},
|
|
125
|
+
skeletonContainer: {
|
|
126
|
+
flex: 1,
|
|
127
|
+
paddingHorizontal: tokens.spacing.md,
|
|
128
|
+
paddingTop: tokens.spacing.md,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const createSkeletonStyles = (tokens: DesignTokens) => StyleSheet.create({
|
|
133
|
+
card: {
|
|
134
|
+
flexDirection: 'row',
|
|
135
|
+
backgroundColor: tokens.colors.surface,
|
|
136
|
+
borderRadius: tokens.spacing.md,
|
|
137
|
+
overflow: 'hidden',
|
|
138
|
+
marginBottom: tokens.spacing.md,
|
|
139
|
+
},
|
|
140
|
+
content: {
|
|
141
|
+
flex: 1,
|
|
142
|
+
padding: tokens.spacing.md,
|
|
143
|
+
justifyContent: 'space-between',
|
|
144
|
+
},
|
|
145
|
+
textArea: {
|
|
146
|
+
gap: tokens.spacing.xs,
|
|
147
|
+
},
|
|
148
|
+
actions: {
|
|
149
|
+
flexDirection: 'row',
|
|
150
|
+
gap: tokens.spacing.sm,
|
|
151
|
+
},
|
|
87
152
|
});
|
|
@@ -11,6 +11,7 @@ export { CreationCard } from "./CreationCard";
|
|
|
11
11
|
export { CreationThumbnail } from "./CreationThumbnail";
|
|
12
12
|
export { CreationImageViewer } from "./CreationImageViewer";
|
|
13
13
|
export { CreationsGrid } from "./CreationsGrid";
|
|
14
|
+
export { CreationsProvider, useCreationsProvider } from "./CreationsProvider";
|
|
14
15
|
|
|
15
16
|
// Detail Components
|
|
16
17
|
export { DetailHeader } from "./CreationDetail/DetailHeader";
|