react-native-form-controls 1.0.0

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 ADDED
@@ -0,0 +1,122 @@
1
+ # react-native-form-controls
2
+
3
+ [![npm version](https://img.shields.io/npm/v/react-native-form-controls.svg)](https://www.npmjs.com/package/react-native-form-controls)
4
+
5
+ A highly customizable input component for React Native that works in **any project**. Use it for text, password, textarea out of the box; optionally add date/time picker and Google Places autocomplete by installing extra packages.
6
+
7
+ ## Features
8
+
9
+ - **Core types (no extra deps)**: text, password, textarea
10
+ - **Optional date/time**: Install `react-native-date-picker` for date, time, and datetime types
11
+ - **Optional autocomplete**: Install `react-native-google-places-autocomplete` and pass `googleApiKey` for location search
12
+ - **Customizable styles**: container, label, input
13
+ - **Error handling**: error message and error border
14
+ - **Icons**: left and right icons with actions
15
+ - **Controlled/uncontrolled**: Supports `value` and `onChangeText` for all types, including date/time
16
+
17
+ ## Installation
18
+
19
+ **Base (works in any project):**
20
+
21
+ ```bash
22
+ npm install react-native-form-controls
23
+ # or
24
+ yarn add react-native-form-controls
25
+ ```
26
+
27
+ **Optional – date/time picker** (for `type="date"`, `type="time"`, `type="datetime"`):
28
+
29
+ ```bash
30
+ npm install react-native-date-picker
31
+ # or
32
+ yarn add react-native-date-picker
33
+ ```
34
+
35
+ **Optional – Google Places autocomplete** (for `type="autocomplete"`):
36
+
37
+ ```bash
38
+ npm install react-native-google-places-autocomplete
39
+ # or
40
+ yarn add react-native-google-places-autocomplete
41
+ ```
42
+
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
+
45
+ ## Example app
46
+
47
+ A runnable example (Expo) is in the [`example/`](./example) folder:
48
+
49
+ ```bash
50
+ npm run build && cd example && npm install && npm start
51
+ ```
52
+
53
+ See [example/README.md](./example/README.md) for details.
54
+
55
+ ## Usage
56
+
57
+ ```tsx
58
+ import { Input, COLORS } from 'react-native-form-controls';
59
+
60
+ // Text
61
+ <Input type="text" label="Name" placeholder="Enter name" />
62
+
63
+ // Password
64
+ <Input type="password" label="Password" placeholder="Enter password" />
65
+
66
+ // Textarea
67
+ <Input type="textarea" label="Notes" placeholder="Enter notes" />
68
+
69
+ // Date (requires react-native-date-picker)
70
+ <Input type="date" label="Birth date" onChangeText={(iso) => setDate(iso)} />
71
+
72
+ // Time (requires react-native-date-picker)
73
+ <Input type="time" label="Time" onChangeText={(iso) => setTime(iso)} />
74
+
75
+ // Autocomplete (requires react-native-google-places-autocomplete + googleApiKey)
76
+ <Input
77
+ type="autocomplete"
78
+ label="Location"
79
+ googleApiKey="YOUR_GOOGLE_PLACES_API_KEY"
80
+ onChangeText={(place) => console.log(place)}
81
+ />
82
+ ```
83
+
84
+ Use `COLORS` from the package to match built-in theming (e.g. `labelStyle={{ color: COLORS.primary }}`).
85
+
86
+ ## Props
87
+
88
+ | Prop | Type | Description |
89
+ |------|------|-------------|
90
+ | `type` | `'text' \| 'password' \| 'date' \| 'time' \| 'datetime' \| 'textarea' \| 'autocomplete'` | Input type |
91
+ | `label` | `string` | Label above the input |
92
+ | `error` | `string` | Error message (shows below input and error border) |
93
+ | `googleApiKey` | `string` | **Required for `type="autocomplete"`**. Google Places API key. |
94
+ | `containerStyle` | `ViewStyle` | Container style |
95
+ | `labelStyle` | `TextStyle` | Label style |
96
+ | `inputStyle` | `TextStyle` | Input style |
97
+ | `leftIcon` | `ImageSourcePropType` | Left icon image source |
98
+ | `rightIcon` | `ReactNode` | Right icon (e.g. eye for password) |
99
+ | Plus all standard `TextInput` props: `value`, `onChangeText`, `placeholder`, etc. |
100
+
101
+ For date/time/datetime, `onChangeText` receives an ISO date string. For autocomplete, it receives an object with `addresstext`, `latitude`, `longitude`, `location` (e.g. `city`, `country`, `state`, `pincode`).
102
+
103
+ ## Publishing to npm
104
+
105
+ From the repository root:
106
+
107
+ ```bash
108
+ # 1. Build the library
109
+ npm run build
110
+
111
+ # 2. Log in to npm (one-time)
112
+ npm login
113
+
114
+ # 3. Publish
115
+ npm publish
116
+ ```
117
+
118
+ To publish a new version, update `version` in `package.json` (e.g. `1.1.1`) then run `npm publish` again. Use `npm version patch` to bump the version automatically.
119
+
120
+ ## License
121
+
122
+ MIT
package/lib/Input.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { ImageSourcePropType, TextInputProps, StyleProp, ViewStyle, TextStyle } from 'react-native';
3
+ export declare const COLORS: {
4
+ black: string;
5
+ white: string;
6
+ background: string;
7
+ darkGray: string;
8
+ lightGray: string;
9
+ primary: string;
10
+ secondary: string;
11
+ success: string;
12
+ tertiary: string;
13
+ danger: string;
14
+ warning: string;
15
+ info: string;
16
+ light: string;
17
+ dark: string;
18
+ link: string;
19
+ error: string;
20
+ };
21
+ interface InputProps extends TextInputProps {
22
+ type: 'text' | 'password' | 'date' | 'time' | 'datetime' | 'textarea' | 'autocomplete';
23
+ leftIcon?: ImageSourcePropType;
24
+ rightIcon?: React.ReactNode;
25
+ label?: string;
26
+ error?: string;
27
+ containerStyle?: StyleProp<ViewStyle>;
28
+ labelStyle?: StyleProp<TextStyle>;
29
+ inputStyle?: StyleProp<TextStyle>;
30
+ /** Required for type="autocomplete". Install react-native-google-places-autocomplete to use. */
31
+ googleApiKey?: string;
32
+ }
33
+ declare const Input: React.FC<InputProps>;
34
+ export default Input;
package/lib/Input.js ADDED
@@ -0,0 +1,289 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ var desc = Object.getOwnPropertyDescriptor(m, k);
16
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
17
+ desc = { enumerable: true, get: function() { return m[k]; } };
18
+ }
19
+ Object.defineProperty(o, k2, desc);
20
+ }) : (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ o[k2] = m[k];
23
+ }));
24
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
25
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
26
+ }) : function(o, v) {
27
+ o["default"] = v;
28
+ });
29
+ var __importStar = (this && this.__importStar) || (function () {
30
+ var ownKeys = function(o) {
31
+ ownKeys = Object.getOwnPropertyNames || function (o) {
32
+ var ar = [];
33
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
34
+ return ar;
35
+ };
36
+ return ownKeys(o);
37
+ };
38
+ return function (mod) {
39
+ if (mod && mod.__esModule) return mod;
40
+ var result = {};
41
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
42
+ __setModuleDefault(result, mod);
43
+ return result;
44
+ };
45
+ })();
46
+ var __rest = (this && this.__rest) || function (s, e) {
47
+ var t = {};
48
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
49
+ t[p] = s[p];
50
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
51
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
52
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
53
+ t[p[i]] = s[p[i]];
54
+ }
55
+ return t;
56
+ };
57
+ var _a;
58
+ Object.defineProperty(exports, "__esModule", { value: true });
59
+ exports.COLORS = void 0;
60
+ var react_1 = __importStar(require("react"));
61
+ var react_native_1 = require("react-native");
62
+ // Optional dependencies – only loaded when used; safe for projects that don't install them
63
+ var DatePicker = null;
64
+ var GooglePlacesAutocomplete = null;
65
+ try {
66
+ DatePicker = require('react-native-date-picker').default;
67
+ }
68
+ catch (_b) {
69
+ // react-native-date-picker not installed – date/time/datetime will show fallback
70
+ }
71
+ try {
72
+ var GooglePlaces = require('react-native-google-places-autocomplete');
73
+ GooglePlacesAutocomplete = (_a = GooglePlaces.GooglePlacesAutocomplete) !== null && _a !== void 0 ? _a : GooglePlaces.default;
74
+ }
75
+ catch (_c) {
76
+ // react-native-google-places-autocomplete not installed – autocomplete will show fallback
77
+ }
78
+ exports.COLORS = {
79
+ // text color
80
+ black: '#252F40',
81
+ white: '#FFFFFF',
82
+ background: '#FFFFF',
83
+ darkGray: '#A9A9A9',
84
+ lightGray: '#D3D3D3',
85
+ // base colors
86
+ primary: '#007bff',
87
+ secondary: '#627594',
88
+ success: '#28a745',
89
+ tertiary: '#E8AE4C',
90
+ danger: '#dc3545',
91
+ warning: '#FFC107',
92
+ info: '#17A2B8',
93
+ light: '#F8F9FA',
94
+ dark: '#343A40',
95
+ link: '#007BFF',
96
+ error: '#EB5757',
97
+ };
98
+ var TextInputField = function (_a) {
99
+ var isPasswordVisible = _a.isPasswordVisible, inputStyle = _a.inputStyle, error = _a.error, type = _a.type, props = __rest(_a, ["isPasswordVisible", "inputStyle", "error", "type"]);
100
+ 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)));
101
+ };
102
+ var TextareaInput = function (_a) {
103
+ var inputStyle = _a.inputStyle, error = _a.error, props = __rest(_a, ["inputStyle", "error"]);
104
+ return (react_1.default.createElement(react_native_1.TextInput, __assign({ style: [styles.textarea, inputStyle, error ? styles.errorBorder : {}], multiline: true, placeholderTextColor: exports.COLORS.secondary }, props)));
105
+ };
106
+ var AutocompleteInput = function (_a) {
107
+ var inputStyle = _a.inputStyle, error = _a.error, googleApiKey = _a.googleApiKey, _b = _a.placeholder, placeholder = _b === void 0 ? 'Search' : _b, props = __rest(_a, ["inputStyle", "error", "googleApiKey", "placeholder"]);
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
+ };
161
+ function parseDateValue(value) {
162
+ if (value === undefined || value === null || value === '')
163
+ return undefined;
164
+ if (value instanceof Date)
165
+ return value;
166
+ var parsed = new Date(value);
167
+ return isNaN(parsed.getTime()) ? undefined : parsed;
168
+ }
169
+ function formatDateByType(date, type) {
170
+ if (type === 'date')
171
+ return date.toLocaleDateString();
172
+ if (type === 'time')
173
+ return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
174
+ return date.toLocaleString();
175
+ }
176
+ var Input = function (_a) {
177
+ var _b;
178
+ 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"]);
179
+ var _c = (0, react_1.useState)(false), isPasswordVisible = _c[0], setIsPasswordVisible = _c[1];
180
+ var initialDate = parseDateValue(valueProp);
181
+ var _d = (0, react_1.useState)(initialDate), date = _d[0], setDate = _d[1];
182
+ var _e = (0, react_1.useState)(false), isDatePickerVisible = _e[0], setIsDatePickerVisible = _e[1];
183
+ var isDateType = type === 'date' || type === 'time' || type === 'datetime';
184
+ var controlledDate = isDateType ? parseDateValue(valueProp) : undefined;
185
+ (0, react_1.useEffect)(function () {
186
+ if (isDateType && controlledDate !== undefined) {
187
+ setDate(controlledDate);
188
+ }
189
+ }, [isDateType, valueProp]);
190
+ var displayDate = (_b = date !== null && date !== void 0 ? date : controlledDate) !== null && _b !== void 0 ? _b : new Date();
191
+ var displayValue = isDateType
192
+ ? (date ? formatDateByType(date, type) : valueProp !== null && valueProp !== void 0 ? valueProp : '')
193
+ : valueProp;
194
+ var handleIconPress = function () {
195
+ if (type === 'password') {
196
+ setIsPasswordVisible(!isPasswordVisible);
197
+ }
198
+ else if (isDateType) {
199
+ setIsDatePickerVisible(true);
200
+ }
201
+ };
202
+ var renderInput = function () {
203
+ switch (type) {
204
+ case 'textarea':
205
+ return (react_1.default.createElement(TextareaInput, __assign({ inputStyle: inputStyle, error: error, value: valueProp }, props)));
206
+ case 'autocomplete':
207
+ return (react_1.default.createElement(AutocompleteInput, __assign({ type: 'text', inputStyle: inputStyle, error: error, googleApiKey: props.googleApiKey }, props)));
208
+ case 'date':
209
+ case 'time':
210
+ case 'datetime':
211
+ if (!DatePicker) {
212
+ return (react_1.default.createElement(react_native_1.TextInput, { style: [styles.input, inputStyle, error ? styles.errorBorder : {}], placeholder: "Install react-native-date-picker for date/time selection", placeholderTextColor: exports.COLORS.secondary, editable: false }));
213
+ }
214
+ return (react_1.default.createElement(TextInputField, __assign({ type: type, value: displayValue, editable: false, inputStyle: inputStyle, error: error }, props)));
215
+ default:
216
+ return (react_1.default.createElement(TextInputField, __assign({ type: type, isPasswordVisible: isPasswordVisible, inputStyle: inputStyle, error: error, value: valueProp }, props)));
217
+ }
218
+ };
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
+ return (react_1.default.createElement(react_native_1.View, { style: [styles.container, containerStyle] },
231
+ label && react_1.default.createElement(react_native_1.Text, { style: [styles.label, labelStyle] }, label),
232
+ react_1.default.createElement(react_native_1.View, { style: [
233
+ type !== 'autocomplete' && styles.inputContainer,
234
+ error ? styles.errorBorder : {},
235
+ ] },
236
+ leftIcon && react_1.default.createElement(react_native_1.Image, { source: leftIcon, style: styles.icon }),
237
+ renderInput(),
238
+ rightIcon && (react_1.default.createElement(react_native_1.TouchableOpacity, { onPress: handleIconPress }, rightIcon))),
239
+ error && react_1.default.createElement(react_native_1.Text, { style: styles.errorText }, error),
240
+ renderDatePicker()));
241
+ };
242
+ var styles = react_native_1.StyleSheet.create({
243
+ container: {
244
+ marginVertical: 5,
245
+ },
246
+ label: {
247
+ marginBottom: 4,
248
+ color: exports.COLORS.black,
249
+ fontSize: 16,
250
+ },
251
+ inputContainer: {
252
+ flexDirection: 'row',
253
+ alignItems: 'center',
254
+ borderWidth: 1,
255
+ borderColor: exports.COLORS.secondary,
256
+ borderRadius: 8,
257
+ paddingVertical: 8,
258
+ paddingHorizontal: 12,
259
+ backgroundColor: exports.COLORS.white,
260
+ minHeight: 40,
261
+ },
262
+ input: {
263
+ flex: 1,
264
+ color: exports.COLORS.black,
265
+ padding: 0,
266
+ fontSize: 14,
267
+ },
268
+ textarea: {
269
+ flex: 1,
270
+ color: exports.COLORS.black,
271
+ padding: 0,
272
+ fontSize: 14,
273
+ textAlignVertical: 'top',
274
+ height: 100,
275
+ },
276
+ icon: {
277
+ width: 16,
278
+ height: 16,
279
+ },
280
+ errorBorder: {
281
+ borderColor: exports.COLORS.error,
282
+ },
283
+ errorText: {
284
+ color: exports.COLORS.error,
285
+ fontSize: 12,
286
+ marginTop: 4,
287
+ },
288
+ });
289
+ exports.default = Input;
package/lib/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export { default as Input, COLORS } from './Input';
package/lib/index.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.COLORS = exports.Input = void 0;
7
+ var Input_1 = require("./Input");
8
+ Object.defineProperty(exports, "Input", { enumerable: true, get: function () { return __importDefault(Input_1).default; } });
9
+ Object.defineProperty(exports, "COLORS", { enumerable: true, get: function () { return Input_1.COLORS; } });
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "react-native-form-controls",
3
+ "version": "1.0.0",
4
+ "description": "A highly customizable and versatile input component for React Native.",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "prepublishOnly": "npm run build"
10
+ },
11
+ "files": [
12
+ "lib",
13
+ "README.md"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/tarunj116/react-native-smart-input.git"
18
+ },
19
+ "keywords": [
20
+ "react-native",
21
+ "input",
22
+ "component",
23
+ "date-picker",
24
+ "google-places-autocomplete"
25
+ ],
26
+ "author": "Tarun Jain",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "react-native": "^0.74.3"
30
+ },
31
+ "peerDependencies": {
32
+ "react-native": ">=0.70.0",
33
+ "react-native-date-picker": "^4.0.0",
34
+ "react-native-google-places-autocomplete": "^2.0.0"
35
+ },
36
+ "peerDependenciesMeta": {
37
+ "react-native-date-picker": {
38
+ "optional": true
39
+ },
40
+ "react-native-google-places-autocomplete": {
41
+ "optional": true
42
+ }
43
+ },
44
+ "devDependencies": {
45
+ "@types/react": "^18.3.3",
46
+ "@types/react-native": "^0.73.0",
47
+ "typescript": "^5.5.4"
48
+ }
49
+ }