@umituz/react-native-ai-generation-content 1.17.28 → 1.17.30

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.17.28",
3
+ "version": "1.17.30",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
package/src/index.ts CHANGED
@@ -121,6 +121,10 @@ export {
121
121
  createJobPoller,
122
122
  generationWrapper,
123
123
  createGenerationWrapper,
124
+ executeImageFeature,
125
+ hasImageFeatureSupport,
126
+ executeVideoFeature,
127
+ hasVideoFeatureSupport,
124
128
  } from "./infrastructure/services";
125
129
 
126
130
  export type {
@@ -128,6 +132,14 @@ export type {
128
132
  PollJobOptions,
129
133
  PollJobResult,
130
134
  WrapperConfig,
135
+ ImageResultExtractor,
136
+ ExecuteImageFeatureOptions,
137
+ ImageFeatureResult,
138
+ ImageFeatureRequest,
139
+ VideoResultExtractor,
140
+ ExecuteVideoFeatureOptions,
141
+ VideoFeatureResult,
142
+ VideoFeatureRequest,
131
143
  } from "./infrastructure/services";
132
144
 
133
145
  // =============================================================================
@@ -275,6 +287,10 @@ export {
275
287
  FeatureHeader,
276
288
  // Photo Upload
277
289
  PhotoUploadCard,
290
+ // Selectors
291
+ StyleSelector,
292
+ AspectRatioSelector,
293
+ DurationSelector,
278
294
  } from "./presentation/components";
279
295
 
280
296
  export type {
@@ -314,6 +330,13 @@ export type {
314
330
  // Photo Upload
315
331
  PhotoUploadCardProps,
316
332
  PhotoUploadCardConfig,
333
+ // Selectors
334
+ StyleSelectorProps,
335
+ AspectRatioSelectorProps,
336
+ DurationSelectorProps,
337
+ StyleOption,
338
+ AspectRatioOption,
339
+ DurationValue,
317
340
  } from "./presentation/components";
318
341
 
319
342
  // =============================================================================
@@ -28,3 +28,4 @@ export * from "./buttons";
28
28
  export * from "./display";
29
29
  export * from "./headers";
30
30
  export * from "./PhotoUploadCard";
31
+ export * from "./selectors";
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Aspect Ratio Selector Component
3
+ * Generic, props-driven aspect ratio selection
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, TouchableOpacity, StyleSheet } from "react-native";
8
+ import {
9
+ AtomicText,
10
+ AtomicIcon,
11
+ useAppDesignTokens,
12
+ } from "@umituz/react-native-design-system";
13
+ import type { AspectRatioOption } from "./types";
14
+
15
+ export interface AspectRatioSelectorProps {
16
+ ratios: AspectRatioOption[];
17
+ selectedRatio: "16:9" | "9:16" | "1:1";
18
+ onRatioSelect: (ratio: "16:9" | "9:16" | "1:1") => void;
19
+ title: string;
20
+ }
21
+
22
+ export const AspectRatioSelector: React.FC<AspectRatioSelectorProps> = ({
23
+ ratios,
24
+ selectedRatio,
25
+ onRatioSelect,
26
+ title,
27
+ }) => {
28
+ const tokens = useAppDesignTokens();
29
+
30
+ return (
31
+ <View style={componentStyles.section}>
32
+ <AtomicText
33
+ type="bodyMedium"
34
+ style={{
35
+ color: tokens.colors.textPrimary,
36
+ fontWeight: "600",
37
+ marginBottom: 12,
38
+ }}
39
+ >
40
+ {title}
41
+ </AtomicText>
42
+ <View style={componentStyles.aspectRatioGrid}>
43
+ {ratios.map((ratio) => (
44
+ <TouchableOpacity
45
+ key={ratio.id}
46
+ style={[
47
+ componentStyles.aspectRatioCard,
48
+ {
49
+ backgroundColor:
50
+ selectedRatio === ratio.id
51
+ ? tokens.colors.primary + "20"
52
+ : tokens.colors.surface,
53
+ borderColor:
54
+ selectedRatio === ratio.id
55
+ ? tokens.colors.primary
56
+ : tokens.colors.borderLight,
57
+ },
58
+ ]}
59
+ onPress={() => onRatioSelect(ratio.id)}
60
+ >
61
+ <AtomicIcon
62
+ name={ratio.icon as never}
63
+ size="lg"
64
+ color={selectedRatio === ratio.id ? "primary" : "secondary"}
65
+ />
66
+ <AtomicText
67
+ type="bodySmall"
68
+ style={{
69
+ color: tokens.colors.textPrimary,
70
+ fontWeight: selectedRatio === ratio.id ? "600" : "400",
71
+ marginTop: 8,
72
+ }}
73
+ >
74
+ {ratio.name}
75
+ </AtomicText>
76
+ <AtomicText
77
+ type="labelSmall"
78
+ style={{ color: tokens.colors.textSecondary, marginTop: 2 }}
79
+ >
80
+ {ratio.description}
81
+ </AtomicText>
82
+ </TouchableOpacity>
83
+ ))}
84
+ </View>
85
+ </View>
86
+ );
87
+ };
88
+
89
+ const componentStyles = StyleSheet.create({
90
+ section: {
91
+ padding: 16,
92
+ marginBottom: 8,
93
+ },
94
+ aspectRatioGrid: {
95
+ flexDirection: "row",
96
+ gap: 12,
97
+ },
98
+ aspectRatioCard: {
99
+ flex: 1,
100
+ padding: 16,
101
+ borderRadius: 12,
102
+ borderWidth: 2,
103
+ alignItems: "center",
104
+ },
105
+ });
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Duration Selector Component
3
+ * Generic, props-driven duration selection for video/audio generation
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, TouchableOpacity, StyleSheet } from "react-native";
8
+ import {
9
+ AtomicText,
10
+ useAppDesignTokens,
11
+ } from "@umituz/react-native-design-system";
12
+ import type { DurationValue } from "./types";
13
+
14
+ export interface DurationSelectorProps<T extends DurationValue> {
15
+ duration: T;
16
+ durationOptions: readonly T[];
17
+ onDurationSelect: (duration: T) => void;
18
+ title: string;
19
+ formatLabel?: (duration: T) => string;
20
+ }
21
+
22
+ export function DurationSelector<T extends DurationValue>({
23
+ duration,
24
+ durationOptions,
25
+ onDurationSelect,
26
+ title,
27
+ formatLabel = (d) => `${d}s`,
28
+ }: DurationSelectorProps<T>): React.ReactElement {
29
+ const tokens = useAppDesignTokens();
30
+
31
+ return (
32
+ <View style={componentStyles.section}>
33
+ <AtomicText
34
+ type="bodyMedium"
35
+ style={{
36
+ color: tokens.colors.textPrimary,
37
+ fontWeight: "600",
38
+ marginBottom: 12,
39
+ }}
40
+ >
41
+ {title}
42
+ </AtomicText>
43
+ <View style={componentStyles.durationGrid}>
44
+ {durationOptions.map((sec) => (
45
+ <TouchableOpacity
46
+ key={sec}
47
+ style={[
48
+ componentStyles.durationButton,
49
+ {
50
+ backgroundColor:
51
+ duration === sec
52
+ ? tokens.colors.primary
53
+ : tokens.colors.surface,
54
+ borderColor:
55
+ duration === sec
56
+ ? tokens.colors.primary
57
+ : tokens.colors.borderLight,
58
+ },
59
+ ]}
60
+ onPress={() => onDurationSelect(sec)}
61
+ >
62
+ <AtomicText
63
+ type="bodyLarge"
64
+ style={{
65
+ color:
66
+ duration === sec
67
+ ? tokens.colors.textInverse
68
+ : tokens.colors.textPrimary,
69
+ fontWeight: duration === sec ? "700" : "400",
70
+ }}
71
+ >
72
+ {formatLabel(sec)}
73
+ </AtomicText>
74
+ </TouchableOpacity>
75
+ ))}
76
+ </View>
77
+ </View>
78
+ );
79
+ }
80
+
81
+ const componentStyles = StyleSheet.create({
82
+ section: {
83
+ padding: 16,
84
+ marginBottom: 8,
85
+ },
86
+ durationGrid: {
87
+ flexDirection: "row",
88
+ gap: 12,
89
+ },
90
+ durationButton: {
91
+ flex: 1,
92
+ paddingVertical: 20,
93
+ borderRadius: 12,
94
+ borderWidth: 2,
95
+ alignItems: "center",
96
+ justifyContent: "center",
97
+ },
98
+ });
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Style Selector Component
3
+ * Generic, props-driven style selection for AI generation
4
+ */
5
+
6
+ import React from "react";
7
+ import { View, ScrollView, TouchableOpacity, StyleSheet } from "react-native";
8
+ import {
9
+ AtomicText,
10
+ AtomicIcon,
11
+ useAppDesignTokens,
12
+ } from "@umituz/react-native-design-system";
13
+ import type { StyleOption } from "./types";
14
+
15
+ export interface StyleSelectorProps {
16
+ styles: StyleOption[];
17
+ selectedStyle: string;
18
+ onStyleSelect: (styleId: string) => void;
19
+ title: string;
20
+ }
21
+
22
+ export const StyleSelector: React.FC<StyleSelectorProps> = ({
23
+ styles,
24
+ selectedStyle,
25
+ onStyleSelect,
26
+ title,
27
+ }) => {
28
+ const tokens = useAppDesignTokens();
29
+
30
+ return (
31
+ <View style={componentStyles.section}>
32
+ <AtomicText
33
+ type="bodyMedium"
34
+ style={{
35
+ color: tokens.colors.textPrimary,
36
+ fontWeight: "600",
37
+ marginBottom: 12,
38
+ }}
39
+ >
40
+ {title}
41
+ </AtomicText>
42
+ <ScrollView
43
+ horizontal
44
+ showsHorizontalScrollIndicator={false}
45
+ style={componentStyles.stylesScroll}
46
+ >
47
+ {styles.map((style) => {
48
+ const isSelected = selectedStyle === style.id;
49
+
50
+ return (
51
+ <TouchableOpacity
52
+ key={style.id}
53
+ style={[
54
+ componentStyles.styleCard,
55
+ {
56
+ backgroundColor: isSelected
57
+ ? tokens.colors.primary
58
+ : tokens.colors.surface,
59
+ borderColor: isSelected
60
+ ? tokens.colors.primary
61
+ : tokens.colors.borderLight,
62
+ },
63
+ ]}
64
+ onPress={() => onStyleSelect(style.id)}
65
+ >
66
+ {style.thumbnail ? (
67
+ <AtomicText type="headlineLarge" style={{ marginBottom: 8 }}>
68
+ {style.thumbnail}
69
+ </AtomicText>
70
+ ) : style.icon ? (
71
+ <AtomicIcon
72
+ name={style.icon as never}
73
+ size="lg"
74
+ color={isSelected ? "primary" : "secondary"}
75
+ />
76
+ ) : null}
77
+ <AtomicText
78
+ type="bodySmall"
79
+ style={{
80
+ color: isSelected
81
+ ? tokens.colors.textInverse
82
+ : tokens.colors.textPrimary,
83
+ fontWeight: isSelected ? "600" : "400",
84
+ textAlign: "center",
85
+ }}
86
+ >
87
+ {style.name}
88
+ </AtomicText>
89
+ {style.description && (
90
+ <AtomicText
91
+ type="labelSmall"
92
+ style={{
93
+ color: isSelected
94
+ ? tokens.colors.textInverse
95
+ : tokens.colors.textSecondary,
96
+ opacity: isSelected ? 0.9 : 0.7,
97
+ textAlign: "center",
98
+ marginTop: 4,
99
+ }}
100
+ numberOfLines={2}
101
+ >
102
+ {style.description}
103
+ </AtomicText>
104
+ )}
105
+ </TouchableOpacity>
106
+ );
107
+ })}
108
+ </ScrollView>
109
+ </View>
110
+ );
111
+ };
112
+
113
+ const componentStyles = StyleSheet.create({
114
+ section: {
115
+ padding: 16,
116
+ marginBottom: 8,
117
+ },
118
+ stylesScroll: {
119
+ marginHorizontal: -16,
120
+ paddingHorizontal: 16,
121
+ },
122
+ styleCard: {
123
+ width: 120,
124
+ padding: 16,
125
+ borderRadius: 16,
126
+ borderWidth: 2,
127
+ marginRight: 12,
128
+ alignItems: "center",
129
+ minHeight: 140,
130
+ },
131
+ });
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Selector Components
3
+ * Generic, props-driven selection UI components
4
+ */
5
+
6
+ export { StyleSelector } from "./StyleSelector";
7
+ export { AspectRatioSelector } from "./AspectRatioSelector";
8
+ export { DurationSelector } from "./DurationSelector";
9
+
10
+ export type { StyleSelectorProps } from "./StyleSelector";
11
+ export type { AspectRatioSelectorProps } from "./AspectRatioSelector";
12
+ export type { DurationSelectorProps } from "./DurationSelector";
13
+
14
+ export type {
15
+ StyleOption,
16
+ AspectRatioOption,
17
+ DurationValue,
18
+ } from "./types";
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Selector Component Types
3
+ * Generic types for selector UI components
4
+ */
5
+
6
+ /**
7
+ * Style option for StyleSelector
8
+ * All fields are required - app provides translated values
9
+ */
10
+ export interface StyleOption {
11
+ id: string;
12
+ name: string;
13
+ description?: string;
14
+ thumbnail?: string;
15
+ icon?: string;
16
+ }
17
+
18
+ /**
19
+ * Aspect ratio option for AspectRatioSelector
20
+ * App provides translated name and description
21
+ */
22
+ export interface AspectRatioOption {
23
+ id: "16:9" | "9:16" | "1:1";
24
+ name: string;
25
+ icon: string;
26
+ description: string;
27
+ }
28
+
29
+ /**
30
+ * Duration value type (seconds)
31
+ */
32
+ export type DurationValue = number;