react-native-form-controls 1.0.0 → 1.0.2
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 +9 -16
- package/lib/Input.d.ts +1 -2
- package/lib/Input.js +384 -122
- package/package.json +2 -9
package/README.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/react-native-form-controls)
|
|
4
4
|
|
|
5
|
-
A highly customizable input component for React Native
|
|
5
|
+
A highly customizable input component for React Native. **Date/time**: uses **react-native-date-picker** when installed (recommended); otherwise falls back to a built-in picker. **Autocomplete**: built-in Google Places (pass `googleApiKey`).
|
|
6
6
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
11
|
-
- **
|
|
9
|
+
- **Text, password, textarea**: Standard inputs
|
|
10
|
+
- **Date, time, datetime**: Uses **react-native-date-picker** when installed (best UX); otherwise built-in modal picker
|
|
11
|
+
- **Autocomplete**: Built-in Google Places search (pass `googleApiKey`; uses Places API)
|
|
12
12
|
- **Customizable styles**: container, label, input
|
|
13
13
|
- **Error handling**: error message and error border
|
|
14
14
|
- **Icons**: left and right icons with actions
|
|
@@ -16,7 +16,7 @@ A highly customizable input component for React Native that works in **any proje
|
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
19
|
-
**
|
|
19
|
+
**Required:** react-native
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
22
|
npm install react-native-form-controls
|
|
@@ -24,7 +24,7 @@ npm install react-native-form-controls
|
|
|
24
24
|
yarn add react-native-form-controls
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
**Optional
|
|
27
|
+
**Optional (recommended for date/time):** For the best date/time picker experience, install **react-native-date-picker**. The package will use it automatically when present; otherwise a built-in picker is used.
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
30
|
npm install react-native-date-picker
|
|
@@ -32,15 +32,8 @@ npm install react-native-date-picker
|
|
|
32
32
|
yarn add react-native-date-picker
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
**Optional – Google Places autocomplete** (for `type="autocomplete"`):
|
|
36
35
|
|
|
37
|
-
```bash
|
|
38
|
-
npm install react-native-google-places-autocomplete
|
|
39
|
-
# or
|
|
40
|
-
yarn add react-native-google-places-autocomplete
|
|
41
|
-
```
|
|
42
36
|
|
|
43
|
-
If you don’t install the optional packages, the component still works: text, password, and textarea work as usual; date/time and autocomplete show a fallback message asking you to install the corresponding package.
|
|
44
37
|
|
|
45
38
|
## Example app
|
|
46
39
|
|
|
@@ -66,13 +59,13 @@ import { Input, COLORS } from 'react-native-form-controls';
|
|
|
66
59
|
// Textarea
|
|
67
60
|
<Input type="textarea" label="Notes" placeholder="Enter notes" />
|
|
68
61
|
|
|
69
|
-
// Date (
|
|
62
|
+
// Date (built-in picker)
|
|
70
63
|
<Input type="date" label="Birth date" onChangeText={(iso) => setDate(iso)} />
|
|
71
64
|
|
|
72
|
-
// Time (
|
|
65
|
+
// Time (built-in picker)
|
|
73
66
|
<Input type="time" label="Time" onChangeText={(iso) => setTime(iso)} />
|
|
74
67
|
|
|
75
|
-
// Autocomplete (requires
|
|
68
|
+
// Autocomplete (built-in; requires googleApiKey – Google Places API key)
|
|
76
69
|
<Input
|
|
77
70
|
type="autocomplete"
|
|
78
71
|
label="Location"
|
package/lib/Input.d.ts
CHANGED
|
@@ -21,13 +21,12 @@ export declare const COLORS: {
|
|
|
21
21
|
interface InputProps extends TextInputProps {
|
|
22
22
|
type: 'text' | 'password' | 'date' | 'time' | 'datetime' | 'textarea' | 'autocomplete';
|
|
23
23
|
leftIcon?: ImageSourcePropType;
|
|
24
|
-
rightIcon?:
|
|
24
|
+
rightIcon?: ImageSourcePropType;
|
|
25
25
|
label?: string;
|
|
26
26
|
error?: string;
|
|
27
27
|
containerStyle?: StyleProp<ViewStyle>;
|
|
28
28
|
labelStyle?: StyleProp<TextStyle>;
|
|
29
29
|
inputStyle?: StyleProp<TextStyle>;
|
|
30
|
-
/** Required for type="autocomplete". Install react-native-google-places-autocomplete to use. */
|
|
31
30
|
googleApiKey?: string;
|
|
32
31
|
}
|
|
33
32
|
declare const Input: React.FC<InputProps>;
|
package/lib/Input.js
CHANGED
|
@@ -43,6 +43,42 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
43
43
|
return result;
|
|
44
44
|
};
|
|
45
45
|
})();
|
|
46
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
47
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
48
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
49
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
50
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
51
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
52
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
56
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
57
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
58
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
59
|
+
function step(op) {
|
|
60
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
61
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
62
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
63
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
64
|
+
switch (op[0]) {
|
|
65
|
+
case 0: case 1: t = op; break;
|
|
66
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
67
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
68
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
69
|
+
default:
|
|
70
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
71
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
72
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
73
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
74
|
+
if (t[2]) _.ops.pop();
|
|
75
|
+
_.trys.pop(); continue;
|
|
76
|
+
}
|
|
77
|
+
op = body.call(thisArg, _);
|
|
78
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
79
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
80
|
+
}
|
|
81
|
+
};
|
|
46
82
|
var __rest = (this && this.__rest) || function (s, e) {
|
|
47
83
|
var t = {};
|
|
48
84
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -54,35 +90,36 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
54
90
|
}
|
|
55
91
|
return t;
|
|
56
92
|
};
|
|
57
|
-
var _a;
|
|
58
93
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
59
94
|
exports.COLORS = void 0;
|
|
60
95
|
var react_1 = __importStar(require("react"));
|
|
61
96
|
var react_native_1 = require("react-native");
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
97
|
+
// On Android, require() returns a number but RCTImageView expects an object – convert it.
|
|
98
|
+
function getImageSource(source) {
|
|
99
|
+
if (typeof source === 'number') {
|
|
100
|
+
if (react_native_1.Platform.OS === 'android') {
|
|
101
|
+
var resolved = react_native_1.Image.resolveAssetSource(source);
|
|
102
|
+
if (resolved === null || resolved === void 0 ? void 0 : resolved.uri)
|
|
103
|
+
return { uri: resolved.uri, width: resolved.width, height: resolved.height };
|
|
104
|
+
}
|
|
105
|
+
return source;
|
|
106
|
+
}
|
|
107
|
+
return source;
|
|
70
108
|
}
|
|
109
|
+
// Prefer react-native-date-picker when installed (better native UX)
|
|
110
|
+
var RNDatePicker = null;
|
|
71
111
|
try {
|
|
72
|
-
|
|
73
|
-
GooglePlacesAutocomplete = (_a = GooglePlaces.GooglePlacesAutocomplete) !== null && _a !== void 0 ? _a : GooglePlaces.default;
|
|
112
|
+
RNDatePicker = require('react-native-date-picker').default;
|
|
74
113
|
}
|
|
75
|
-
catch (
|
|
76
|
-
//
|
|
114
|
+
catch (_a) {
|
|
115
|
+
// Use built-in picker when not installed
|
|
77
116
|
}
|
|
78
117
|
exports.COLORS = {
|
|
79
|
-
// text color
|
|
80
118
|
black: '#252F40',
|
|
81
119
|
white: '#FFFFFF',
|
|
82
|
-
background: '#
|
|
120
|
+
background: '#FFFFFF',
|
|
83
121
|
darkGray: '#A9A9A9',
|
|
84
122
|
lightGray: '#D3D3D3',
|
|
85
|
-
// base colors
|
|
86
123
|
primary: '#007bff',
|
|
87
124
|
secondary: '#627594',
|
|
88
125
|
success: '#28a745',
|
|
@@ -95,69 +132,16 @@ exports.COLORS = {
|
|
|
95
132
|
link: '#007BFF',
|
|
96
133
|
error: '#EB5757',
|
|
97
134
|
};
|
|
98
|
-
var
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
var
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
var getAddress = (0, react_1.useCallback)(function (details) {
|
|
109
|
-
var addressComponent = details === null || details === void 0 ? void 0 : details.address_components;
|
|
110
|
-
var address = {};
|
|
111
|
-
addressComponent === null || addressComponent === void 0 ? void 0 : addressComponent.forEach(function (item) {
|
|
112
|
-
var _a, _b, _c, _d;
|
|
113
|
-
if ((_a = item === null || item === void 0 ? void 0 : item.types) === null || _a === void 0 ? void 0 : _a.includes('locality')) {
|
|
114
|
-
address.city = item === null || item === void 0 ? void 0 : item.long_name;
|
|
115
|
-
}
|
|
116
|
-
if ((_b = item === null || item === void 0 ? void 0 : item.types) === null || _b === void 0 ? void 0 : _b.includes('country')) {
|
|
117
|
-
address.country = item === null || item === void 0 ? void 0 : item.long_name;
|
|
118
|
-
address.countryCode = item === null || item === void 0 ? void 0 : item.short_name;
|
|
119
|
-
}
|
|
120
|
-
if ((_c = item === null || item === void 0 ? void 0 : item.types) === null || _c === void 0 ? void 0 : _c.includes('postal_code')) {
|
|
121
|
-
address.pincode = item === null || item === void 0 ? void 0 : item.long_name;
|
|
122
|
-
}
|
|
123
|
-
if ((_d = item === null || item === void 0 ? void 0 : item.types) === null || _d === void 0 ? void 0 : _d.includes('administrative_area_level_1')) {
|
|
124
|
-
address.state = item === null || item === void 0 ? void 0 : item.long_name;
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
return address;
|
|
128
|
-
}, []);
|
|
129
|
-
var handlePlacePress = (0, react_1.useCallback)(function (data, details) {
|
|
130
|
-
var _a, _b, _c, _d;
|
|
131
|
-
if (props.onChangeText) {
|
|
132
|
-
var addressObj = {
|
|
133
|
-
addresstext: data.description,
|
|
134
|
-
latitude: (_b = (_a = details === null || details === void 0 ? void 0 : details.geometry) === null || _a === void 0 ? void 0 : _a.location) === null || _b === void 0 ? void 0 : _b.lat,
|
|
135
|
-
longitude: (_d = (_c = details === null || details === void 0 ? void 0 : details.geometry) === null || _c === void 0 ? void 0 : _c.location) === null || _d === void 0 ? void 0 : _d.lng,
|
|
136
|
-
location: getAddress(details),
|
|
137
|
-
};
|
|
138
|
-
props.onChangeText(addressObj);
|
|
139
|
-
}
|
|
140
|
-
}, [getAddress, props.onChangeText]);
|
|
141
|
-
if (!GooglePlacesAutocomplete) {
|
|
142
|
-
return (react_1.default.createElement(react_native_1.TextInput, { style: [styles.input, styles.inputContainer, inputStyle, error ? styles.errorBorder : {}], placeholder: "Install react-native-google-places-autocomplete for location search", placeholderTextColor: exports.COLORS.secondary, editable: false }));
|
|
143
|
-
}
|
|
144
|
-
if (!googleApiKey) {
|
|
145
|
-
return (react_1.default.createElement(react_native_1.TextInput, { style: [styles.input, styles.inputContainer, inputStyle, error ? styles.errorBorder : {}], placeholder: "Provide googleApiKey for location search", placeholderTextColor: exports.COLORS.secondary, editable: false }));
|
|
146
|
-
}
|
|
147
|
-
var PlacesComponent = GooglePlacesAutocomplete;
|
|
148
|
-
return (react_1.default.createElement(PlacesComponent, __assign({ placeholder: placeholder, fetchDetails: true, onPress: handlePlacePress, query: {
|
|
149
|
-
key: googleApiKey,
|
|
150
|
-
language: 'en',
|
|
151
|
-
}, textInputProps: {
|
|
152
|
-
placeholderTextColor: exports.COLORS.secondary,
|
|
153
|
-
}, styles: {
|
|
154
|
-
textInput: [
|
|
155
|
-
styles.inputContainer,
|
|
156
|
-
inputStyle,
|
|
157
|
-
error ? styles.errorBorder : {},
|
|
158
|
-
],
|
|
159
|
-
} }, props)));
|
|
160
|
-
};
|
|
135
|
+
var MONTHS = [
|
|
136
|
+
'January', 'February', 'March', 'April', 'May', 'June',
|
|
137
|
+
'July', 'August', 'September', 'October', 'November', 'December',
|
|
138
|
+
];
|
|
139
|
+
var PICKER_ITEM_HEIGHT = 36;
|
|
140
|
+
var PICKER_VISIBLE_ITEMS = 5;
|
|
141
|
+
var PICKER_COLUMN_HEIGHT = PICKER_ITEM_HEIGHT * PICKER_VISIBLE_ITEMS;
|
|
142
|
+
function getDaysInMonth(year, month) {
|
|
143
|
+
return new Date(year, month + 1, 0).getDate();
|
|
144
|
+
}
|
|
161
145
|
function parseDateValue(value) {
|
|
162
146
|
if (value === undefined || value === null || value === '')
|
|
163
147
|
return undefined;
|
|
@@ -173,6 +157,278 @@ function formatDateByType(date, type) {
|
|
|
173
157
|
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
|
174
158
|
return date.toLocaleString();
|
|
175
159
|
}
|
|
160
|
+
// Wheel column: same design as react-native-date-picker (scrollable, center highlight)
|
|
161
|
+
var PickerWheelColumn = function (_a) {
|
|
162
|
+
var items = _a.items, selectedIndex = _a.selectedIndex, onSelect = _a.onSelect, _b = _a.itemHeight, itemHeight = _b === void 0 ? PICKER_ITEM_HEIGHT : _b;
|
|
163
|
+
var scrollRef = (0, react_1.useRef)(null);
|
|
164
|
+
var padding = (PICKER_VISIBLE_ITEMS - 1) * 0.5 * itemHeight;
|
|
165
|
+
var centerOffset = padding + selectedIndex * itemHeight - (PICKER_COLUMN_HEIGHT - itemHeight) / 2;
|
|
166
|
+
(0, react_1.useEffect)(function () {
|
|
167
|
+
var timeoutId = null;
|
|
168
|
+
var task = react_native_1.InteractionManager.runAfterInteractions(function () {
|
|
169
|
+
timeoutId = setTimeout(function () {
|
|
170
|
+
var _a;
|
|
171
|
+
try {
|
|
172
|
+
(_a = scrollRef.current) === null || _a === void 0 ? void 0 : _a.scrollTo({
|
|
173
|
+
y: Math.max(0, centerOffset),
|
|
174
|
+
animated: false,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch (_) { }
|
|
178
|
+
}, 100);
|
|
179
|
+
});
|
|
180
|
+
return function () {
|
|
181
|
+
task.cancel();
|
|
182
|
+
if (timeoutId != null)
|
|
183
|
+
clearTimeout(timeoutId);
|
|
184
|
+
};
|
|
185
|
+
}, [selectedIndex, itemHeight, centerOffset]);
|
|
186
|
+
return (react_1.default.createElement(react_native_1.View, { style: pickerStyles.wheelColumn },
|
|
187
|
+
react_1.default.createElement(react_native_1.View, { style: [pickerStyles.wheelHighlight, { height: itemHeight }], pointerEvents: "none" }),
|
|
188
|
+
react_1.default.createElement(react_native_1.ScrollView, { ref: scrollRef, style: { height: PICKER_COLUMN_HEIGHT }, contentContainerStyle: { paddingVertical: padding }, showsVerticalScrollIndicator: false, snapToInterval: itemHeight, snapToAlignment: "center", decelerationRate: "fast", onMomentumScrollEnd: function (e) {
|
|
189
|
+
var y = e.nativeEvent.contentOffset.y + (PICKER_COLUMN_HEIGHT - itemHeight) / 2 - padding;
|
|
190
|
+
var i = Math.round(y / itemHeight);
|
|
191
|
+
if (i >= 0 && i < items.length)
|
|
192
|
+
onSelect(i);
|
|
193
|
+
} }, items.map(function (item, i) { return (react_1.default.createElement(react_native_1.Pressable, { key: i, style: [pickerStyles.wheelItem, { height: itemHeight }, i === selectedIndex && pickerStyles.wheelItemSelected], onPress: function () { return onSelect(i); } },
|
|
194
|
+
react_1.default.createElement(react_native_1.Text, { style: [pickerStyles.wheelItemText, i === selectedIndex && pickerStyles.wheelItemTextSelected] }, String(item)))); }))));
|
|
195
|
+
};
|
|
196
|
+
// Built-in date/time picker – same design as react-native-date-picker (header + wheel)
|
|
197
|
+
var BuiltInDateTimePicker = function (_a) {
|
|
198
|
+
var visible = _a.visible, mode = _a.mode, initialDate = _a.initialDate, onConfirm = _a.onConfirm, onCancel = _a.onCancel;
|
|
199
|
+
var _b = (0, react_1.useState)(initialDate), date = _b[0], setDate = _b[1];
|
|
200
|
+
var year = date.getFullYear();
|
|
201
|
+
var month = date.getMonth();
|
|
202
|
+
var day = date.getDate();
|
|
203
|
+
var hours = date.getHours();
|
|
204
|
+
var minutes = date.getMinutes();
|
|
205
|
+
(0, react_1.useEffect)(function () {
|
|
206
|
+
if (visible)
|
|
207
|
+
setDate(initialDate);
|
|
208
|
+
}, [visible, initialDate.getTime()]);
|
|
209
|
+
var years = Array.from({ length: 100 }, function (_, i) { return new Date().getFullYear() - 80 + i; });
|
|
210
|
+
var months = MONTHS;
|
|
211
|
+
var days = Array.from({ length: getDaysInMonth(year, month) }, function (_, i) { return i + 1; });
|
|
212
|
+
var hourItems = Array.from({ length: 24 }, function (_, i) { return i.toString().padStart(2, '0'); });
|
|
213
|
+
var minuteItems = Array.from({ length: 60 }, function (_, i) { return i.toString().padStart(2, '0'); });
|
|
214
|
+
var handleConfirm = function () {
|
|
215
|
+
var d = new Date(year, month, Math.min(day, getDaysInMonth(year, month)), hours, minutes);
|
|
216
|
+
onConfirm(d);
|
|
217
|
+
};
|
|
218
|
+
if (!visible)
|
|
219
|
+
return null;
|
|
220
|
+
return (react_1.default.createElement(react_native_1.Modal, { visible: true, transparent: true, animationType: "slide", onRequestClose: onCancel },
|
|
221
|
+
react_1.default.createElement(react_native_1.Pressable, { style: pickerStyles.overlay, onPress: onCancel },
|
|
222
|
+
react_1.default.createElement(react_native_1.Pressable, { style: pickerStyles.modal, onPress: function () { } },
|
|
223
|
+
react_1.default.createElement(react_native_1.View, { style: pickerStyles.modalContent, collapsable: false },
|
|
224
|
+
react_1.default.createElement(react_native_1.View, { style: pickerStyles.header },
|
|
225
|
+
react_1.default.createElement(react_native_1.Pressable, { onPress: onCancel, style: pickerStyles.headerBtn },
|
|
226
|
+
react_1.default.createElement(react_native_1.Text, { style: pickerStyles.headerCancel }, "Cancel")),
|
|
227
|
+
react_1.default.createElement(react_native_1.Text, { style: pickerStyles.headerTitle, numberOfLines: 1 }, mode === 'date' ? 'Date' : mode === 'time' ? 'Time' : 'Date & Time'),
|
|
228
|
+
react_1.default.createElement(react_native_1.Pressable, { onPress: handleConfirm, style: pickerStyles.headerBtn },
|
|
229
|
+
react_1.default.createElement(react_native_1.Text, { style: pickerStyles.headerConfirm }, "Confirm"))),
|
|
230
|
+
react_1.default.createElement(react_native_1.View, { style: pickerStyles.wheelRow },
|
|
231
|
+
(mode === 'date' || mode === 'datetime') && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
232
|
+
react_1.default.createElement(PickerWheelColumn, { items: months, selectedIndex: month, onSelect: function (i) { return setDate(new Date(year, i, Math.min(day, getDaysInMonth(year, i)), hours, minutes)); } }),
|
|
233
|
+
react_1.default.createElement(PickerWheelColumn, { items: days, selectedIndex: day - 1, onSelect: function (i) { return setDate(new Date(year, month, i + 1, hours, minutes)); } }),
|
|
234
|
+
react_1.default.createElement(PickerWheelColumn, { items: years, selectedIndex: years.indexOf(year), onSelect: function (i) { return setDate(new Date(years[i], month, Math.min(day, getDaysInMonth(years[i], month)), hours, minutes)); } }))),
|
|
235
|
+
(mode === 'time' || mode === 'datetime') && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
236
|
+
react_1.default.createElement(PickerWheelColumn, { items: hourItems, selectedIndex: hours, onSelect: function (i) { return setDate(new Date(year, month, day, i, minutes)); } }),
|
|
237
|
+
react_1.default.createElement(PickerWheelColumn, { items: minuteItems, selectedIndex: minutes, onSelect: function (i) { return setDate(new Date(year, month, day, hours, i)); } })))))))));
|
|
238
|
+
};
|
|
239
|
+
var pickerStyles = react_native_1.StyleSheet.create({
|
|
240
|
+
overlay: {
|
|
241
|
+
flex: 1,
|
|
242
|
+
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
243
|
+
justifyContent: 'flex-end',
|
|
244
|
+
},
|
|
245
|
+
modal: {
|
|
246
|
+
backgroundColor: exports.COLORS.white,
|
|
247
|
+
borderTopLeftRadius: 16,
|
|
248
|
+
borderTopRightRadius: 16,
|
|
249
|
+
width: '100%',
|
|
250
|
+
minHeight: Math.min(340, react_native_1.Dimensions.get('window').height * 0.45),
|
|
251
|
+
maxHeight: '65%',
|
|
252
|
+
},
|
|
253
|
+
modalContent: {},
|
|
254
|
+
header: {
|
|
255
|
+
flexDirection: 'row',
|
|
256
|
+
alignItems: 'center',
|
|
257
|
+
justifyContent: 'space-between',
|
|
258
|
+
paddingHorizontal: 16,
|
|
259
|
+
paddingVertical: 14,
|
|
260
|
+
borderBottomWidth: react_native_1.StyleSheet.hairlineWidth,
|
|
261
|
+
borderBottomColor: exports.COLORS.lightGray,
|
|
262
|
+
},
|
|
263
|
+
headerBtn: { minWidth: 70 },
|
|
264
|
+
headerCancel: { fontSize: 16, color: exports.COLORS.secondary },
|
|
265
|
+
headerTitle: { fontSize: 16, fontWeight: '600', color: exports.COLORS.black, flex: 1, textAlign: 'center' },
|
|
266
|
+
headerConfirm: { fontSize: 16, fontWeight: '600', color: exports.COLORS.primary, textAlign: 'right' },
|
|
267
|
+
wheelRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingVertical: 8 },
|
|
268
|
+
wheelColumn: { flex: 1, maxWidth: 100, height: PICKER_COLUMN_HEIGHT, justifyContent: 'center' },
|
|
269
|
+
wheelHighlight: {
|
|
270
|
+
position: 'absolute',
|
|
271
|
+
left: 8,
|
|
272
|
+
right: 8,
|
|
273
|
+
top: (PICKER_COLUMN_HEIGHT - PICKER_ITEM_HEIGHT) / 2,
|
|
274
|
+
backgroundColor: 'rgba(0,122,255,0.08)',
|
|
275
|
+
borderRadius: 8,
|
|
276
|
+
zIndex: 0,
|
|
277
|
+
},
|
|
278
|
+
wheelItem: {
|
|
279
|
+
justifyContent: 'center',
|
|
280
|
+
alignItems: 'center',
|
|
281
|
+
zIndex: 1,
|
|
282
|
+
},
|
|
283
|
+
wheelItemSelected: {},
|
|
284
|
+
wheelItemText: { fontSize: 18, color: exports.COLORS.darkGray },
|
|
285
|
+
wheelItemTextSelected: { fontSize: 20, fontWeight: '600', color: exports.COLORS.black },
|
|
286
|
+
});
|
|
287
|
+
// Built-in Google Places autocomplete (no external lib) – uses Places API
|
|
288
|
+
function useDebounce(value, delay) {
|
|
289
|
+
var _a = (0, react_1.useState)(value), debouncedValue = _a[0], setDebouncedValue = _a[1];
|
|
290
|
+
(0, react_1.useEffect)(function () {
|
|
291
|
+
var t = setTimeout(function () { return setDebouncedValue(value); }, delay);
|
|
292
|
+
return function () { return clearTimeout(t); };
|
|
293
|
+
}, [value, delay]);
|
|
294
|
+
return debouncedValue;
|
|
295
|
+
}
|
|
296
|
+
var AutocompleteInput = function (_a) {
|
|
297
|
+
var inputStyle = _a.inputStyle, error = _a.error, googleApiKey = _a.googleApiKey, _b = _a.placeholder, placeholder = _b === void 0 ? 'Search location' : _b, props = __rest(_a, ["inputStyle", "error", "googleApiKey", "placeholder"]);
|
|
298
|
+
var _c = (0, react_1.useState)(''), query = _c[0], setQuery = _c[1];
|
|
299
|
+
var _d = (0, react_1.useState)([]), predictions = _d[0], setPredictions = _d[1];
|
|
300
|
+
var _e = (0, react_1.useState)(false), loading = _e[0], setLoading = _e[1];
|
|
301
|
+
var _f = (0, react_1.useState)(false), listVisible = _f[0], setListVisible = _f[1];
|
|
302
|
+
var debouncedQuery = useDebounce(query, 300);
|
|
303
|
+
var fetchPredictions = (0, react_1.useCallback)(function (q) { return __awaiter(void 0, void 0, void 0, function () {
|
|
304
|
+
var url, res, data, _a;
|
|
305
|
+
return __generator(this, function (_b) {
|
|
306
|
+
switch (_b.label) {
|
|
307
|
+
case 0:
|
|
308
|
+
if (!googleApiKey || !q.trim()) {
|
|
309
|
+
setPredictions([]);
|
|
310
|
+
return [2 /*return*/];
|
|
311
|
+
}
|
|
312
|
+
setLoading(true);
|
|
313
|
+
_b.label = 1;
|
|
314
|
+
case 1:
|
|
315
|
+
_b.trys.push([1, 4, 5, 6]);
|
|
316
|
+
url = "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=".concat(encodeURIComponent(q), "&key=").concat(googleApiKey);
|
|
317
|
+
return [4 /*yield*/, fetch(url)];
|
|
318
|
+
case 2:
|
|
319
|
+
res = _b.sent();
|
|
320
|
+
return [4 /*yield*/, res.json()];
|
|
321
|
+
case 3:
|
|
322
|
+
data = _b.sent();
|
|
323
|
+
if (data.predictions && Array.isArray(data.predictions)) {
|
|
324
|
+
setPredictions(data.predictions.map(function (p) { return ({ description: p.description, place_id: p.place_id }); }));
|
|
325
|
+
setListVisible(true);
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
setPredictions([]);
|
|
329
|
+
}
|
|
330
|
+
return [3 /*break*/, 6];
|
|
331
|
+
case 4:
|
|
332
|
+
_a = _b.sent();
|
|
333
|
+
setPredictions([]);
|
|
334
|
+
return [3 /*break*/, 6];
|
|
335
|
+
case 5:
|
|
336
|
+
setLoading(false);
|
|
337
|
+
return [7 /*endfinally*/];
|
|
338
|
+
case 6: return [2 /*return*/];
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}); }, [googleApiKey]);
|
|
342
|
+
(0, react_1.useEffect)(function () {
|
|
343
|
+
fetchPredictions(debouncedQuery);
|
|
344
|
+
}, [debouncedQuery, fetchPredictions]);
|
|
345
|
+
var getAddressFromDetails = (0, react_1.useCallback)(function (details) {
|
|
346
|
+
var _a;
|
|
347
|
+
var address = {};
|
|
348
|
+
var components = ((_a = details === null || details === void 0 ? void 0 : details.result) === null || _a === void 0 ? void 0 : _a.address_components) || [];
|
|
349
|
+
components.forEach(function (item) {
|
|
350
|
+
var _a, _b, _c, _d;
|
|
351
|
+
if ((_a = item.types) === null || _a === void 0 ? void 0 : _a.includes('locality'))
|
|
352
|
+
address.city = item.long_name;
|
|
353
|
+
if ((_b = item.types) === null || _b === void 0 ? void 0 : _b.includes('country')) {
|
|
354
|
+
address.country = item.long_name;
|
|
355
|
+
address.countryCode = item.short_name;
|
|
356
|
+
}
|
|
357
|
+
if ((_c = item.types) === null || _c === void 0 ? void 0 : _c.includes('postal_code'))
|
|
358
|
+
address.pincode = item.long_name;
|
|
359
|
+
if ((_d = item.types) === null || _d === void 0 ? void 0 : _d.includes('administrative_area_level_1'))
|
|
360
|
+
address.state = item.long_name;
|
|
361
|
+
});
|
|
362
|
+
return address;
|
|
363
|
+
}, []);
|
|
364
|
+
var onSelectPlace = (0, react_1.useCallback)(function (placeId, description) { return __awaiter(void 0, void 0, void 0, function () {
|
|
365
|
+
var url, res, data, result, loc, addressObj, _a;
|
|
366
|
+
var _b;
|
|
367
|
+
return __generator(this, function (_c) {
|
|
368
|
+
switch (_c.label) {
|
|
369
|
+
case 0:
|
|
370
|
+
setListVisible(false);
|
|
371
|
+
setQuery(description);
|
|
372
|
+
if (!props.onChangeText || !googleApiKey)
|
|
373
|
+
return [2 /*return*/];
|
|
374
|
+
setLoading(true);
|
|
375
|
+
_c.label = 1;
|
|
376
|
+
case 1:
|
|
377
|
+
_c.trys.push([1, 4, 5, 6]);
|
|
378
|
+
url = "https://maps.googleapis.com/maps/api/place/details/json?place_id=".concat(encodeURIComponent(placeId), "&key=").concat(googleApiKey);
|
|
379
|
+
return [4 /*yield*/, fetch(url)];
|
|
380
|
+
case 2:
|
|
381
|
+
res = _c.sent();
|
|
382
|
+
return [4 /*yield*/, res.json()];
|
|
383
|
+
case 3:
|
|
384
|
+
data = _c.sent();
|
|
385
|
+
result = data === null || data === void 0 ? void 0 : data.result;
|
|
386
|
+
loc = (_b = result === null || result === void 0 ? void 0 : result.geometry) === null || _b === void 0 ? void 0 : _b.location;
|
|
387
|
+
addressObj = {
|
|
388
|
+
addresstext: description,
|
|
389
|
+
latitude: loc === null || loc === void 0 ? void 0 : loc.lat,
|
|
390
|
+
longitude: loc === null || loc === void 0 ? void 0 : loc.lng,
|
|
391
|
+
location: getAddressFromDetails({ result: result }),
|
|
392
|
+
};
|
|
393
|
+
props.onChangeText(addressObj);
|
|
394
|
+
return [3 /*break*/, 6];
|
|
395
|
+
case 4:
|
|
396
|
+
_a = _c.sent();
|
|
397
|
+
props.onChangeText({ addresstext: description, latitude: undefined, longitude: undefined, location: {} });
|
|
398
|
+
return [3 /*break*/, 6];
|
|
399
|
+
case 5:
|
|
400
|
+
setLoading(false);
|
|
401
|
+
return [7 /*endfinally*/];
|
|
402
|
+
case 6: return [2 /*return*/];
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
}); }, [googleApiKey, props.onChangeText, getAddressFromDetails]);
|
|
406
|
+
if (!googleApiKey) {
|
|
407
|
+
return (react_1.default.createElement(react_native_1.TextInput, { style: [styles.input, styles.inputContainer, inputStyle, error ? styles.errorBorder : {}], placeholder: "Provide googleApiKey for location search", placeholderTextColor: exports.COLORS.secondary, editable: false }));
|
|
408
|
+
}
|
|
409
|
+
return (react_1.default.createElement(react_native_1.View, { style: styles.autocompleteWrap },
|
|
410
|
+
react_1.default.createElement(react_native_1.View, { style: [styles.inputContainer, error ? styles.errorBorder : {}] },
|
|
411
|
+
react_1.default.createElement(react_native_1.TextInput, { style: [styles.input, inputStyle], placeholder: placeholder, placeholderTextColor: exports.COLORS.secondary, value: query, onChangeText: function (t) {
|
|
412
|
+
setQuery(t);
|
|
413
|
+
if (!t.trim())
|
|
414
|
+
setListVisible(false);
|
|
415
|
+
}, onFocus: function () { return predictions.length > 0 && setListVisible(true); }, onBlur: function () { return setTimeout(function () { return setListVisible(false); }, 200); } }),
|
|
416
|
+
loading && react_1.default.createElement(react_native_1.ActivityIndicator, { size: "small", color: exports.COLORS.primary, style: styles.autocompleteLoader })),
|
|
417
|
+
listVisible && predictions.length > 0 && (react_1.default.createElement(react_native_1.View, { style: styles.predictionsList },
|
|
418
|
+
react_1.default.createElement(react_native_1.FlatList, { data: predictions, keyExtractor: function (item) { return item.place_id; }, keyboardShouldPersistTaps: "handled", renderItem: function (_a) {
|
|
419
|
+
var item = _a.item;
|
|
420
|
+
return (react_1.default.createElement(react_native_1.Pressable, { style: styles.predictionItem, onPress: function () { return onSelectPlace(item.place_id, item.description); } },
|
|
421
|
+
react_1.default.createElement(react_native_1.Text, { style: styles.predictionText, numberOfLines: 2 }, item.description)));
|
|
422
|
+
} })))));
|
|
423
|
+
};
|
|
424
|
+
var TextInputField = function (_a) {
|
|
425
|
+
var isPasswordVisible = _a.isPasswordVisible, inputStyle = _a.inputStyle, error = _a.error, type = _a.type, props = __rest(_a, ["isPasswordVisible", "inputStyle", "error", "type"]);
|
|
426
|
+
return (react_1.default.createElement(react_native_1.TextInput, __assign({ style: [styles.input, inputStyle, error ? styles.errorBorder : {}], secureTextEntry: type === 'password' && !isPasswordVisible, placeholderTextColor: exports.COLORS.secondary }, props)));
|
|
427
|
+
};
|
|
428
|
+
var TextareaInput = function (_a) {
|
|
429
|
+
var inputStyle = _a.inputStyle, error = _a.error, props = __rest(_a, ["inputStyle", "error"]);
|
|
430
|
+
return (react_1.default.createElement(react_native_1.TextInput, __assign({ style: [styles.textarea, inputStyle, error ? styles.errorBorder : {}], multiline: true, placeholderTextColor: exports.COLORS.secondary }, props)));
|
|
431
|
+
};
|
|
176
432
|
var Input = function (_a) {
|
|
177
433
|
var _b;
|
|
178
434
|
var type = _a.type, leftIcon = _a.leftIcon, rightIcon = _a.rightIcon, label = _a.label, error = _a.error, containerStyle = _a.containerStyle, labelStyle = _a.labelStyle, inputStyle = _a.inputStyle, valueProp = _a.value, props = __rest(_a, ["type", "leftIcon", "rightIcon", "label", "error", "containerStyle", "labelStyle", "inputStyle", "value"]);
|
|
@@ -199,55 +455,56 @@ var Input = function (_a) {
|
|
|
199
455
|
setIsDatePickerVisible(true);
|
|
200
456
|
}
|
|
201
457
|
};
|
|
458
|
+
var closeDatePicker = (0, react_1.useCallback)(function () {
|
|
459
|
+
setIsDatePickerVisible(false);
|
|
460
|
+
}, []);
|
|
461
|
+
var handleDateConfirm = (0, react_1.useCallback)(function (selectedDate) {
|
|
462
|
+
closeDatePicker();
|
|
463
|
+
// Defer date update so Modal can unmount first (avoids dispatchCommand on TextInput)
|
|
464
|
+
setTimeout(function () {
|
|
465
|
+
setDate(selectedDate);
|
|
466
|
+
if (props.onChangeText)
|
|
467
|
+
props.onChangeText(selectedDate.toISOString());
|
|
468
|
+
}, 200);
|
|
469
|
+
}, [props.onChangeText, closeDatePicker]);
|
|
202
470
|
var renderInput = function () {
|
|
203
471
|
switch (type) {
|
|
204
472
|
case 'textarea':
|
|
205
473
|
return (react_1.default.createElement(TextareaInput, __assign({ inputStyle: inputStyle, error: error, value: valueProp }, props)));
|
|
206
474
|
case 'autocomplete':
|
|
207
|
-
return (react_1.default.createElement(AutocompleteInput, __assign({ type:
|
|
475
|
+
return (react_1.default.createElement(AutocompleteInput, __assign({ type: "text", inputStyle: inputStyle, error: error, googleApiKey: props.googleApiKey }, props)));
|
|
208
476
|
case 'date':
|
|
209
477
|
case 'time':
|
|
210
478
|
case 'datetime':
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
479
|
+
return (react_1.default.createElement(react_native_1.Pressable, { onPress: function () { return setIsDatePickerVisible(true); }, style: styles.dateInputPressable },
|
|
480
|
+
react_1.default.createElement(react_native_1.Text, { style: [
|
|
481
|
+
styles.input,
|
|
482
|
+
styles.dateDisplayText,
|
|
483
|
+
inputStyle,
|
|
484
|
+
error ? styles.errorBorder : {},
|
|
485
|
+
!displayValue && { color: exports.COLORS.secondary },
|
|
486
|
+
], numberOfLines: 1 }, displayValue || props.placeholder || '')));
|
|
215
487
|
default:
|
|
216
488
|
return (react_1.default.createElement(TextInputField, __assign({ type: type, isPasswordVisible: isPasswordVisible, inputStyle: inputStyle, error: error, value: valueProp }, props)));
|
|
217
489
|
}
|
|
218
490
|
};
|
|
219
|
-
var renderDatePicker = function () {
|
|
220
|
-
if (!DatePicker || !isDateType || !isDatePickerVisible)
|
|
221
|
-
return null;
|
|
222
|
-
return (react_1.default.createElement(DatePicker, { modal: true, mode: type === 'datetime' ? 'datetime' : type, open: isDatePickerVisible, date: displayDate, onConfirm: function (selectedDate) {
|
|
223
|
-
setIsDatePickerVisible(false);
|
|
224
|
-
setDate(selectedDate);
|
|
225
|
-
if (props.onChangeText) {
|
|
226
|
-
props.onChangeText(selectedDate.toISOString());
|
|
227
|
-
}
|
|
228
|
-
}, onCancel: function () { return setIsDatePickerVisible(false); } }));
|
|
229
|
-
};
|
|
230
491
|
return (react_1.default.createElement(react_native_1.View, { style: [styles.container, containerStyle] },
|
|
231
492
|
label && react_1.default.createElement(react_native_1.Text, { style: [styles.label, labelStyle] }, label),
|
|
232
493
|
react_1.default.createElement(react_native_1.View, { style: [
|
|
233
494
|
type !== 'autocomplete' && styles.inputContainer,
|
|
234
495
|
error ? styles.errorBorder : {},
|
|
235
496
|
] },
|
|
236
|
-
leftIcon && react_1.default.createElement(react_native_1.Image, { source: leftIcon, style: styles.icon }),
|
|
497
|
+
leftIcon != null && (react_1.default.createElement(react_native_1.Image, { source: getImageSource(leftIcon), style: styles.icon, resizeMode: "contain" })),
|
|
237
498
|
renderInput(),
|
|
238
|
-
rightIcon && (react_1.default.createElement(react_native_1.
|
|
499
|
+
rightIcon != null && (react_1.default.createElement(react_native_1.Pressable, { onPress: handleIconPress },
|
|
500
|
+
react_1.default.createElement(react_native_1.Image, { source: getImageSource(rightIcon), style: styles.icon, resizeMode: "contain" })))),
|
|
239
501
|
error && react_1.default.createElement(react_native_1.Text, { style: styles.errorText }, error),
|
|
240
|
-
|
|
502
|
+
isDateType && RNDatePicker && (react_1.default.createElement(RNDatePicker, { modal: true, open: isDatePickerVisible, date: displayDate, mode: type === 'datetime' ? 'datetime' : type, onConfirm: function (d) { return handleDateConfirm(d); }, onCancel: closeDatePicker })),
|
|
503
|
+
isDateType && !RNDatePicker && (react_1.default.createElement(BuiltInDateTimePicker, { visible: isDatePickerVisible, mode: type === 'datetime' ? 'datetime' : type, initialDate: displayDate, onConfirm: handleDateConfirm, onCancel: closeDatePicker }))));
|
|
241
504
|
};
|
|
242
505
|
var styles = react_native_1.StyleSheet.create({
|
|
243
|
-
container: {
|
|
244
|
-
|
|
245
|
-
},
|
|
246
|
-
label: {
|
|
247
|
-
marginBottom: 4,
|
|
248
|
-
color: exports.COLORS.black,
|
|
249
|
-
fontSize: 16,
|
|
250
|
-
},
|
|
506
|
+
container: { marginVertical: 5 },
|
|
507
|
+
label: { marginBottom: 4, color: exports.COLORS.black, fontSize: 16 },
|
|
251
508
|
inputContainer: {
|
|
252
509
|
flexDirection: 'row',
|
|
253
510
|
alignItems: 'center',
|
|
@@ -259,12 +516,9 @@ var styles = react_native_1.StyleSheet.create({
|
|
|
259
516
|
backgroundColor: exports.COLORS.white,
|
|
260
517
|
minHeight: 40,
|
|
261
518
|
},
|
|
262
|
-
input: {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
padding: 0,
|
|
266
|
-
fontSize: 14,
|
|
267
|
-
},
|
|
519
|
+
input: { flex: 1, color: exports.COLORS.black, padding: 0, fontSize: 14 },
|
|
520
|
+
dateInputPressable: { flex: 1 },
|
|
521
|
+
dateDisplayText: { lineHeight: 20 },
|
|
268
522
|
textarea: {
|
|
269
523
|
flex: 1,
|
|
270
524
|
color: exports.COLORS.black,
|
|
@@ -273,17 +527,25 @@ var styles = react_native_1.StyleSheet.create({
|
|
|
273
527
|
textAlignVertical: 'top',
|
|
274
528
|
height: 100,
|
|
275
529
|
},
|
|
276
|
-
icon: {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
},
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
530
|
+
icon: { width: 24, height: 24 },
|
|
531
|
+
errorBorder: { borderColor: exports.COLORS.error },
|
|
532
|
+
errorText: { color: exports.COLORS.error, fontSize: 12, marginTop: 4 },
|
|
533
|
+
autocompleteWrap: { position: 'relative' },
|
|
534
|
+
autocompleteLoader: { position: 'absolute', right: 12, top: 10 },
|
|
535
|
+
predictionsList: {
|
|
536
|
+
position: 'absolute',
|
|
537
|
+
top: '100%',
|
|
538
|
+
left: 0,
|
|
539
|
+
right: 0,
|
|
540
|
+
backgroundColor: exports.COLORS.white,
|
|
541
|
+
borderWidth: 1,
|
|
542
|
+
borderColor: exports.COLORS.lightGray,
|
|
543
|
+
borderRadius: 8,
|
|
286
544
|
marginTop: 4,
|
|
545
|
+
maxHeight: 200,
|
|
546
|
+
zIndex: 1000,
|
|
287
547
|
},
|
|
548
|
+
predictionItem: { padding: 12, borderBottomWidth: 1, borderBottomColor: exports.COLORS.light },
|
|
549
|
+
predictionText: { fontSize: 14, color: exports.COLORS.black },
|
|
288
550
|
});
|
|
289
551
|
exports.default = Input;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-form-controls",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A highly customizable and versatile input component for React Native.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -25,20 +25,13 @@
|
|
|
25
25
|
],
|
|
26
26
|
"author": "Tarun Jain",
|
|
27
27
|
"license": "MIT",
|
|
28
|
-
"dependencies": {
|
|
29
|
-
"react-native": "^0.74.3"
|
|
30
|
-
},
|
|
31
28
|
"peerDependencies": {
|
|
32
29
|
"react-native": ">=0.70.0",
|
|
33
|
-
"react-native-date-picker": "^4.0.0"
|
|
34
|
-
"react-native-google-places-autocomplete": "^2.0.0"
|
|
30
|
+
"react-native-date-picker": "^4.0.0"
|
|
35
31
|
},
|
|
36
32
|
"peerDependenciesMeta": {
|
|
37
33
|
"react-native-date-picker": {
|
|
38
34
|
"optional": true
|
|
39
|
-
},
|
|
40
|
-
"react-native-google-places-autocomplete": {
|
|
41
|
-
"optional": true
|
|
42
35
|
}
|
|
43
36
|
},
|
|
44
37
|
"devDependencies": {
|