react-native-bottom-sheet-dropdown 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 +335 -0
- package/lib/BottomSheetDropdown.d.ts +4 -0
- package/lib/BottomSheetDropdown.js +54 -0
- package/lib/DropdownModal.d.ts +4 -0
- package/lib/DropdownModal.js +73 -0
- package/lib/icons/DownIcon.d.ts +5 -0
- package/lib/icons/DownIcon.js +14 -0
- package/lib/icons/TickIcon.d.ts +6 -0
- package/lib/icons/TickIcon.js +14 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +21 -0
- package/lib/types.d.ts +52 -0
- package/lib/types.js +2 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +6 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
# React Native Bottom Sheet Dropdown
|
|
2
|
+
|
|
3
|
+
A customizable dropdown component with bottom sheet UI for React Native applications. This component provides a smooth, native-feeling dropdown experience with modal presentation.
|
|
4
|
+
|
|
5
|
+
Demo
|
|
6
|
+
<table>
|
|
7
|
+
<tr>
|
|
8
|
+
<td align="center">
|
|
9
|
+
<img src="./demo/english-demo.gif" alt="English Demo" width="300" />
|
|
10
|
+
<br />
|
|
11
|
+
<b>English Version</b>
|
|
12
|
+
</td>
|
|
13
|
+
<td align="center">
|
|
14
|
+
<img src="./demo/arabic-demo.gif" alt="Arabic Demo" width="300" />
|
|
15
|
+
<br />
|
|
16
|
+
<b>Arabic Version (RTL Support)</b>
|
|
17
|
+
</td>
|
|
18
|
+
</tr>
|
|
19
|
+
</table>
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
- ✅ **Bottom Sheet Modal**: Elegant modal presentation from bottom of screen
|
|
23
|
+
- ✅ **Customizable Styling**: Full control over appearance and styling
|
|
24
|
+
- ✅ **RTL Support**: Right-to-left language support
|
|
25
|
+
- ✅ **TypeScript Support**: Full TypeScript definitions included
|
|
26
|
+
- ✅ **Responsive Design**: Uses responsive screen dimensions
|
|
27
|
+
- ✅ **Smooth Animations**: Built-in animations for modal presentation
|
|
28
|
+
- ✅ **Selected State**: Visual feedback for selected items
|
|
29
|
+
- ✅ **Accessibility**: Proper accessibility support
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install react-native-bottom-sheet-dropdown
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Dependencies
|
|
38
|
+
|
|
39
|
+
This package requires the following peer dependencies:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install react-native-modal react-native-responsive-screen react-native-svg
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
For iOS, you'll also need to run:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
cd ios && pod install
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Basic Usage
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import React, { useState } from 'react';
|
|
55
|
+
import { View } from 'react-native';
|
|
56
|
+
import { BottomSheetDropdown, DropdownItem } from 'react-native-bottom-sheet-dropdown';
|
|
57
|
+
|
|
58
|
+
const data: DropdownItem[] = [
|
|
59
|
+
{ label: 'Option 1', value: '1' },
|
|
60
|
+
{ label: 'Option 2', value: '2' },
|
|
61
|
+
{ label: 'Option 3', value: '3' },
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
const App = () => {
|
|
65
|
+
const [selectedOption, setSelectedOption] = useState<DropdownItem | undefined>();
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<View style={{ padding: 20 }}>
|
|
69
|
+
<BottomSheetDropdown
|
|
70
|
+
data={data}
|
|
71
|
+
onSelect={(item) => setSelectedOption(item)}
|
|
72
|
+
selectedOption={selectedOption}
|
|
73
|
+
placeholder="Choose an option"
|
|
74
|
+
title="Select Item"
|
|
75
|
+
dropdownModalProps={{
|
|
76
|
+
dropdownProps: {
|
|
77
|
+
dropdownTitle: 'Select Option',
|
|
78
|
+
closeTitle: 'Close'
|
|
79
|
+
}
|
|
80
|
+
}}
|
|
81
|
+
/>
|
|
82
|
+
</View>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default App;
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Props
|
|
90
|
+
|
|
91
|
+
### BottomSheetDropdown Props
|
|
92
|
+
|
|
93
|
+
| Prop | Type | Default | Description |
|
|
94
|
+
|------|------|---------|-------------|
|
|
95
|
+
| `data` | `DropdownItem[]` | **Required** | Array of dropdown items |
|
|
96
|
+
| `onSelect` | `(item: DropdownItem) => void` | **Required** | Callback when item is selected |
|
|
97
|
+
| `selectedOption` | `DropdownItem` | `undefined` | Currently selected item |
|
|
98
|
+
| `placeholder` | `string` | `"Select an option"` | Placeholder text |
|
|
99
|
+
| `title` | `string` | `""` | Title displayed above dropdown |
|
|
100
|
+
| `rtl` | `boolean` | `false` | Right-to-left layout support |
|
|
101
|
+
| `selectedValue` | `string \| number` | `undefined` | Alternative way to set selected value |
|
|
102
|
+
| `style` | `ViewStyle` | `undefined` | Container style |
|
|
103
|
+
| `dropdownStyle` | `ViewStyle` | `undefined` | Dropdown button style |
|
|
104
|
+
| `mainDropdownInput` | `ViewStyle` | `undefined` | Main dropdown input style |
|
|
105
|
+
| `titleStyle` | `TextStyle` | `undefined` | Title text style |
|
|
106
|
+
| `selectedValueStyle` | `TextStyle` | `undefined` | Selected value text style |
|
|
107
|
+
| `placeholderStyle` | `TextStyle` | `undefined` | Placeholder text style |
|
|
108
|
+
| `dropdownModalProps` | `DropdownModalProps` | **Required** | Modal configuration |
|
|
109
|
+
|
|
110
|
+
### DropdownItem
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
interface DropdownItem {
|
|
114
|
+
label: string;
|
|
115
|
+
value: string;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### DropdownModalProps
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
interface DropdownModalProps {
|
|
123
|
+
dropdownProps?: {
|
|
124
|
+
dropdownTitle: string;
|
|
125
|
+
closeTitle: string;
|
|
126
|
+
};
|
|
127
|
+
dropdownStyles?: {
|
|
128
|
+
dropdownTitleStyle?: TextStyle;
|
|
129
|
+
closeTitleStyle?: TextStyle;
|
|
130
|
+
optionValueText?: TextStyle;
|
|
131
|
+
selectedOptionText?: TextStyle;
|
|
132
|
+
optionContainerStyle?: ViewStyle;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Advanced Usage
|
|
138
|
+
|
|
139
|
+
### Custom Styling
|
|
140
|
+
|
|
141
|
+
```tsx
|
|
142
|
+
<BottomSheetDropdown
|
|
143
|
+
data={data}
|
|
144
|
+
onSelect={handleSelect}
|
|
145
|
+
selectedOption={selectedOption}
|
|
146
|
+
placeholder="Custom placeholder"
|
|
147
|
+
title="Custom Title"
|
|
148
|
+
titleStyle={{
|
|
149
|
+
fontSize: 18,
|
|
150
|
+
fontWeight: 'bold',
|
|
151
|
+
color: '#333'
|
|
152
|
+
}}
|
|
153
|
+
mainDropdownInput={{
|
|
154
|
+
backgroundColor: '#f5f5f5',
|
|
155
|
+
borderRadius: 12,
|
|
156
|
+
borderWidth: 2,
|
|
157
|
+
borderColor: '#ddd'
|
|
158
|
+
}}
|
|
159
|
+
selectedValueStyle={{
|
|
160
|
+
color: '#007AFF',
|
|
161
|
+
fontWeight: '600'
|
|
162
|
+
}}
|
|
163
|
+
placeholderStyle={{
|
|
164
|
+
color: '#999',
|
|
165
|
+
fontStyle: 'italic'
|
|
166
|
+
}}
|
|
167
|
+
dropdownModalProps={{
|
|
168
|
+
dropdownProps: {
|
|
169
|
+
dropdownTitle: 'Choose Option',
|
|
170
|
+
closeTitle: 'Cancel'
|
|
171
|
+
},
|
|
172
|
+
dropdownStyles: {
|
|
173
|
+
dropdownTitleStyle: {
|
|
174
|
+
fontSize: 18,
|
|
175
|
+
fontWeight: 'bold'
|
|
176
|
+
},
|
|
177
|
+
closeTitleStyle: {
|
|
178
|
+
color: '#007AFF',
|
|
179
|
+
fontSize: 16
|
|
180
|
+
},
|
|
181
|
+
optionValueText: {
|
|
182
|
+
fontSize: 16,
|
|
183
|
+
color: '#333'
|
|
184
|
+
},
|
|
185
|
+
selectedOptionText: {
|
|
186
|
+
color: '#007AFF',
|
|
187
|
+
fontWeight: '600'
|
|
188
|
+
},
|
|
189
|
+
optionContainerStyle: {
|
|
190
|
+
paddingVertical: 12
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}}
|
|
194
|
+
/>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### RTL Support
|
|
198
|
+
|
|
199
|
+
```tsx
|
|
200
|
+
<BottomSheetDropdown
|
|
201
|
+
data={data}
|
|
202
|
+
onSelect={handleSelect}
|
|
203
|
+
selectedOption={selectedOption}
|
|
204
|
+
rtl={true}
|
|
205
|
+
placeholder="اختر خيار"
|
|
206
|
+
title="العنوان"
|
|
207
|
+
dropdownModalProps={{
|
|
208
|
+
dropdownProps: {
|
|
209
|
+
dropdownTitle: 'اختر خيار',
|
|
210
|
+
closeTitle: 'إغلاق'
|
|
211
|
+
}
|
|
212
|
+
}}
|
|
213
|
+
/>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Using with Form Libraries
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
import { useFormContext, Controller } from 'react-hook-form';
|
|
220
|
+
|
|
221
|
+
const FormDropdown = () => {
|
|
222
|
+
const { control } = useFormContext();
|
|
223
|
+
|
|
224
|
+
return (
|
|
225
|
+
<Controller
|
|
226
|
+
control={control}
|
|
227
|
+
name="selectedOption"
|
|
228
|
+
render={({ field: { onChange, value } }) => (
|
|
229
|
+
<BottomSheetDropdown
|
|
230
|
+
data={data}
|
|
231
|
+
onSelect={onChange}
|
|
232
|
+
selectedOption={value}
|
|
233
|
+
placeholder="Select option"
|
|
234
|
+
dropdownModalProps={{
|
|
235
|
+
dropdownProps: {
|
|
236
|
+
dropdownTitle: 'Select Option',
|
|
237
|
+
closeTitle: 'Close'
|
|
238
|
+
}
|
|
239
|
+
}}
|
|
240
|
+
/>
|
|
241
|
+
)}
|
|
242
|
+
/>
|
|
243
|
+
);
|
|
244
|
+
};
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## Exports
|
|
248
|
+
|
|
249
|
+
The package exports the following components and utilities:
|
|
250
|
+
|
|
251
|
+
```tsx
|
|
252
|
+
import {
|
|
253
|
+
BottomSheetDropdown, // Main component
|
|
254
|
+
DownIcon, // Dropdown arrow icon
|
|
255
|
+
TickIcon, // Selected item icon
|
|
256
|
+
hp, // Height percentage utility
|
|
257
|
+
wp, // Width percentage utility
|
|
258
|
+
DropdownDefaults, // Default values
|
|
259
|
+
|
|
260
|
+
// TypeScript types
|
|
261
|
+
DropdownItem,
|
|
262
|
+
DropdownProps,
|
|
263
|
+
DropdownModalProps,
|
|
264
|
+
DropdownDataProps,
|
|
265
|
+
DropdownModalStyles
|
|
266
|
+
} from 'react-native-bottom-sheet-dropdown';
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Default Values
|
|
270
|
+
|
|
271
|
+
```tsx
|
|
272
|
+
const DropdownDefaults = {
|
|
273
|
+
placeholder: 'Select an option',
|
|
274
|
+
title: '',
|
|
275
|
+
rtl: false,
|
|
276
|
+
dropdownProps: {
|
|
277
|
+
dropdownTitle: 'Select Option',
|
|
278
|
+
closeTitle: 'Close'
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Responsive Design
|
|
284
|
+
|
|
285
|
+
The component uses responsive dimensions based on screen size:
|
|
286
|
+
- `hp(percentage)` - Height percentage of screen
|
|
287
|
+
- `wp(percentage)` - Width percentage of screen
|
|
288
|
+
|
|
289
|
+
These utilities are also exported for use in your custom styling.
|
|
290
|
+
|
|
291
|
+
## Contributing
|
|
292
|
+
|
|
293
|
+
1. Fork the repository
|
|
294
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
295
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
296
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
297
|
+
5. Open a Pull Request
|
|
298
|
+
|
|
299
|
+
## Requirements
|
|
300
|
+
|
|
301
|
+
- React Native >= 0.60.0
|
|
302
|
+
- React >= 16.8.0
|
|
303
|
+
- TypeScript >= 4.9.0 (for TypeScript projects)
|
|
304
|
+
|
|
305
|
+
## License
|
|
306
|
+
|
|
307
|
+
MIT License - see the [LICENSE](LICENSE) file for details.
|
|
308
|
+
|
|
309
|
+
## Troubleshooting
|
|
310
|
+
|
|
311
|
+
### Common Issues
|
|
312
|
+
|
|
313
|
+
1. **Modal not appearing**: Ensure you have `react-native-modal` installed and linked properly
|
|
314
|
+
2. **Icons not showing**: Make sure `react-native-svg` is properly installed and configured
|
|
315
|
+
3. **TypeScript errors**: Ensure you have the latest version with proper type definitions
|
|
316
|
+
|
|
317
|
+
### Platform-specific Setup
|
|
318
|
+
|
|
319
|
+
**iOS**: Run `cd ios && pod install` after installation
|
|
320
|
+
|
|
321
|
+
**Android**: The package should work out of the box with autolinking
|
|
322
|
+
|
|
323
|
+
## Changelog
|
|
324
|
+
|
|
325
|
+
### v1.0.0
|
|
326
|
+
- Initial release
|
|
327
|
+
- Bottom sheet modal dropdown
|
|
328
|
+
- TypeScript support
|
|
329
|
+
- RTL support
|
|
330
|
+
- Customizable styling
|
|
331
|
+
- Responsive design
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
**Made with ❤️ for React Native developers**
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
const React = __importStar(require("react"));
|
|
30
|
+
const react_native_1 = require("react-native");
|
|
31
|
+
const index_1 = require("./utils/index");
|
|
32
|
+
const DownIcon_1 = __importDefault(require("./icons/DownIcon"));
|
|
33
|
+
const DropdownModal_1 = __importDefault(require("./DropdownModal"));
|
|
34
|
+
const BottomSheetDropdown = ({ data, onSelect, rtl, title = "", placeholder = "Select an option", selectedValue, selectedValueStyle, placeholderStyle, mainDropdownInput, titleStyle, dropdownModalProps, selectedOption, }) => {
|
|
35
|
+
const [showModal, setShowModal] = React.useState(false);
|
|
36
|
+
const toggleDropdownModal = React.useCallback(() => {
|
|
37
|
+
setShowModal(!showModal);
|
|
38
|
+
}, [showModal]);
|
|
39
|
+
const styles = react_native_1.StyleSheet.create({
|
|
40
|
+
mainContainer: {},
|
|
41
|
+
dropdownContainer: Object.assign({ width: "100%", height: (0, index_1.hp)(5.5), backgroundColor: "#ffffff", borderRadius: (0, index_1.wp)(2), marginTop: (0, index_1.hp)(1), borderWidth: 1, borderColor: "#CFCFCF", flexDirection: rtl ? "row-reverse" : "row", alignItems: "center", justifyContent: "space-between", paddingHorizontal: (0, index_1.wp)(4), paddingVertical: (0, index_1.hp)(1) }, mainDropdownInput),
|
|
42
|
+
title: Object.assign({ fontSize: 16, color: "#0D0D0D", textAlign: rtl ? "right" : "left" }, titleStyle),
|
|
43
|
+
selectedValue: Object.assign({ fontSize: 16, color: "#0D0D0D", textAlign: rtl ? "right" : "left" }, selectedValueStyle),
|
|
44
|
+
placeholderValue: Object.assign({ fontSize: 16, color: "#A0A0A0", textAlign: rtl ? "right" : "left" }, placeholderStyle),
|
|
45
|
+
});
|
|
46
|
+
return (React.createElement(React.Fragment, null,
|
|
47
|
+
React.createElement(DropdownModal_1.default, { visible: showModal, onClose: toggleDropdownModal, data: data, onSelect: onSelect, selectedOption: selectedOption, rtl: rtl, dropdownModalProps: Object.assign({}, dropdownModalProps) }),
|
|
48
|
+
React.createElement(react_native_1.View, { style: styles.mainContainer },
|
|
49
|
+
React.createElement(react_native_1.Text, { style: styles.title }, title),
|
|
50
|
+
React.createElement(react_native_1.Pressable, { style: styles.dropdownContainer, onPress: toggleDropdownModal },
|
|
51
|
+
selectedOption ? (React.createElement(react_native_1.Text, { style: styles.selectedValue }, selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.label)) : (React.createElement(react_native_1.Text, { style: styles.placeholderValue }, placeholder)),
|
|
52
|
+
React.createElement(DownIcon_1.default, null)))));
|
|
53
|
+
};
|
|
54
|
+
exports.default = BottomSheetDropdown;
|
|
@@ -0,0 +1,73 @@
|
|
|
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
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
const react_native_1 = require("react-native");
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
const react_native_modal_1 = __importDefault(require("react-native-modal"));
|
|
10
|
+
const TickIcon_1 = __importDefault(require("./icons/TickIcon"));
|
|
11
|
+
const DropdownModal = ({ data, visible, onClose, onSelect, dropdownModalProps, selectedOption, rtl, }) => {
|
|
12
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
13
|
+
const styles = react_native_1.StyleSheet.create({
|
|
14
|
+
modalContainer: {
|
|
15
|
+
justifyContent: "flex-start",
|
|
16
|
+
alignItems: "center",
|
|
17
|
+
height: (0, utils_1.hp)(40),
|
|
18
|
+
width: "100%",
|
|
19
|
+
borderTopLeftRadius: (0, utils_1.wp)(2),
|
|
20
|
+
borderTopRightRadius: (0, utils_1.wp)(2),
|
|
21
|
+
paddingHorizontal: (0, utils_1.wp)(4),
|
|
22
|
+
paddingVertical: (0, utils_1.hp)(2),
|
|
23
|
+
backgroundColor: "#fff",
|
|
24
|
+
},
|
|
25
|
+
dash: {
|
|
26
|
+
width: (0, utils_1.wp)(10),
|
|
27
|
+
height: (0, utils_1.hp)(0.5),
|
|
28
|
+
backgroundColor: "rgba(60, 60, 67, 0.3)",
|
|
29
|
+
borderRadius: (0, utils_1.wp)(2),
|
|
30
|
+
alignSelf: "center",
|
|
31
|
+
marginBottom: (0, utils_1.hp)(2),
|
|
32
|
+
},
|
|
33
|
+
row: {
|
|
34
|
+
width: "100%",
|
|
35
|
+
flexDirection: rtl ? "row-reverse" : "row",
|
|
36
|
+
alignItems: "center",
|
|
37
|
+
justifyContent: "space-between",
|
|
38
|
+
},
|
|
39
|
+
dropdownTitle: Object.assign({ fontSize: 16 }, (_a = dropdownModalProps === null || dropdownModalProps === void 0 ? void 0 : dropdownModalProps.dropdownStyles) === null || _a === void 0 ? void 0 : _a.dropdownTitleStyle),
|
|
40
|
+
close: Object.assign({ fontSize: 16, color: "blue" }, (_b = dropdownModalProps === null || dropdownModalProps === void 0 ? void 0 : dropdownModalProps.dropdownStyles) === null || _b === void 0 ? void 0 : _b.closeTitleStyle),
|
|
41
|
+
leftSpacer: {
|
|
42
|
+
width: (0, utils_1.wp)(10),
|
|
43
|
+
},
|
|
44
|
+
optionContainer: Object.assign({ width: "100%", height: (0, utils_1.hp)(6), justifyContent: "space-between", borderBottomWidth: 1, borderBottomColor: "rgba(60, 60, 67, 0.3)", flexDirection: rtl ? "row-reverse" : "row", alignItems: "center" }, (_c = dropdownModalProps === null || dropdownModalProps === void 0 ? void 0 : dropdownModalProps.dropdownStyles) === null || _c === void 0 ? void 0 : _c.optionContainerStyle),
|
|
45
|
+
optionValueText: Object.assign({ fontSize: 14, textAlign: "left" }, (_d = dropdownModalProps === null || dropdownModalProps === void 0 ? void 0 : dropdownModalProps.dropdownStyles) === null || _d === void 0 ? void 0 : _d.optionValueText),
|
|
46
|
+
scrollView: {
|
|
47
|
+
width: "100%",
|
|
48
|
+
},
|
|
49
|
+
selectedValueText: Object.assign({ color: "#007AFF" }, (_e = dropdownModalProps === null || dropdownModalProps === void 0 ? void 0 : dropdownModalProps.dropdownStyles) === null || _e === void 0 ? void 0 : _e.selectedOptionText),
|
|
50
|
+
});
|
|
51
|
+
return (react_1.default.createElement(react_native_modal_1.default, { isVisible: visible, onBackdropPress: onClose, style: { justifyContent: "flex-end", margin: 0 } },
|
|
52
|
+
react_1.default.createElement(react_native_1.View, { style: styles.modalContainer },
|
|
53
|
+
react_1.default.createElement(react_native_1.View, { style: styles.dash }),
|
|
54
|
+
react_1.default.createElement(react_native_1.View, { style: styles.row },
|
|
55
|
+
react_1.default.createElement(react_native_1.View, { style: styles.leftSpacer }),
|
|
56
|
+
react_1.default.createElement(react_native_1.Text, { style: styles.dropdownTitle }, (_f = dropdownModalProps === null || dropdownModalProps === void 0 ? void 0 : dropdownModalProps.dropdownProps) === null || _f === void 0 ? void 0 : _f.dropdownTitle),
|
|
57
|
+
react_1.default.createElement(react_native_1.TouchableOpacity, { onPress: onClose },
|
|
58
|
+
react_1.default.createElement(react_native_1.Text, { style: styles.close }, (_g = dropdownModalProps === null || dropdownModalProps === void 0 ? void 0 : dropdownModalProps.dropdownProps) === null || _g === void 0 ? void 0 : _g.closeTitle))),
|
|
59
|
+
react_1.default.createElement(react_native_1.ScrollView, { style: styles.scrollView, showsVerticalScrollIndicator: false }, data.map((item) => {
|
|
60
|
+
var _a, _b;
|
|
61
|
+
const isSelected = (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.value) === item.value;
|
|
62
|
+
return (react_1.default.createElement(react_native_1.Pressable, { key: item.value, style: styles.optionContainer, onPress: () => {
|
|
63
|
+
onSelect(item);
|
|
64
|
+
onClose();
|
|
65
|
+
} },
|
|
66
|
+
react_1.default.createElement(react_native_1.Text, { style: [
|
|
67
|
+
styles.optionValueText,
|
|
68
|
+
isSelected && styles.selectedValueText,
|
|
69
|
+
] }, item.label),
|
|
70
|
+
isSelected && (react_1.default.createElement(TickIcon_1.default, { color: ((_b = (_a = dropdownModalProps === null || dropdownModalProps === void 0 ? void 0 : dropdownModalProps.dropdownStyles) === null || _a === void 0 ? void 0 : _a.selectedOptionText) === null || _b === void 0 ? void 0 : _b.color) || "#007AFF" }))));
|
|
71
|
+
})))));
|
|
72
|
+
};
|
|
73
|
+
exports.default = DropdownModal;
|
|
@@ -0,0 +1,14 @@
|
|
|
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.DownIcon = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const react_native_svg_1 = require("react-native-svg");
|
|
9
|
+
function DownIcon({ color = "#0D0D0D", }) {
|
|
10
|
+
return (react_1.default.createElement(react_native_svg_1.Svg, { width: "18", height: "9", viewBox: "0 0 18 9", fill: "none" },
|
|
11
|
+
react_1.default.createElement(react_native_svg_1.Path, { d: "M16.9201 0.950195L10.4001 7.4702C9.63008 8.2402 8.37008 8.2402 7.60008 7.4702L1.08008 0.950195", stroke: color, strokeWidth: "1.5", strokeMiterlimit: "10", strokeLinecap: "round", strokeLinejoin: "round" })));
|
|
12
|
+
}
|
|
13
|
+
exports.DownIcon = DownIcon;
|
|
14
|
+
exports.default = DownIcon;
|
|
@@ -0,0 +1,14 @@
|
|
|
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.TickIcon = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
const react_native_svg_1 = require("react-native-svg");
|
|
9
|
+
function TickIcon({ color = "#215A47" }) {
|
|
10
|
+
return (react_1.default.createElement(react_native_svg_1.Svg, { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none" },
|
|
11
|
+
react_1.default.createElement(react_native_svg_1.Path, { d: "M3 12L8.99294 18L21 6", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })));
|
|
12
|
+
}
|
|
13
|
+
exports.TickIcon = TickIcon;
|
|
14
|
+
exports.default = TickIcon;
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { default as BottomSheetDropdown } from './BottomSheetDropdown';
|
|
2
|
+
export { default } from './BottomSheetDropdown';
|
|
3
|
+
export type { DropdownItem, DropdownProps, DropdownModalProps, DropdownDataProps, DropdownModalStyles } from './types';
|
|
4
|
+
export declare const DropdownDefaults: {
|
|
5
|
+
readonly placeholder: "Select an option";
|
|
6
|
+
readonly title: "";
|
|
7
|
+
readonly rtl: false;
|
|
8
|
+
readonly dropdownProps: {
|
|
9
|
+
readonly dropdownTitle: "Select Option";
|
|
10
|
+
readonly closeTitle: "Close";
|
|
11
|
+
};
|
|
12
|
+
};
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
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.DropdownDefaults = exports.default = exports.BottomSheetDropdown = void 0;
|
|
7
|
+
// Main entry point for react-native-bottom-sheet-dropdown library
|
|
8
|
+
var BottomSheetDropdown_1 = require("./BottomSheetDropdown");
|
|
9
|
+
Object.defineProperty(exports, "BottomSheetDropdown", { enumerable: true, get: function () { return __importDefault(BottomSheetDropdown_1).default; } });
|
|
10
|
+
var BottomSheetDropdown_2 = require("./BottomSheetDropdown");
|
|
11
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(BottomSheetDropdown_2).default; } });
|
|
12
|
+
// Default values that match the component implementation
|
|
13
|
+
exports.DropdownDefaults = {
|
|
14
|
+
placeholder: 'Select an option',
|
|
15
|
+
title: '',
|
|
16
|
+
rtl: false,
|
|
17
|
+
dropdownProps: {
|
|
18
|
+
dropdownTitle: 'Select Option',
|
|
19
|
+
closeTitle: 'Close'
|
|
20
|
+
}
|
|
21
|
+
};
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { ViewStyle, TextStyle } from "react-native";
|
|
2
|
+
export interface DropdownItem {
|
|
3
|
+
label: string;
|
|
4
|
+
value: string;
|
|
5
|
+
}
|
|
6
|
+
export interface DropdownProps {
|
|
7
|
+
data: DropdownItem[];
|
|
8
|
+
onSelect: (item: DropdownItem) => void;
|
|
9
|
+
selectedOption?: DropdownItem;
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
selectedValue?: string | number;
|
|
12
|
+
style?: ViewStyle;
|
|
13
|
+
dropdownStyle?: ViewStyle;
|
|
14
|
+
mainDropdownInput?: ViewStyle;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
searchable?: boolean;
|
|
17
|
+
maxHeight?: number;
|
|
18
|
+
headerTitle?: string;
|
|
19
|
+
showHeader?: boolean;
|
|
20
|
+
rtl?: boolean;
|
|
21
|
+
title?: string;
|
|
22
|
+
titleStyle?: TextStyle;
|
|
23
|
+
selectedValueStyle?: TextStyle;
|
|
24
|
+
placeholderStyle?: TextStyle;
|
|
25
|
+
dropdownModalProps: {
|
|
26
|
+
dropdownProps?: DropdownDataProps;
|
|
27
|
+
dropdownStyles?: DropdownModalStyles;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface DropdownModalProps {
|
|
31
|
+
visible: boolean;
|
|
32
|
+
onClose: () => void;
|
|
33
|
+
data: DropdownItem[];
|
|
34
|
+
onSelect: (item: DropdownItem) => void;
|
|
35
|
+
selectedOption?: DropdownItem;
|
|
36
|
+
dropdownModalProps: {
|
|
37
|
+
dropdownProps?: DropdownDataProps;
|
|
38
|
+
dropdownStyles?: DropdownModalStyles;
|
|
39
|
+
};
|
|
40
|
+
rtl?: boolean;
|
|
41
|
+
}
|
|
42
|
+
export interface DropdownDataProps {
|
|
43
|
+
dropdownTitle: string;
|
|
44
|
+
closeTitle: string;
|
|
45
|
+
}
|
|
46
|
+
export interface DropdownModalStyles {
|
|
47
|
+
dropdownTitleStyle?: TextStyle;
|
|
48
|
+
closeTitleStyle?: TextStyle;
|
|
49
|
+
optionValueText?: TextStyle;
|
|
50
|
+
selectedOptionText?: TextStyle;
|
|
51
|
+
optionContainerStyle?: ViewStyle;
|
|
52
|
+
}
|
package/lib/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { heightPercentageToDP as hp, widthPercentageToDP as wp, } from "react-native-responsive-screen";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.wp = exports.hp = void 0;
|
|
4
|
+
var react_native_responsive_screen_1 = require("react-native-responsive-screen");
|
|
5
|
+
Object.defineProperty(exports, "hp", { enumerable: true, get: function () { return react_native_responsive_screen_1.heightPercentageToDP; } });
|
|
6
|
+
Object.defineProperty(exports, "wp", { enumerable: true, get: function () { return react_native_responsive_screen_1.widthPercentageToDP; } });
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-bottom-sheet-dropdown",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A dropdown component with bottom sheet UI for React Native",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"prepare": "npm run build",
|
|
10
|
+
"test": "jest",
|
|
11
|
+
"lint": "eslint src --ext .ts,.tsx"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"react-native",
|
|
15
|
+
"dropdown",
|
|
16
|
+
"bottom-sheet",
|
|
17
|
+
"modal",
|
|
18
|
+
"picker",
|
|
19
|
+
"component",
|
|
20
|
+
"typescript"
|
|
21
|
+
],
|
|
22
|
+
"author": "Your Name",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/moustafahelmi96/react-native-bottom-sheet-dropdown"
|
|
27
|
+
},
|
|
28
|
+
"peerDependencies": {
|
|
29
|
+
"react": ">=16.8.0",
|
|
30
|
+
"react-native": ">=0.60.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/react": "^18.0.0",
|
|
34
|
+
"@types/react-native": "^0.72.0",
|
|
35
|
+
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
|
36
|
+
"@typescript-eslint/parser": "^5.0.0",
|
|
37
|
+
"eslint": "^8.0.0",
|
|
38
|
+
"jest": "^29.0.0",
|
|
39
|
+
"typescript": "^4.9.0"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"lib/",
|
|
43
|
+
"README.md",
|
|
44
|
+
"LICENSE"
|
|
45
|
+
],
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"react-native-modal": "^14.0.0-rc.1",
|
|
48
|
+
"react-native-responsive-screen": "^1.4.2",
|
|
49
|
+
"react-native-svg": "^15.12.0"
|
|
50
|
+
}
|
|
51
|
+
}
|