@hitesh0009/react-native-basic-form 1.1.3 → 1.1.5
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/README.md +186 -0
- package/dist/Form.js +25 -8
- package/dist/types.d.ts +20 -12
- package/package.json +1 -1
- package/src/Form.tsx +48 -18
- package/src/types.ts +30 -25
- package/README.MD +0 -26
package/README.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# react-native-basic-form
|
|
2
|
+
|
|
3
|
+
A lightweight, data-driven form renderer for React Native with fully controlled inputs and flexible styling.
|
|
4
|
+
|
|
5
|
+
This library helps you render simple forms using a declarative data structure, without managing internal state or enforcing opinions about validation or submission.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
* 📦 No native code (JS-only)
|
|
12
|
+
* 🎛 Fully controlled inputs
|
|
13
|
+
* 🧩 Data-driven rendering
|
|
14
|
+
* 🎨 Flexible style overrides
|
|
15
|
+
* 🧠 Unopinionated & extendable
|
|
16
|
+
* ⚡ Rendered using `FlatList` for performance
|
|
17
|
+
* 🧰 Pass-through props for `FlatList`, `TextInput`, `Text`, and `Image`
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 📦 Installation
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
npm install @hitesh0009/react-native-basic-form
|
|
25
|
+
# or
|
|
26
|
+
yarn add @hitesh0009/react-native-basic-form
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 🚀 Basic Usage
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
import { Form } from '@hitesh0009/react-native-basic-form';
|
|
35
|
+
|
|
36
|
+
const data = [
|
|
37
|
+
{
|
|
38
|
+
id: '1',
|
|
39
|
+
label: 'Full Name',
|
|
40
|
+
input: {
|
|
41
|
+
value: name,
|
|
42
|
+
onChangeText: setName,
|
|
43
|
+
placeholder: 'Enter your full name',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: '2',
|
|
48
|
+
label: 'Phone Number',
|
|
49
|
+
input: {
|
|
50
|
+
value: phone,
|
|
51
|
+
onChangeText: setPhone,
|
|
52
|
+
placeholder: 'Enter phone number',
|
|
53
|
+
keyboardType: 'numeric',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: '3',
|
|
58
|
+
button: {
|
|
59
|
+
label: 'Submit',
|
|
60
|
+
onPress: handleSubmit,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
<Form data={data} />;
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 🧩 Data Structure
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import type { KeyboardType } from 'react-native';
|
|
74
|
+
|
|
75
|
+
export type FormItem = {
|
|
76
|
+
id: string; // must be unique
|
|
77
|
+
label?: string;
|
|
78
|
+
input?: {
|
|
79
|
+
value: string;
|
|
80
|
+
onChangeText: (text: string) => void;
|
|
81
|
+
placeholder?: string;
|
|
82
|
+
keyboardType?: KeyboardType;
|
|
83
|
+
multiline?: boolean;
|
|
84
|
+
textAlignVertical?: 'auto' | 'top' | 'center' | 'bottom';
|
|
85
|
+
};
|
|
86
|
+
button?: {
|
|
87
|
+
label: string;
|
|
88
|
+
onPress: () => void;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 🧠 Header Support (Optional)
|
|
96
|
+
|
|
97
|
+
```tsx
|
|
98
|
+
<Form
|
|
99
|
+
headerIcon={Images.user}
|
|
100
|
+
headerText="Contact Information"
|
|
101
|
+
/>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 🧰 Props Reference
|
|
107
|
+
|
|
108
|
+
### Core Props
|
|
109
|
+
|
|
110
|
+
| Prop | Type | Description |
|
|
111
|
+
| ------------------ | ------------ | ----------------------------------------- |
|
|
112
|
+
| `data` | `FormItem[]` | Required form definition |
|
|
113
|
+
| `gap_bwt_keyValue` | `number` | Gap between label and input (default: 10) |
|
|
114
|
+
| `gap_bwt_keys` | `number` | Gap between form rows (default: 12) |
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
### Style Props
|
|
119
|
+
|
|
120
|
+
| Prop | Applies To |
|
|
121
|
+
| ---------------------- | ---------------- |
|
|
122
|
+
| `containerStyle` | Root container |
|
|
123
|
+
| `headerContainerStyle` | Header wrapper |
|
|
124
|
+
| `labelStyle` | Label text |
|
|
125
|
+
| `inputTextStyle` | TextInput |
|
|
126
|
+
| `buttonContainerStyle` | Button container |
|
|
127
|
+
| `buttonTextStyle` | Button text |
|
|
128
|
+
| `headerIconStyle` | Header image |
|
|
129
|
+
| `headerTextStyle` | Header text |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 🔌 Pass-through Props (Advanced)
|
|
134
|
+
|
|
135
|
+
### `flatlistProps`
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
<Form
|
|
139
|
+
flatlistProps={{
|
|
140
|
+
scrollEnabled: false,
|
|
141
|
+
showsVerticalScrollIndicator: false,
|
|
142
|
+
contentContainerStyle: { paddingBottom: 40 },
|
|
143
|
+
}}
|
|
144
|
+
/>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### `textInputProps`
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
<Form
|
|
151
|
+
textInputProps={{
|
|
152
|
+
autoCapitalize: 'none',
|
|
153
|
+
returnKeyType: 'done',
|
|
154
|
+
}}
|
|
155
|
+
/>
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## ⚠️ Important Notes
|
|
161
|
+
|
|
162
|
+
* This library does not manage state
|
|
163
|
+
* All inputs are fully controlled
|
|
164
|
+
* Validation and submission logic are your responsibility
|
|
165
|
+
* `id` must always be a string
|
|
166
|
+
* Avoid nesting inside `ScrollView` unless scrolling is disabled via `flatlistProps`
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## 🧠 Design Philosophy
|
|
171
|
+
|
|
172
|
+
Forms should be declarative, flexible, and boring.
|
|
173
|
+
|
|
174
|
+
This library intentionally avoids:
|
|
175
|
+
|
|
176
|
+
* Hidden internal state
|
|
177
|
+
* Opinionated validation rules
|
|
178
|
+
* Forced UX decisions
|
|
179
|
+
|
|
180
|
+
Instead, it provides:
|
|
181
|
+
|
|
182
|
+
* A predictable rendering layer
|
|
183
|
+
* Maximum control over behavior and styles
|
|
184
|
+
* Easy integration with your existing logic
|
|
185
|
+
|
|
186
|
+
|
package/dist/Form.js
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import { FlatList, StyleSheet, Text, TextInput, TouchableOpacity, View, } from "react-native";
|
|
2
|
-
export const Form = ({ data, gap_bwt_keyValue = 10, gap_bwt_keys = 12,
|
|
3
|
-
return (<View>
|
|
4
|
-
<
|
|
5
|
-
|
|
1
|
+
import { FlatList, Image, StyleSheet, Text, TextInput, TouchableOpacity, View, } from "react-native";
|
|
2
|
+
export const Form = ({ data, gap_bwt_keyValue = 10, gap_bwt_keys = 12, lableStyle, inputTextStyle, buttonContainerStyle, buttonTextStyle, headerIcon, headerIconStyle, headerTextStyle, imageProps, flatlistProps, textInputProps, textProp, headerText, headerContainerStyle, containerStyle, }) => {
|
|
3
|
+
return (<View style={[{ gap: 20 }, containerStyle]}>
|
|
4
|
+
<View style={[{ flexDirection: "row", gap: 10 }, headerContainerStyle]}>
|
|
5
|
+
{headerIcon && (<Image source={headerIcon} style={[styles.headericon, headerIconStyle]} {...imageProps}/>)}
|
|
6
|
+
{headerText && (<Text style={[styles.headertext, headerTextStyle]} {...textProp}>
|
|
7
|
+
{headerText}
|
|
8
|
+
</Text>)}
|
|
9
|
+
</View>
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
<FlatList {...flatlistProps} data={data} keyExtractor={(item) => item.id} ItemSeparatorComponent={() => <View style={{ height: gap_bwt_keys }}/>} renderItem={({ item }) => (<View style={{ gap: gap_bwt_keyValue }}>
|
|
12
|
+
{item.label && (<Text style={[styles.lable, lableStyle]}>{item.label}</Text>)}
|
|
8
13
|
|
|
9
|
-
{item.
|
|
10
|
-
|
|
14
|
+
{item.input && (<TextInput {...textInputProps} style={[styles.inputtext, inputTextStyle]} placeholder={item.input.placeholder} value={item.input.value} onChangeText={item.input.onChangeText} keyboardType={item.input.keyboardType}/>)}
|
|
15
|
+
|
|
16
|
+
{item.button && (<TouchableOpacity onPress={item.button.onPress} style={[styles.button_container, buttonContainerStyle]}>
|
|
17
|
+
<Text style={[styles.button_text, buttonTextStyle]}>
|
|
11
18
|
{item.button.label}
|
|
12
19
|
</Text>
|
|
13
20
|
</TouchableOpacity>)}
|
|
@@ -32,4 +39,14 @@ const styles = StyleSheet.create({
|
|
|
32
39
|
color: "#000",
|
|
33
40
|
fontSize: 14,
|
|
34
41
|
},
|
|
42
|
+
headericon: {
|
|
43
|
+
height: 30,
|
|
44
|
+
width: 30,
|
|
45
|
+
resizeMode: "contain",
|
|
46
|
+
},
|
|
47
|
+
headertext: {
|
|
48
|
+
color: "#000",
|
|
49
|
+
fontSize: 18,
|
|
50
|
+
fontWeight: "400",
|
|
51
|
+
},
|
|
35
52
|
});
|
package/dist/types.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type { TextStyle, ViewStyle } from "react-native";
|
|
1
|
+
import type { FlatListProps, ImageProps, ImageSourcePropType, ImageStyle, TextInputProps, TextProps, TextStyle, ViewStyle } from "react-native";
|
|
2
2
|
export type FormInput = {
|
|
3
3
|
placeholder?: string;
|
|
4
4
|
value: string;
|
|
5
|
-
onChangeText:
|
|
6
|
-
multiline
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
onChangeText: TextInputProps["onChangeText"];
|
|
6
|
+
multiline?: TextInputProps["multiline"];
|
|
7
|
+
textAlignVertical?: TextInputProps["textAlignVertical"];
|
|
8
|
+
keyboardType?: TextInputProps["keyboardType"];
|
|
9
9
|
};
|
|
10
10
|
export type FormButton = {
|
|
11
11
|
label: string;
|
|
@@ -21,11 +21,19 @@ export type FormProps = {
|
|
|
21
21
|
data: FormItem[];
|
|
22
22
|
gap_bwt_keyValue?: number;
|
|
23
23
|
gap_bwt_keys?: number;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
24
|
+
lableStyle?: TextStyle;
|
|
25
|
+
inputTextStyle?: TextStyle;
|
|
26
|
+
buttonContainerStyle?: ViewStyle;
|
|
27
|
+
buttonTextStyle?: TextStyle;
|
|
28
|
+
headerIcon?: ImageSourcePropType | undefined;
|
|
29
|
+
headerIconStyle?: ImageStyle;
|
|
30
|
+
imageProps?: ImageProps;
|
|
31
|
+
numColumns?: number;
|
|
32
|
+
flatlistProps?: FlatListProps<FormItem>;
|
|
33
|
+
textProp?: TextProps;
|
|
34
|
+
headerText?: string | undefined;
|
|
35
|
+
headerTextStyle?: TextStyle;
|
|
36
|
+
headerContainerStyle?: ViewStyle;
|
|
37
|
+
containerStyle?: ViewStyle;
|
|
38
|
+
textInputProps?: TextInputProps;
|
|
31
39
|
};
|
package/package.json
CHANGED
package/src/Form.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FlatList,
|
|
3
|
+
Image,
|
|
3
4
|
StyleSheet,
|
|
4
5
|
Text,
|
|
5
6
|
TextInput,
|
|
@@ -12,47 +13,66 @@ export const Form: React.FC<FormProps> = ({
|
|
|
12
13
|
data,
|
|
13
14
|
gap_bwt_keyValue = 10,
|
|
14
15
|
gap_bwt_keys = 12,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
lableStyle,
|
|
17
|
+
inputTextStyle,
|
|
18
|
+
buttonContainerStyle,
|
|
19
|
+
buttonTextStyle,
|
|
20
|
+
headerIcon,
|
|
21
|
+
headerIconStyle,
|
|
22
|
+
headerTextStyle,
|
|
23
|
+
imageProps,
|
|
24
|
+
flatlistProps,
|
|
25
|
+
textInputProps,
|
|
26
|
+
textProp,
|
|
27
|
+
headerText,
|
|
28
|
+
headerContainerStyle,
|
|
29
|
+
containerStyle,
|
|
22
30
|
}) => {
|
|
23
31
|
return (
|
|
24
|
-
<View>
|
|
32
|
+
<View style={[{gap:20},containerStyle]}>
|
|
33
|
+
<View style={[{ flexDirection: "row",gap:10 }, headerContainerStyle]}>
|
|
34
|
+
{headerIcon && (
|
|
35
|
+
<Image
|
|
36
|
+
source={headerIcon}
|
|
37
|
+
style={[styles.headericon, headerIconStyle]}
|
|
38
|
+
{...imageProps}
|
|
39
|
+
/>
|
|
40
|
+
)}
|
|
41
|
+
{headerText && (
|
|
42
|
+
<Text style={[styles.headertext, headerTextStyle]} {...textProp}>
|
|
43
|
+
{headerText}
|
|
44
|
+
</Text>
|
|
45
|
+
)}
|
|
46
|
+
</View>
|
|
47
|
+
|
|
25
48
|
<FlatList<FormItem>
|
|
26
|
-
|
|
27
|
-
showsHorizontalScrollIndicator={showsHorizontalScrollIndicator}
|
|
49
|
+
{...flatlistProps}
|
|
28
50
|
data={data}
|
|
29
51
|
keyExtractor={(item) => item.id}
|
|
30
52
|
ItemSeparatorComponent={() => <View style={{ height: gap_bwt_keys }} />}
|
|
31
53
|
renderItem={({ item }) => (
|
|
32
54
|
<View style={{ gap: gap_bwt_keyValue }}>
|
|
33
55
|
{item.label && (
|
|
34
|
-
<Text style={[styles.lable,
|
|
56
|
+
<Text style={[styles.lable, lableStyle]}>{item.label}</Text>
|
|
35
57
|
)}
|
|
36
58
|
|
|
37
59
|
{item.input && (
|
|
38
60
|
<TextInput
|
|
39
|
-
|
|
61
|
+
{...textInputProps}
|
|
62
|
+
style={[styles.inputtext, inputTextStyle]}
|
|
40
63
|
placeholder={item.input.placeholder}
|
|
41
|
-
placeholderTextColor={placeholderTextColor}
|
|
42
|
-
multiline={item.input.multiline}
|
|
43
|
-
textAlignVertical={item.input.TextAlignVertical}
|
|
44
64
|
value={item.input.value}
|
|
45
65
|
onChangeText={item.input.onChangeText}
|
|
46
|
-
keyboardType={item.input.
|
|
66
|
+
keyboardType={item.input.keyboardType}
|
|
47
67
|
/>
|
|
48
68
|
)}
|
|
49
69
|
|
|
50
70
|
{item.button && (
|
|
51
71
|
<TouchableOpacity
|
|
52
72
|
onPress={item.button.onPress}
|
|
53
|
-
style={[styles.button_container,
|
|
73
|
+
style={[styles.button_container, buttonContainerStyle]}
|
|
54
74
|
>
|
|
55
|
-
<Text style={[styles.button_text,
|
|
75
|
+
<Text style={[styles.button_text, buttonTextStyle]}>
|
|
56
76
|
{item.button.label}
|
|
57
77
|
</Text>
|
|
58
78
|
</TouchableOpacity>
|
|
@@ -82,4 +102,14 @@ const styles = StyleSheet.create({
|
|
|
82
102
|
color: "#000",
|
|
83
103
|
fontSize: 14,
|
|
84
104
|
},
|
|
105
|
+
headericon: {
|
|
106
|
+
height: 30,
|
|
107
|
+
width: 30,
|
|
108
|
+
resizeMode: "contain",
|
|
109
|
+
},
|
|
110
|
+
headertext: {
|
|
111
|
+
color: "#000",
|
|
112
|
+
fontSize: 18,
|
|
113
|
+
fontWeight: "400",
|
|
114
|
+
},
|
|
85
115
|
});
|
package/src/types.ts
CHANGED
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
FlatListProps,
|
|
3
|
+
ImageProps,
|
|
4
|
+
ImageSourcePropType,
|
|
5
|
+
ImageStyle,
|
|
6
|
+
TextInputProps,
|
|
7
|
+
TextProps,
|
|
8
|
+
TextStyle,
|
|
9
|
+
ViewStyle,
|
|
10
|
+
} from "react-native";
|
|
2
11
|
|
|
3
12
|
export type FormInput = {
|
|
4
13
|
placeholder?: string;
|
|
5
14
|
value: string;
|
|
6
|
-
onChangeText:
|
|
7
|
-
multiline
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
| "default"
|
|
11
|
-
| "number-pad"
|
|
12
|
-
| "decimal-pad"
|
|
13
|
-
| "numeric"
|
|
14
|
-
| "email-address"
|
|
15
|
-
| "phone-pad"
|
|
16
|
-
| "url"
|
|
17
|
-
| "ascii-capable"
|
|
18
|
-
| "numbers-and-punctuation"
|
|
19
|
-
| "name-phone-pad"
|
|
20
|
-
| "twitter"
|
|
21
|
-
| "web-search"
|
|
22
|
-
| "visible-password";
|
|
15
|
+
onChangeText: TextInputProps["onChangeText"];
|
|
16
|
+
multiline?: TextInputProps["multiline"];
|
|
17
|
+
textAlignVertical?: TextInputProps["textAlignVertical"];
|
|
18
|
+
keyboardType?: TextInputProps["keyboardType"];
|
|
23
19
|
};
|
|
24
20
|
|
|
25
21
|
export type FormButton = {
|
|
@@ -40,13 +36,22 @@ export type FormProps = {
|
|
|
40
36
|
gap_bwt_keyValue?: number;
|
|
41
37
|
gap_bwt_keys?: number;
|
|
42
38
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
39
|
+
lableStyle?: TextStyle;
|
|
40
|
+
inputTextStyle?: TextStyle;
|
|
41
|
+
buttonContainerStyle?: ViewStyle;
|
|
42
|
+
buttonTextStyle?: TextStyle;
|
|
47
43
|
|
|
48
|
-
|
|
44
|
+
headerIcon?: ImageSourcePropType | undefined;
|
|
45
|
+
headerIconStyle?: ImageStyle;
|
|
46
|
+
imageProps?: ImageProps;
|
|
47
|
+
numColumns?: number;
|
|
48
|
+
flatlistProps?: FlatListProps<FormItem>;
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
textProp?: TextProps;
|
|
51
|
+
headerText?: string | undefined;
|
|
52
|
+
headerTextStyle?: TextStyle;
|
|
53
|
+
|
|
54
|
+
headerContainerStyle?: ViewStyle;
|
|
55
|
+
containerStyle?: ViewStyle;
|
|
56
|
+
textInputProps?: TextInputProps
|
|
52
57
|
};
|
package/README.MD
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# react-native-basic-form
|
|
2
|
-
|
|
3
|
-
A lightweight, data-driven form renderer for React Native with fully controlled inputs and flexible styling.
|
|
4
|
-
|
|
5
|
-
This library helps you render simple forms using a declarative data structure, without managing internal state or enforcing opinions about validation or submission.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## ✨ Features
|
|
10
|
-
|
|
11
|
-
- 📦 **JS-only** (no native code, no linking)
|
|
12
|
-
- 🎛 **Fully controlled inputs**
|
|
13
|
-
- 🧩 **Data-driven rendering**
|
|
14
|
-
- 🎨 **Style overrides supported**
|
|
15
|
-
- ⚡ Built on `FlatList` for performance
|
|
16
|
-
- 🧠 Unopinionated and easy to extend
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## 📦 Installation
|
|
21
|
-
|
|
22
|
-
```sh
|
|
23
|
-
npm install react-native-basic-form
|
|
24
|
-
or
|
|
25
|
-
yarn add react-native-basic-form
|
|
26
|
-
|