@umituz/react-native-ai-generation-content 1.27.26 → 1.27.28

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.27.26",
3
+ "version": "1.27.28",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -1,17 +1,19 @@
1
1
  /**
2
2
  * SelectionScreen
3
3
  * Generic selection step for wizard flows (duration, style, etc.)
4
+ * Uses design system: NavigationHeader + ScreenLayout
4
5
  */
5
6
 
6
- import React, { useState, useCallback } from "react";
7
- import { View, ScrollView, TouchableOpacity } from "react-native";
7
+ import React, { useState, useCallback, useMemo } from "react";
8
+ import { View, TouchableOpacity, StyleSheet } from "react-native";
8
9
  import {
9
10
  AtomicText,
10
- AtomicButton,
11
11
  AtomicIcon,
12
12
  useAppDesignTokens,
13
+ ScreenLayout,
14
+ NavigationHeader,
15
+ type DesignTokens,
13
16
  } from "@umituz/react-native-design-system";
14
- import { styles } from "./SelectionScreen.styles";
15
17
  import type { SelectionScreenProps } from "./SelectionScreen.types";
16
18
 
17
19
  export type {
@@ -78,28 +80,55 @@ export const SelectionScreen: React.FC<SelectionScreenProps> = ({
78
80
  [isMultiSelect, selected],
79
81
  );
80
82
 
81
- return (
82
- <View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
83
- <View style={[styles.header, { paddingHorizontal: tokens.spacing.md }]}>
84
- <AtomicButton variant="text" size="sm" onPress={onBack}>
85
- <View style={styles.backButtonContent}>
86
- <AtomicIcon name="arrow-back" size="sm" color="textPrimary" />
87
- {translations.backButton ? (
88
- <AtomicText type="labelMedium" color="textPrimary" style={styles.backButtonText}>
89
- {translations.backButton}
90
- </AtomicText>
91
- ) : null}
92
- </View>
93
- </AtomicButton>
94
- </View>
83
+ const styles = useMemo(() => createStyles(tokens), [tokens]);
95
84
 
96
- <ScrollView style={styles.scrollView} contentContainerStyle={{ padding: tokens.spacing.md }}>
85
+ return (
86
+ <View style={{ flex: 1, backgroundColor: tokens.colors.backgroundPrimary }}>
87
+ <NavigationHeader
88
+ title=""
89
+ onBackPress={onBack}
90
+ rightElement={
91
+ <TouchableOpacity
92
+ onPress={handleContinue}
93
+ activeOpacity={0.7}
94
+ disabled={!canContinue}
95
+ style={[
96
+ styles.continueButton,
97
+ {
98
+ backgroundColor: canContinue ? tokens.colors.primary : tokens.colors.surfaceVariant,
99
+ opacity: canContinue ? 1 : 0.5,
100
+ },
101
+ ]}
102
+ >
103
+ <AtomicText
104
+ type="bodyMedium"
105
+ style={[
106
+ styles.continueText,
107
+ { color: canContinue ? tokens.colors.onPrimary : tokens.colors.textSecondary },
108
+ ]}
109
+ >
110
+ {translations.continueButton}
111
+ </AtomicText>
112
+ <AtomicIcon
113
+ name="arrow-forward"
114
+ size="sm"
115
+ color={canContinue ? "onPrimary" : "textSecondary"}
116
+ />
117
+ </TouchableOpacity>
118
+ }
119
+ />
120
+ <ScreenLayout
121
+ scrollable={true}
122
+ edges={["left", "right"]}
123
+ hideScrollIndicator={true}
124
+ contentContainerStyle={styles.scrollContent}
125
+ >
97
126
  <AtomicText type="headlineMedium" color="textPrimary" style={styles.title}>
98
127
  {translations.title}
99
128
  </AtomicText>
100
129
 
101
130
  {translations.subtitle ? (
102
- <AtomicText type="bodyMedium" color="textSecondary" style={{ marginBottom: tokens.spacing.lg }}>
131
+ <AtomicText type="bodyMedium" color="textSecondary" style={styles.subtitle}>
103
132
  {translations.subtitle}
104
133
  </AtomicText>
105
134
  ) : null}
@@ -115,7 +144,6 @@ export const SelectionScreen: React.FC<SelectionScreenProps> = ({
115
144
  {
116
145
  backgroundColor: isSelected ? tokens.colors.primaryContainer : tokens.colors.backgroundSecondary,
117
146
  borderColor: isSelected ? tokens.colors.primary : tokens.colors.border,
118
- borderRadius: tokens.borders.radius.md,
119
147
  },
120
148
  ]}
121
149
  onPress={() => handleSelect(option.id)}
@@ -136,13 +164,61 @@ export const SelectionScreen: React.FC<SelectionScreenProps> = ({
136
164
  );
137
165
  })}
138
166
  </View>
139
- </ScrollView>
140
-
141
- <View style={[styles.footer, { padding: tokens.spacing.md }]}>
142
- <AtomicButton variant="primary" size="lg" onPress={handleContinue} disabled={!canContinue} style={styles.continueButton}>
143
- {translations.continueButton}
144
- </AtomicButton>
145
- </View>
167
+ </ScreenLayout>
146
168
  </View>
147
169
  );
148
170
  };
171
+
172
+ const createStyles = (tokens: DesignTokens) =>
173
+ StyleSheet.create({
174
+ scrollContent: {
175
+ paddingHorizontal: tokens.spacing.lg,
176
+ paddingBottom: 40,
177
+ },
178
+ title: {
179
+ marginBottom: tokens.spacing.sm,
180
+ },
181
+ subtitle: {
182
+ marginBottom: tokens.spacing.lg,
183
+ },
184
+ optionsGrid: {
185
+ flexDirection: "row",
186
+ flexWrap: "wrap",
187
+ gap: tokens.spacing.sm,
188
+ },
189
+ optionCard: {
190
+ flex: 1,
191
+ minWidth: "45%",
192
+ padding: tokens.spacing.md,
193
+ borderWidth: 2,
194
+ borderRadius: tokens.borders.radius.md,
195
+ alignItems: "center",
196
+ justifyContent: "center",
197
+ gap: tokens.spacing.xs,
198
+ position: "relative",
199
+ },
200
+ optionLabel: {
201
+ textAlign: "center",
202
+ },
203
+ checkmark: {
204
+ position: "absolute",
205
+ top: tokens.spacing.xs,
206
+ right: tokens.spacing.xs,
207
+ width: 20,
208
+ height: 20,
209
+ borderRadius: 10,
210
+ alignItems: "center",
211
+ justifyContent: "center",
212
+ },
213
+ continueButton: {
214
+ flexDirection: "row",
215
+ alignItems: "center",
216
+ paddingHorizontal: tokens.spacing.md,
217
+ paddingVertical: tokens.spacing.xs,
218
+ borderRadius: tokens.borders.radius.full,
219
+ },
220
+ continueText: {
221
+ fontWeight: "800",
222
+ marginRight: 4,
223
+ },
224
+ });
@@ -1,16 +1,19 @@
1
1
  /**
2
2
  * TextInputScreen
3
3
  * Generic text input step for wizard flows
4
- * Header: Back on left, Continue on right
4
+ * Uses design system: NavigationHeader + ScreenLayout
5
5
  */
6
6
 
7
- import React, { useState, useCallback } from "react";
8
- import { View, ScrollView, TextInput, TouchableOpacity, StyleSheet } from "react-native";
7
+ import React, { useState, useCallback, useMemo } from "react";
8
+ import { View, TextInput, TouchableOpacity, StyleSheet } from "react-native";
9
9
  import {
10
10
  AtomicText,
11
11
  AtomicButton,
12
12
  AtomicIcon,
13
13
  useAppDesignTokens,
14
+ ScreenLayout,
15
+ NavigationHeader,
16
+ type DesignTokens,
14
17
  } from "@umituz/react-native-design-system";
15
18
  import type { TextInputScreenProps } from "./TextInputScreen.types";
16
19
 
@@ -46,64 +49,63 @@ export const TextInputScreen: React.FC<TextInputScreenProps> = ({
46
49
  setText(example);
47
50
  }, []);
48
51
 
49
- return (
50
- <View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
51
- {/* Header with Back on left, Continue on right */}
52
- <View style={[styles.header, { paddingHorizontal: tokens.spacing.md }]}>
53
- <TouchableOpacity onPress={onBack} style={styles.backButton}>
54
- <AtomicIcon name="chevron-left" size="md" color="textPrimary" />
55
- </TouchableOpacity>
52
+ const styles = useMemo(() => createStyles(tokens), [tokens]);
56
53
 
57
- <TouchableOpacity
58
- onPress={handleContinue}
59
- disabled={!canContinue}
60
- style={[
61
- styles.continueButton,
62
- {
63
- backgroundColor: canContinue ? tokens.colors.primary : tokens.colors.surfaceSecondary,
64
- borderRadius: tokens.radius.md,
65
- },
66
- ]}
67
- >
68
- <AtomicText
69
- type="labelLarge"
70
- style={{
71
- color: canContinue ? tokens.colors.textInverse : tokens.colors.textSecondary,
72
- fontWeight: "600",
73
- }}
54
+ return (
55
+ <View style={{ flex: 1, backgroundColor: tokens.colors.backgroundPrimary }}>
56
+ <NavigationHeader
57
+ title=""
58
+ onBackPress={onBack}
59
+ rightElement={
60
+ <TouchableOpacity
61
+ onPress={handleContinue}
62
+ activeOpacity={0.7}
63
+ disabled={!canContinue}
64
+ style={[
65
+ styles.continueButton,
66
+ {
67
+ backgroundColor: canContinue ? tokens.colors.primary : tokens.colors.surfaceVariant,
68
+ opacity: canContinue ? 1 : 0.5,
69
+ },
70
+ ]}
74
71
  >
75
- {translations.continueButton}
76
- </AtomicText>
77
- </TouchableOpacity>
78
- </View>
79
-
80
- <ScrollView
81
- style={styles.scrollView}
82
- contentContainerStyle={{ padding: tokens.spacing.md }}
83
- keyboardShouldPersistTaps="handled"
72
+ <AtomicText
73
+ type="bodyMedium"
74
+ style={[
75
+ styles.continueText,
76
+ { color: canContinue ? tokens.colors.onPrimary : tokens.colors.textSecondary },
77
+ ]}
78
+ >
79
+ {translations.continueButton}
80
+ </AtomicText>
81
+ <AtomicIcon
82
+ name="arrow-forward"
83
+ size="sm"
84
+ color={canContinue ? "onPrimary" : "textSecondary"}
85
+ />
86
+ </TouchableOpacity>
87
+ }
88
+ />
89
+ <ScreenLayout
90
+ scrollable={true}
91
+ edges={["left", "right"]}
92
+ hideScrollIndicator={true}
93
+ keyboardAvoiding={true}
94
+ contentContainerStyle={styles.scrollContent}
84
95
  >
85
96
  <AtomicText type="headlineMedium" color="textPrimary" style={styles.title}>
86
97
  {translations.title}
87
98
  </AtomicText>
88
99
 
89
100
  {translations.subtitle ? (
90
- <AtomicText type="bodyMedium" color="textSecondary" style={{ marginBottom: tokens.spacing.lg }}>
101
+ <AtomicText type="bodyMedium" color="textSecondary" style={styles.subtitle}>
91
102
  {translations.subtitle}
92
103
  </AtomicText>
93
104
  ) : null}
94
105
 
95
- <View
96
- style={[
97
- styles.inputContainer,
98
- {
99
- backgroundColor: tokens.colors.backgroundSecondary,
100
- borderRadius: tokens.borders.radius.md,
101
- borderColor: tokens.colors.border,
102
- },
103
- ]}
104
- >
106
+ <View style={styles.inputContainer}>
105
107
  <TextInput
106
- style={[styles.textInput, { color: tokens.colors.textPrimary, minHeight: config?.multiline ? 120 : 48 }]}
108
+ style={[styles.textInput, { minHeight: config?.multiline ? 120 : 48 }]}
107
109
  placeholder={translations.placeholder}
108
110
  placeholderTextColor={tokens.colors.textTertiary}
109
111
  value={text}
@@ -118,8 +120,8 @@ export const TextInputScreen: React.FC<TextInputScreenProps> = ({
118
120
  </View>
119
121
 
120
122
  {examplePrompts.length > 0 && translations.examplesTitle ? (
121
- <View style={{ marginTop: tokens.spacing.lg }}>
122
- <AtomicText type="labelLarge" color="textSecondary" style={{ marginBottom: tokens.spacing.sm }}>
123
+ <View style={styles.examplesSection}>
124
+ <AtomicText type="labelLarge" color="textSecondary" style={styles.examplesTitle}>
123
125
  {translations.examplesTitle}
124
126
  </AtomicText>
125
127
  {examplePrompts.slice(0, 4).map((example, index) => (
@@ -128,53 +130,64 @@ export const TextInputScreen: React.FC<TextInputScreenProps> = ({
128
130
  variant="outline"
129
131
  size="sm"
130
132
  onPress={() => handleExampleSelect(example)}
131
- style={{ marginBottom: tokens.spacing.xs }}
133
+ style={styles.exampleButton}
132
134
  >
133
135
  {example.length > 50 ? `${example.slice(0, 50)}...` : example}
134
136
  </AtomicButton>
135
137
  ))}
136
138
  </View>
137
139
  ) : null}
138
- </ScrollView>
140
+ </ScreenLayout>
139
141
  </View>
140
142
  );
141
143
  };
142
144
 
143
- const styles = StyleSheet.create({
144
- container: {
145
- flex: 1,
146
- },
147
- header: {
148
- flexDirection: "row",
149
- justifyContent: "space-between",
150
- alignItems: "center",
151
- paddingVertical: 12,
152
- },
153
- backButton: {
154
- flexDirection: "row",
155
- alignItems: "center",
156
- gap: 4,
157
- },
158
- continueButton: {
159
- paddingHorizontal: 16,
160
- paddingVertical: 8,
161
- },
162
- scrollView: {
163
- flex: 1,
164
- },
165
- title: {
166
- marginBottom: 8,
167
- },
168
- inputContainer: {
169
- borderWidth: 1,
170
- padding: 12,
171
- },
172
- textInput: {
173
- fontSize: 16,
174
- lineHeight: 22,
175
- },
176
- charCount: {
177
- textAlign: "right",
178
- marginTop: 8,
179
- },
180
- });
145
+ const createStyles = (tokens: DesignTokens) =>
146
+ StyleSheet.create({
147
+ scrollContent: {
148
+ paddingHorizontal: tokens.spacing.lg,
149
+ paddingBottom: 40,
150
+ },
151
+ title: {
152
+ marginBottom: tokens.spacing.sm,
153
+ },
154
+ subtitle: {
155
+ marginBottom: tokens.spacing.lg,
156
+ },
157
+ inputContainer: {
158
+ backgroundColor: tokens.colors.backgroundSecondary,
159
+ borderRadius: tokens.borders.radius.md,
160
+ borderWidth: 1,
161
+ borderColor: tokens.colors.border,
162
+ padding: tokens.spacing.md,
163
+ },
164
+ textInput: {
165
+ fontSize: 16,
166
+ lineHeight: 22,
167
+ color: tokens.colors.textPrimary,
168
+ },
169
+ charCount: {
170
+ textAlign: "right",
171
+ marginTop: tokens.spacing.sm,
172
+ },
173
+ examplesSection: {
174
+ marginTop: tokens.spacing.lg,
175
+ },
176
+ examplesTitle: {
177
+ marginBottom: tokens.spacing.sm,
178
+ },
179
+ exampleButton: {
180
+ marginBottom: tokens.spacing.xs,
181
+ },
182
+ continueButton: {
183
+ flexDirection: "row",
184
+ alignItems: "center",
185
+ paddingHorizontal: tokens.spacing.md,
186
+ paddingVertical: tokens.spacing.xs,
187
+ borderRadius: tokens.borders.radius.full,
188
+ },
189
+ continueText: {
190
+ fontWeight: "800",
191
+ marginRight: 4,
192
+ },
193
+ });
@@ -1,63 +0,0 @@
1
- /**
2
- * SelectionScreen Styles
3
- */
4
-
5
- import { StyleSheet } from "react-native";
6
-
7
- export const styles = StyleSheet.create({
8
- container: {
9
- flex: 1,
10
- },
11
- header: {
12
- flexDirection: "row",
13
- alignItems: "center",
14
- paddingVertical: 8,
15
- },
16
- backButtonContent: {
17
- flexDirection: "row",
18
- alignItems: "center",
19
- },
20
- backButtonText: {
21
- marginLeft: 4,
22
- },
23
- scrollView: {
24
- flex: 1,
25
- },
26
- title: {
27
- marginBottom: 8,
28
- },
29
- optionsGrid: {
30
- flexDirection: "row",
31
- flexWrap: "wrap",
32
- gap: 12,
33
- },
34
- optionCard: {
35
- flex: 1,
36
- minWidth: "45%",
37
- padding: 16,
38
- borderWidth: 2,
39
- alignItems: "center",
40
- position: "relative",
41
- },
42
- optionLabel: {
43
- marginTop: 8,
44
- textAlign: "center",
45
- },
46
- checkmark: {
47
- position: "absolute",
48
- top: 8,
49
- right: 8,
50
- width: 20,
51
- height: 20,
52
- borderRadius: 10,
53
- alignItems: "center",
54
- justifyContent: "center",
55
- },
56
- footer: {
57
- borderTopWidth: 1,
58
- borderTopColor: "rgba(0,0,0,0.1)",
59
- },
60
- continueButton: {
61
- width: "100%",
62
- },
63
- });