create-rn-folder-structure 1.0.2 → 1.0.3

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.
@@ -0,0 +1,290 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ function write(root, filePath, content) {
5
+ const fullPath = path.join(root, filePath);
6
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
7
+ fs.writeFileSync(fullPath, content);
8
+ }
9
+
10
+ module.exports = function generateIntermediateComponents(projectRoot) {
11
+ console.log("🧩 Creating Intermediate UI Components...");
12
+
13
+ const base = "src/shared/components";
14
+
15
+ // ---------------------------------------------------------
16
+ // Modal Component
17
+ // ---------------------------------------------------------
18
+ write(
19
+ projectRoot,
20
+ `${base}/AppModal.tsx`,
21
+ `
22
+ import React from "react";
23
+ import { Modal, View, StyleSheet, TouchableOpacity, Text } from "react-native";
24
+
25
+ interface Props {
26
+ visible: boolean;
27
+ onClose: () => void;
28
+ title?: string;
29
+ children?: any;
30
+ }
31
+
32
+ export default function AppModal({ visible, onClose, title, children }: Props) {
33
+ return (
34
+ <Modal visible={visible} transparent animationType="fade">
35
+ <View style={styles.overlay}>
36
+ <View style={styles.box}>
37
+ {title && <Text style={styles.title}>{title}</Text>}
38
+ {children}
39
+ <TouchableOpacity style={styles.closeBtn} onPress={onClose}>
40
+ <Text style={styles.closeText}>Close</Text>
41
+ </TouchableOpacity>
42
+ </View>
43
+ </View>
44
+ </Modal>
45
+ );
46
+ }
47
+
48
+ const styles = StyleSheet.create({
49
+ overlay: {
50
+ flex: 1,
51
+ backgroundColor: "rgba(0,0,0,0.4)",
52
+ justifyContent: "center",
53
+ alignItems: "center",
54
+ },
55
+ box: {
56
+ backgroundColor: "#fff",
57
+ width: "85%",
58
+ padding: 20,
59
+ borderRadius: 10,
60
+ },
61
+ title: {
62
+ fontSize: 18,
63
+ fontWeight: "600",
64
+ marginBottom: 10,
65
+ },
66
+ closeBtn: {
67
+ marginTop: 10,
68
+ backgroundColor: "#007AFF",
69
+ paddingVertical: 10,
70
+ borderRadius: 6,
71
+ },
72
+ closeText: {
73
+ textAlign: "center",
74
+ color: "#fff",
75
+ fontWeight: "600",
76
+ },
77
+ });
78
+ `
79
+ );
80
+
81
+ // ---------------------------------------------------------
82
+ // Dropdown (simple custom)
83
+ // ---------------------------------------------------------
84
+ write(
85
+ projectRoot,
86
+ `${base}/Dropdown.tsx`,
87
+ `
88
+ import React, { useState } from "react";
89
+ import {
90
+ View,
91
+ Text,
92
+ TouchableOpacity,
93
+ StyleSheet,
94
+ FlatList,
95
+ } from "react-native";
96
+
97
+ interface Item {
98
+ label: string;
99
+ value: any;
100
+ }
101
+
102
+ interface Props {
103
+ data: Item[];
104
+ onSelect: (value: any) => void;
105
+ placeholder?: string;
106
+ }
107
+
108
+ export default function Dropdown({ data, onSelect, placeholder }: Props) {
109
+ const [open, setOpen] = useState(false);
110
+ const [selected, setSelected] = useState("");
111
+
112
+ const handleSelect = (item: Item) => {
113
+ setSelected(item.label);
114
+ onSelect(item.value);
115
+ setOpen(false);
116
+ };
117
+
118
+ return (
119
+ <View>
120
+ <TouchableOpacity style={styles.box} onPress={() => setOpen(!open)}>
121
+ <Text style={styles.text}>
122
+ {selected || placeholder || "Select"}
123
+ </Text>
124
+ </TouchableOpacity>
125
+
126
+ {open && (
127
+ <View style={styles.dropdown}>
128
+ <FlatList
129
+ data={data}
130
+ keyExtractor={(item) => item.value.toString()}
131
+ renderItem={({ item }) => (
132
+ <TouchableOpacity
133
+ style={styles.item}
134
+ onPress={() => handleSelect(item)}
135
+ >
136
+ <Text>{item.label}</Text>
137
+ </TouchableOpacity>
138
+ )}
139
+ />
140
+ </View>
141
+ )}
142
+ </View>
143
+ );
144
+ }
145
+
146
+ const styles = StyleSheet.create({
147
+ box: {
148
+ borderWidth: 1,
149
+ borderColor: "#ccc",
150
+ padding: 12,
151
+ borderRadius: 8,
152
+ marginVertical: 6,
153
+ },
154
+ text: { fontSize: 16 },
155
+ dropdown: {
156
+ backgroundColor: "#fff",
157
+ borderWidth: 1,
158
+ borderColor: "#ccc",
159
+ marginTop: 4,
160
+ borderRadius: 8,
161
+ maxHeight: 160,
162
+ },
163
+ item: {
164
+ padding: 12,
165
+ borderBottomWidth: 1,
166
+ borderBottomColor: "#eee",
167
+ },
168
+ });
169
+ `
170
+ );
171
+
172
+ // ---------------------------------------------------------
173
+ // SearchBar
174
+ // ---------------------------------------------------------
175
+ write(
176
+ projectRoot,
177
+ `${base}/SearchBar.tsx`,
178
+ `
179
+ import React from "react";
180
+ import { View, TextInput, StyleSheet } from "react-native";
181
+
182
+ export default function SearchBar({ value, onChangeText }: any) {
183
+ return (
184
+ <View style={styles.box}>
185
+ <TextInput
186
+ value={value}
187
+ onChangeText={onChangeText}
188
+ placeholder="Search..."
189
+ style={styles.input}
190
+ />
191
+ </View>
192
+ );
193
+ }
194
+
195
+ const styles = StyleSheet.create({
196
+ box: {
197
+ borderWidth: 1,
198
+ borderColor: "#ccc",
199
+ paddingHorizontal: 12,
200
+ paddingVertical: 6,
201
+ borderRadius: 8,
202
+ marginVertical: 6,
203
+ },
204
+ input: {
205
+ fontSize: 16,
206
+ },
207
+ });
208
+ `
209
+ );
210
+
211
+ // ---------------------------------------------------------
212
+ // FlatListCard
213
+ // ---------------------------------------------------------
214
+ write(
215
+ projectRoot,
216
+ `${base}/FlatListCard.tsx`,
217
+ `
218
+ import React from "react";
219
+ import { View, Text, StyleSheet, TouchableOpacity } from "react-native";
220
+
221
+ interface Props {
222
+ title: string;
223
+ subtitle?: string;
224
+ onPress?: () => void;
225
+ }
226
+
227
+ export default function FlatListCard({ title, subtitle, onPress }: Props) {
228
+ return (
229
+ <TouchableOpacity style={styles.card} onPress={onPress}>
230
+ <View>
231
+ <Text style={styles.title}>{title}</Text>
232
+ {subtitle && <Text style={styles.sub}>{subtitle}</Text>}
233
+ </View>
234
+ </TouchableOpacity>
235
+ );
236
+ }
237
+
238
+ const styles = StyleSheet.create({
239
+ card: {
240
+ padding: 15,
241
+ backgroundColor: "#fff",
242
+ marginVertical: 6,
243
+ borderRadius: 8,
244
+ elevation: 2,
245
+ },
246
+ title: { fontSize: 16, fontWeight: "600" },
247
+ sub: { color: "#666", marginTop: 4 },
248
+ });
249
+ `
250
+ );
251
+
252
+ // ---------------------------------------------------------
253
+ // AlertMessage
254
+ // ---------------------------------------------------------
255
+ write(
256
+ projectRoot,
257
+ `${base}/AlertMessage.tsx`,
258
+ `
259
+ import React from "react";
260
+ import { View, Text, StyleSheet } from "react-native";
261
+
262
+ interface Props {
263
+ type?: "success" | "error" | "info";
264
+ message: string;
265
+ }
266
+
267
+ export default function AlertMessage({ type = "info", message }: Props) {
268
+ return (
269
+ <View style={[styles.box, styles[type]]}>
270
+ <Text style={styles.text}>{message}</Text>
271
+ </View>
272
+ );
273
+ }
274
+
275
+ const styles = StyleSheet.create({
276
+ box: {
277
+ padding: 12,
278
+ borderRadius: 8,
279
+ marginVertical: 6,
280
+ },
281
+ text: { color: "#fff", fontWeight: "600" },
282
+ success: { backgroundColor: "green" },
283
+ error: { backgroundColor: "red" },
284
+ info: { backgroundColor: "blue" },
285
+ });
286
+ `
287
+ );
288
+
289
+ console.log("✅ Intermediate Components Created!");
290
+ };
@@ -0,0 +1,181 @@
1
+ const fs = require("fs");
2
+ const path = require("path");
3
+
4
+ function write(root, filePath, content) {
5
+ const fullPath = path.join(root, filePath);
6
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
7
+ fs.writeFileSync(fullPath, content);
8
+ }
9
+
10
+ module.exports = function generateUploadComponents(projectRoot) {
11
+ console.log("📤 Creating Upload Components...");
12
+
13
+ const base = "src/shared/components";
14
+
15
+ // ---------------------------------------------------------
16
+ // 📄 File Upload
17
+ // ---------------------------------------------------------
18
+ write(
19
+ projectRoot,
20
+ `${base}/FileUpload.tsx`,
21
+ `
22
+ import React, { useState } from "react";
23
+ import { View, Text, TouchableOpacity, StyleSheet } from "react-native";
24
+ import DocumentPicker from "react-native-document-picker";
25
+
26
+ export default function FileUpload({ onSelect }: { onSelect: (file: any) => void }) {
27
+ const [fileName, setFileName] = useState("");
28
+
29
+ const pickFile = async () => {
30
+ try {
31
+ const res = await DocumentPicker.pickSingle({
32
+ type: [DocumentPicker.types.allFiles],
33
+ });
34
+ setFileName(res.name);
35
+ onSelect(res);
36
+ } catch (err) {
37
+ if (!DocumentPicker.isCancel(err)) console.log(err);
38
+ }
39
+ };
40
+
41
+ return (
42
+ <View>
43
+ <TouchableOpacity style={styles.btn} onPress={pickFile}>
44
+ <Text style={styles.btnText}>Select File</Text>
45
+ </TouchableOpacity>
46
+ {fileName ? <Text style={styles.label}>📄 {fileName}</Text> : null}
47
+ </View>
48
+ );
49
+ }
50
+
51
+ const styles = StyleSheet.create({
52
+ btn: {
53
+ backgroundColor: "#007AFF",
54
+ padding: 10,
55
+ borderRadius: 6,
56
+ alignItems: "center",
57
+ },
58
+ btnText: { color: "#fff", fontWeight: "600" },
59
+ label: { marginTop: 8, fontSize: 14 },
60
+ });
61
+ `
62
+ );
63
+
64
+ // ---------------------------------------------------------
65
+ // 🖼 Image Upload
66
+ // ---------------------------------------------------------
67
+ write(
68
+ projectRoot,
69
+ `${base}/ImageUpload.tsx`,
70
+ `
71
+ import React, { useState } from "react";
72
+ import { View, Text, Image, TouchableOpacity, StyleSheet } from "react-native";
73
+ import { launchImageLibrary } from "react-native-image-picker";
74
+
75
+ export default function ImageUpload({
76
+ onSelect,
77
+ }: {
78
+ onSelect: (file: any) => void;
79
+ }) {
80
+ const [image, setImage] = useState("");
81
+
82
+ const pickImage = () => {
83
+ launchImageLibrary({ mediaType: "photo" }, (res) => {
84
+ if (res.assets && res.assets.length > 0) {
85
+ const asset = res.assets[0];
86
+ setImage(asset.uri || "");
87
+ onSelect(asset);
88
+ }
89
+ });
90
+ };
91
+
92
+ return (
93
+ <View>
94
+ <TouchableOpacity style={styles.btn} onPress={pickImage}>
95
+ <Text style={styles.btnText}>Select Image</Text>
96
+ </TouchableOpacity>
97
+
98
+ {image ? <Image source={{ uri: image }} style={styles.preview} /> : null}
99
+ </View>
100
+ );
101
+ }
102
+
103
+ const styles = StyleSheet.create({
104
+ btn: {
105
+ backgroundColor: "#007AFF",
106
+ padding: 10,
107
+ borderRadius: 6,
108
+ alignItems: "center",
109
+ },
110
+ btnText: { color: "#fff", fontWeight: "600" },
111
+ preview: {
112
+ width: 120,
113
+ height: 120,
114
+ borderRadius: 8,
115
+ marginTop: 10,
116
+ },
117
+ });
118
+ `
119
+ );
120
+
121
+ // ---------------------------------------------------------
122
+ // 🎥 Video Upload
123
+ // ---------------------------------------------------------
124
+ write(
125
+ projectRoot,
126
+ `${base}/VideoUpload.tsx`,
127
+ `
128
+ import React, { useState } from "react";
129
+ import { View, Text, TouchableOpacity, StyleSheet, Image } from "react-native";
130
+ import { launchImageLibrary } from "react-native-image-picker";
131
+
132
+ export default function VideoUpload({
133
+ onSelect,
134
+ }: {
135
+ onSelect: (file: any) => void;
136
+ }) {
137
+ const [thumbnail, setThumbnail] = useState("");
138
+
139
+ const pickVideo = () => {
140
+ launchImageLibrary({ mediaType: "video" }, (res) => {
141
+ if (res.assets && res.assets.length > 0) {
142
+ const asset = res.assets[0];
143
+ setThumbnail(asset.uri || "");
144
+ onSelect(asset);
145
+ }
146
+ });
147
+ };
148
+
149
+ return (
150
+ <View>
151
+ <TouchableOpacity style={styles.btn} onPress={pickVideo}>
152
+ <Text style={styles.btnText}>Select Video</Text>
153
+ </TouchableOpacity>
154
+
155
+ {thumbnail ? (
156
+ <Image source={{ uri: thumbnail }} style={styles.thumbnail} />
157
+ ) : null}
158
+ </View>
159
+ );
160
+ }
161
+
162
+ const styles = StyleSheet.create({
163
+ btn: {
164
+ backgroundColor: "#007AFF",
165
+ padding: 10,
166
+ borderRadius: 6,
167
+ alignItems: "center",
168
+ },
169
+ btnText: { color: "#fff", fontWeight: "600" },
170
+ thumbnail: {
171
+ width: 140,
172
+ height: 100,
173
+ borderRadius: 8,
174
+ marginTop: 10,
175
+ },
176
+ });
177
+ `
178
+ );
179
+
180
+ console.log("✅ Upload Components Created!");
181
+ };