@shaquillehinds/react-native-dropdown-selector 0.0.1
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/LICENSE +20 -0
- package/README.md +526 -0
- package/lib/commonjs/DropDownSelector/DropDownSelector.controller.js +129 -0
- package/lib/commonjs/DropDownSelector/DropDownSelector.controller.js.map +1 -0
- package/lib/commonjs/DropDownSelector/DropDownSelector.js +136 -0
- package/lib/commonjs/DropDownSelector/DropDownSelector.js.map +1 -0
- package/lib/commonjs/DropDownSelector/DropDownSelector.types.js +6 -0
- package/lib/commonjs/DropDownSelector/DropDownSelector.types.js.map +1 -0
- package/lib/commonjs/DropDownSelector/index.js +28 -0
- package/lib/commonjs/DropDownSelector/index.js.map +1 -0
- package/lib/commonjs/DropDownSelector/svgs/ChevronUp.js +26 -0
- package/lib/commonjs/DropDownSelector/svgs/ChevronUp.js.map +1 -0
- package/lib/commonjs/index.js +21 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/module/DropDownSelector/DropDownSelector.controller.js +125 -0
- package/lib/module/DropDownSelector/DropDownSelector.controller.js.map +1 -0
- package/lib/module/DropDownSelector/DropDownSelector.js +132 -0
- package/lib/module/DropDownSelector/DropDownSelector.js.map +1 -0
- package/lib/module/DropDownSelector/DropDownSelector.types.js +4 -0
- package/lib/module/DropDownSelector/DropDownSelector.types.js.map +1 -0
- package/lib/module/DropDownSelector/index.js +5 -0
- package/lib/module/DropDownSelector/index.js.map +1 -0
- package/lib/module/DropDownSelector/svgs/ChevronUp.js +21 -0
- package/lib/module/DropDownSelector/svgs/ChevronUp.js.map +1 -0
- package/lib/module/index.js +6 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/DropDownSelector/DropDownSelector.controller.d.ts +28 -0
- package/lib/typescript/commonjs/src/DropDownSelector/DropDownSelector.controller.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/DropDownSelector/DropDownSelector.d.ts +3 -0
- package/lib/typescript/commonjs/src/DropDownSelector/DropDownSelector.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/DropDownSelector/DropDownSelector.types.d.ts +45 -0
- package/lib/typescript/commonjs/src/DropDownSelector/DropDownSelector.types.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/DropDownSelector/index.d.ts +3 -0
- package/lib/typescript/commonjs/src/DropDownSelector/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/DropDownSelector/svgs/ChevronUp.d.ts +5 -0
- package/lib/typescript/commonjs/src/DropDownSelector/svgs/ChevronUp.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +4 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/DropDownSelector/DropDownSelector.controller.d.ts +28 -0
- package/lib/typescript/module/src/DropDownSelector/DropDownSelector.controller.d.ts.map +1 -0
- package/lib/typescript/module/src/DropDownSelector/DropDownSelector.d.ts +3 -0
- package/lib/typescript/module/src/DropDownSelector/DropDownSelector.d.ts.map +1 -0
- package/lib/typescript/module/src/DropDownSelector/DropDownSelector.types.d.ts +45 -0
- package/lib/typescript/module/src/DropDownSelector/DropDownSelector.types.d.ts.map +1 -0
- package/lib/typescript/module/src/DropDownSelector/index.d.ts +3 -0
- package/lib/typescript/module/src/DropDownSelector/index.d.ts.map +1 -0
- package/lib/typescript/module/src/DropDownSelector/svgs/ChevronUp.d.ts +5 -0
- package/lib/typescript/module/src/DropDownSelector/svgs/ChevronUp.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +4 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/package.json +203 -0
- package/src/DropDownSelector/DropDownSelector.controller.tsx +174 -0
- package/src/DropDownSelector/DropDownSelector.tsx +183 -0
- package/src/DropDownSelector/DropDownSelector.types.ts +44 -0
- package/src/DropDownSelector/index.ts +2 -0
- package/src/DropDownSelector/svgs/ChevronUp.tsx +18 -0
- package/src/index.tsx +4 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Shaquille Hinds
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
# @shaquillehinds/react-native-dropdown-selector
|
|
2
|
+
|
|
3
|
+
A beautifully animated, fully customizable dropdown selector for React Native that intelligently adapts to screen position and just works out of the box.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@shaquillehinds/react-native-dropdown-selector)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## ✨ Features
|
|
9
|
+
|
|
10
|
+
- 🎯 **Smart Positioning** - Automatically detects available screen space and renders upward or downward
|
|
11
|
+
- 🎨 **Fully Customizable** - Style every element from the button to individual items
|
|
12
|
+
- 🔄 **Smooth Animations** - Fluid spring and timing animations with configurable parameters
|
|
13
|
+
- 📱 **Cross-Platform** - Works seamlessly on iOS and Android with platform-specific optimizations
|
|
14
|
+
- 🎭 **Custom Components** - Replace default components with your own React components
|
|
15
|
+
- 🔍 **TypeScript Support** - Full type safety with generic type support
|
|
16
|
+
- 🪶 **Lightweight** - Minimal dependencies, built on react-native-essentials
|
|
17
|
+
- ♿ **Accessible** - Includes proper touch targets and visual feedback
|
|
18
|
+
|
|
19
|
+
## 📦 Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @shaquillehinds/react-native-dropdown-selector
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
or
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
yarn add @shaquillehinds/react-native-dropdown-selector
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Peer Dependencies
|
|
32
|
+
|
|
33
|
+
This package requires the following peer dependencies:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install react-native-gesture-handler react-native-reanimated react-native-svg
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Make sure to complete the installation setup for these libraries as per their documentation.
|
|
40
|
+
|
|
41
|
+
## 🚀 Basic Usage
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { DropDownSelector } from '@shaquillehinds/react-native-dropdown-selector';
|
|
45
|
+
import { useState } from 'react';
|
|
46
|
+
|
|
47
|
+
function MyComponent() {
|
|
48
|
+
const [selectedValue, setSelectedValue] = useState<string>('apple');
|
|
49
|
+
|
|
50
|
+
const fruits = [
|
|
51
|
+
{ label: 'Apple', value: 'apple' },
|
|
52
|
+
{ label: 'Banana', value: 'banana' },
|
|
53
|
+
{ label: 'Orange', value: 'orange' },
|
|
54
|
+
{ label: 'Mango', value: 'mango' },
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<DropDownSelector
|
|
59
|
+
items={fruits}
|
|
60
|
+
selectedItem={selectedValue}
|
|
61
|
+
onSelect={setSelectedValue}
|
|
62
|
+
placeholder="Select a fruit"
|
|
63
|
+
/>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 🎨 Advanced Customization
|
|
69
|
+
|
|
70
|
+
### Styling the Dropdown Button
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
<DropDownSelector
|
|
74
|
+
items={items}
|
|
75
|
+
selectedItem={selectedValue}
|
|
76
|
+
onSelect={setSelectedValue}
|
|
77
|
+
placeholder="Select option"
|
|
78
|
+
dropdownButtonProps={{
|
|
79
|
+
backgroundColor: '#007AFF',
|
|
80
|
+
borderRadius: 'large',
|
|
81
|
+
padding: [2, 6],
|
|
82
|
+
}}
|
|
83
|
+
dropdownButtonTextProps={{
|
|
84
|
+
color: 'white',
|
|
85
|
+
fontSize: 16,
|
|
86
|
+
fontWeight: '600',
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Custom Icon Component
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
import { ChevronDown } from './icons';
|
|
95
|
+
|
|
96
|
+
<DropDownSelector
|
|
97
|
+
items={items}
|
|
98
|
+
selectedItem={selectedValue}
|
|
99
|
+
onSelect={setSelectedValue}
|
|
100
|
+
placeholder="Select option"
|
|
101
|
+
DropdownButtonIcon={({ isOpen, expandDirection }) => (
|
|
102
|
+
<ChevronDown
|
|
103
|
+
color="#007AFF"
|
|
104
|
+
style={{
|
|
105
|
+
transform: [{ rotate: isOpen ? '180deg' : '0deg' }],
|
|
106
|
+
}}
|
|
107
|
+
/>
|
|
108
|
+
)}
|
|
109
|
+
/>;
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Custom Dropdown Item Component
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
<DropDownSelector
|
|
116
|
+
items={items}
|
|
117
|
+
selectedItem={selectedValue}
|
|
118
|
+
onSelect={setSelectedValue}
|
|
119
|
+
placeholder="Select option"
|
|
120
|
+
DropdownItemComponent={({ item, isSelected }) => (
|
|
121
|
+
<View style={styles.customItem}>
|
|
122
|
+
<Image source={{ uri: item.icon }} style={styles.icon} />
|
|
123
|
+
<Text style={[styles.itemText, isSelected && styles.selected]}>
|
|
124
|
+
{item.label}
|
|
125
|
+
</Text>
|
|
126
|
+
{isSelected && <CheckIcon />}
|
|
127
|
+
</View>
|
|
128
|
+
)}
|
|
129
|
+
/>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Configuring Animations
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
<DropDownSelector
|
|
136
|
+
items={items}
|
|
137
|
+
selectedItem={selectedValue}
|
|
138
|
+
onSelect={setSelectedValue}
|
|
139
|
+
placeholder="Select option"
|
|
140
|
+
expandAnimationConfig={{
|
|
141
|
+
type: 'spring',
|
|
142
|
+
speed: 12,
|
|
143
|
+
bounciness: 8,
|
|
144
|
+
}}
|
|
145
|
+
unMountDelayInMilliSeconds={250}
|
|
146
|
+
/>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Controlling Expand Direction
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
// Force expand upward
|
|
153
|
+
<DropDownSelector
|
|
154
|
+
items={items}
|
|
155
|
+
selectedItem={selectedValue}
|
|
156
|
+
onSelect={setSelectedValue}
|
|
157
|
+
placeholder="Select option"
|
|
158
|
+
expandDirection="up"
|
|
159
|
+
/>
|
|
160
|
+
|
|
161
|
+
// Force expand downward
|
|
162
|
+
<DropDownSelector
|
|
163
|
+
items={items}
|
|
164
|
+
selectedItem={selectedValue}
|
|
165
|
+
onSelect={setSelectedValue}
|
|
166
|
+
placeholder="Select option"
|
|
167
|
+
expandDirection="down"
|
|
168
|
+
/>
|
|
169
|
+
|
|
170
|
+
// Auto-detect (default behavior)
|
|
171
|
+
<DropDownSelector
|
|
172
|
+
items={items}
|
|
173
|
+
selectedItem={selectedValue}
|
|
174
|
+
onSelect={setSelectedValue}
|
|
175
|
+
placeholder="Select option"
|
|
176
|
+
// expandDirection not specified - automatically detects best direction
|
|
177
|
+
/>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Custom Expand Distance
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
<DropDownSelector
|
|
184
|
+
items={items}
|
|
185
|
+
selectedItem={selectedValue}
|
|
186
|
+
onSelect={setSelectedValue}
|
|
187
|
+
placeholder="Select option"
|
|
188
|
+
expandDistance={250} // Maximum height in pixels
|
|
189
|
+
/>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## 📚 API Reference
|
|
193
|
+
|
|
194
|
+
### Props
|
|
195
|
+
|
|
196
|
+
| Prop | Type | Required | Description |
|
|
197
|
+
| ------------------------------- | --------------------------------- | -------- | ------------------------------------------------- |
|
|
198
|
+
| `items` | `DropDownItem<T>[]` | ✅ | Array of items to display in dropdown |
|
|
199
|
+
| `selectedItem` | `T` | ✅ | Currently selected item value |
|
|
200
|
+
| `onSelect` | `(item: T) => void` | ✅ | Callback when an item is selected |
|
|
201
|
+
| `placeholder` | `string` | ✅ | Placeholder text when no item is selected |
|
|
202
|
+
| `onOpen` | `() => void` | ❌ | Callback when dropdown opens |
|
|
203
|
+
| `onClose` | `() => void` | ❌ | Callback when dropdown closes |
|
|
204
|
+
| `unMountDelayInMilliSeconds` | `number` | ❌ | Delay before unmounting dropdown (default: 300ms) |
|
|
205
|
+
| `isDisabled` | `boolean` | ❌ | Disables the dropdown selector |
|
|
206
|
+
| `disableShadow` | `boolean` | ❌ | Removes shadow from dropdown |
|
|
207
|
+
| `expandDirection` | `'up' \| 'down'` | ❌ | Forces dropdown to expand in specific direction |
|
|
208
|
+
| `expandDistance` | `number` | ❌ | Maximum height for dropdown content |
|
|
209
|
+
| `expandAnimationConfig` | `AnimationConfig` | ❌ | Custom animation configuration |
|
|
210
|
+
| `containerProps` | `LayoutProps` | ❌ | Props for the root container |
|
|
211
|
+
| `dropdownButtonProps` | `RNPressableLayoutProps` | ❌ | Props for the dropdown button |
|
|
212
|
+
| `dropdownButtonTextProps` | `BaseTextProps` | ❌ | Props for the button text |
|
|
213
|
+
| `DropdownButtonIcon` | `Component` | ❌ | Custom button icon component |
|
|
214
|
+
| `dropdownScrollViewProps` | `ScrollViewProps` | ❌ | Props for the dropdown ScrollView |
|
|
215
|
+
| `dropdownContentContainerProps` | `LayoutProps` | ❌ | Props for the dropdown content container |
|
|
216
|
+
| `DropdownItemComponent` | `Component` | ❌ | Custom dropdown item component |
|
|
217
|
+
| `onDropdownItemPress` | `(item: DropDownItem<T>) => void` | ❌ | Callback when dropdown item is pressed |
|
|
218
|
+
| `dropdownItemProps` | `TouchableLayoutProps` | ❌ | Props for individual dropdown items |
|
|
219
|
+
| `dropdownItemTextProps` | `BaseTextProps` | ❌ | Props for dropdown item text |
|
|
220
|
+
| `DropdownItemSelectedIcon` | `Component` | ❌ | Custom selected item icon component |
|
|
221
|
+
|
|
222
|
+
### Types
|
|
223
|
+
|
|
224
|
+
#### DropDownItem<T>
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
type DropDownItem<T> = {
|
|
228
|
+
label: string; // Display text
|
|
229
|
+
value: T; // Value (can be any type)
|
|
230
|
+
};
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### AnimationConfig
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
type AnimationConfig =
|
|
237
|
+
| (Omit<Animated.TimingAnimationConfig, 'toValue'> & { type: 'timing' })
|
|
238
|
+
| (Omit<Animated.SpringAnimationConfig, 'toValue'> & { type: 'spring' });
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Custom Component Props
|
|
242
|
+
|
|
243
|
+
#### DropdownButtonIcon
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
type DropdownButtonIconProps = {
|
|
247
|
+
isOpen: boolean;
|
|
248
|
+
expandDirection: 'up' | 'down';
|
|
249
|
+
};
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
#### DropdownItemComponent
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
type DropdownItemComponentProps<T> = {
|
|
256
|
+
item: DropDownItem<T>;
|
|
257
|
+
isSelected: boolean;
|
|
258
|
+
};
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
#### DropdownItemSelectedIcon
|
|
262
|
+
|
|
263
|
+
```typescript
|
|
264
|
+
type DropdownItemSelectedIconProps<T> = {
|
|
265
|
+
item: DropDownItem<T>;
|
|
266
|
+
};
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## 🎯 Advanced Examples
|
|
270
|
+
|
|
271
|
+
### With TypeScript Generics
|
|
272
|
+
|
|
273
|
+
```tsx
|
|
274
|
+
interface User {
|
|
275
|
+
id: number;
|
|
276
|
+
name: string;
|
|
277
|
+
email: string;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function UserSelector() {
|
|
281
|
+
const [selectedUserId, setSelectedUserId] = useState<number>(1);
|
|
282
|
+
|
|
283
|
+
const users: DropDownItem<number>[] = [
|
|
284
|
+
{ label: 'John Doe', value: 1 },
|
|
285
|
+
{ label: 'Jane Smith', value: 2 },
|
|
286
|
+
{ label: 'Bob Johnson', value: 3 },
|
|
287
|
+
];
|
|
288
|
+
|
|
289
|
+
return (
|
|
290
|
+
<DropDownSelector<number>
|
|
291
|
+
items={users}
|
|
292
|
+
selectedItem={selectedUserId}
|
|
293
|
+
onSelect={setSelectedUserId}
|
|
294
|
+
placeholder="Select a user"
|
|
295
|
+
/>
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### With Complex Objects
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
interface Country {
|
|
304
|
+
code: string;
|
|
305
|
+
name: string;
|
|
306
|
+
flag: string;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function CountrySelector() {
|
|
310
|
+
const [selectedCountry, setSelectedCountry] = useState<string>('US');
|
|
311
|
+
|
|
312
|
+
const countries: DropDownItem<string>[] = [
|
|
313
|
+
{ label: '🇺🇸 United States', value: 'US' },
|
|
314
|
+
{ label: '🇨🇦 Canada', value: 'CA' },
|
|
315
|
+
{ label: '🇬🇧 United Kingdom', value: 'GB' },
|
|
316
|
+
{ label: '🇦🇺 Australia', value: 'AU' },
|
|
317
|
+
];
|
|
318
|
+
|
|
319
|
+
return (
|
|
320
|
+
<DropDownSelector<string>
|
|
321
|
+
items={countries}
|
|
322
|
+
selectedItem={selectedCountry}
|
|
323
|
+
onSelect={setSelectedCountry}
|
|
324
|
+
placeholder="Select a country"
|
|
325
|
+
onDropdownItemPress={(item) => {
|
|
326
|
+
console.log('Selected country:', item.label);
|
|
327
|
+
}}
|
|
328
|
+
/>
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### With Lifecycle Callbacks
|
|
334
|
+
|
|
335
|
+
```tsx
|
|
336
|
+
<DropDownSelector
|
|
337
|
+
items={items}
|
|
338
|
+
selectedItem={selectedValue}
|
|
339
|
+
onSelect={setSelectedValue}
|
|
340
|
+
placeholder="Select option"
|
|
341
|
+
onOpen={() => {
|
|
342
|
+
console.log('Dropdown opened');
|
|
343
|
+
// Track analytics, pause animations, etc.
|
|
344
|
+
}}
|
|
345
|
+
onClose={() => {
|
|
346
|
+
console.log('Dropdown closed');
|
|
347
|
+
// Resume animations, save state, etc.
|
|
348
|
+
}}
|
|
349
|
+
onDropdownItemPress={(item) => {
|
|
350
|
+
console.log('Item pressed:', item);
|
|
351
|
+
// Custom handling before selection
|
|
352
|
+
}}
|
|
353
|
+
/>
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Fully Customized Theme
|
|
357
|
+
|
|
358
|
+
```tsx
|
|
359
|
+
<DropDownSelector
|
|
360
|
+
items={items}
|
|
361
|
+
selectedItem={selectedValue}
|
|
362
|
+
onSelect={setSelectedValue}
|
|
363
|
+
placeholder="Select option"
|
|
364
|
+
containerProps={{
|
|
365
|
+
margin: [2, 0],
|
|
366
|
+
}}
|
|
367
|
+
dropdownButtonProps={{
|
|
368
|
+
backgroundColor: '#1E1E1E',
|
|
369
|
+
borderRadius: 'large',
|
|
370
|
+
padding: [3, 5],
|
|
371
|
+
borderWidth: 1,
|
|
372
|
+
borderColor: '#333',
|
|
373
|
+
}}
|
|
374
|
+
dropdownButtonTextProps={{
|
|
375
|
+
color: '#FFFFFF',
|
|
376
|
+
fontSize: 16,
|
|
377
|
+
fontWeight: '500',
|
|
378
|
+
}}
|
|
379
|
+
dropdownContentContainerProps={{
|
|
380
|
+
backgroundColor: '#2A2A2A',
|
|
381
|
+
borderRadius: 'soft',
|
|
382
|
+
}}
|
|
383
|
+
dropdownItemProps={{
|
|
384
|
+
padding: [3, 5],
|
|
385
|
+
backgroundColor: '#2A2A2A',
|
|
386
|
+
}}
|
|
387
|
+
dropdownItemTextProps={{
|
|
388
|
+
color: '#FFFFFF',
|
|
389
|
+
fontSize: 15,
|
|
390
|
+
}}
|
|
391
|
+
disableShadow={false}
|
|
392
|
+
/>
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## 🔧 How It Works
|
|
396
|
+
|
|
397
|
+
### Smart Positioning
|
|
398
|
+
|
|
399
|
+
The dropdown automatically measures its position on the screen and determines whether there's enough space to expand downward. If not, it expands upward. This ensures the dropdown is always visible and accessible.
|
|
400
|
+
|
|
401
|
+
```tsx
|
|
402
|
+
// The component automatically:
|
|
403
|
+
// 1. Measures its position using onLayout
|
|
404
|
+
// 2. Calculates distance to bottom of screen
|
|
405
|
+
// 3. Compares with expandDistance (or default maxHeight)
|
|
406
|
+
// 4. Renders upward if insufficient space below
|
|
407
|
+
// 5. Animates chevron icon to match direction
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Animation System
|
|
411
|
+
|
|
412
|
+
The component uses `react-native-reanimated` for smooth, performant animations:
|
|
413
|
+
|
|
414
|
+
- **Dropdown expansion**: Configurable spring or timing animation
|
|
415
|
+
- **Chevron rotation**: Spring animation that follows expand direction
|
|
416
|
+
- **Android shadow**: Timing animation for platform-specific shadow rendering
|
|
417
|
+
|
|
418
|
+
### Modal Integration
|
|
419
|
+
|
|
420
|
+
Uses `@shaquillehinds/react-native-essentials` modal system for proper overlay handling, ensuring the dropdown appears above other content with correct z-index management.
|
|
421
|
+
|
|
422
|
+
## 🎨 Styling with react-native-essentials
|
|
423
|
+
|
|
424
|
+
This package leverages `@shaquillehinds/react-native-essentials` for its layout and styling system, which provides:
|
|
425
|
+
|
|
426
|
+
- Predefined border radius sizes (`soft`, `medium`, `large`)
|
|
427
|
+
- Shadow utilities with platform-specific handling
|
|
428
|
+
- Responsive sizing based on device orientation
|
|
429
|
+
- Flexible layout components with intuitive props
|
|
430
|
+
|
|
431
|
+
Example of essentials-powered styling:
|
|
432
|
+
|
|
433
|
+
```tsx
|
|
434
|
+
<DropDownSelector
|
|
435
|
+
dropdownButtonProps={{
|
|
436
|
+
borderRadius: 'medium', // Uses predefined radius
|
|
437
|
+
padding: [2, 5], // [vertical, horizontal] shorthand
|
|
438
|
+
backgroundColor: 'white',
|
|
439
|
+
}}
|
|
440
|
+
/>
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
## 🐛 Troubleshooting
|
|
444
|
+
|
|
445
|
+
### Dropdown not appearing
|
|
446
|
+
|
|
447
|
+
Ensure you've installed and configured peer dependencies:
|
|
448
|
+
|
|
449
|
+
- `react-native-gesture-handler`
|
|
450
|
+
- `react-native-reanimated`
|
|
451
|
+
- `react-native-svg`
|
|
452
|
+
|
|
453
|
+
### Items not scrolling
|
|
454
|
+
|
|
455
|
+
Check that `react-native-gesture-handler` is properly set up in your app's entry file:
|
|
456
|
+
|
|
457
|
+
```tsx
|
|
458
|
+
import 'react-native-gesture-handler';
|
|
459
|
+
// ... rest of your imports
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### Shadow not showing on Android
|
|
463
|
+
|
|
464
|
+
The component handles Android shadows differently. If you're still not seeing shadows, try:
|
|
465
|
+
|
|
466
|
+
- Setting `disableShadow={false}` explicitly
|
|
467
|
+
- Checking that your Android API level supports the shadow properties
|
|
468
|
+
|
|
469
|
+
### Dropdown position incorrect
|
|
470
|
+
|
|
471
|
+
The component measures position on mount and when opened. If your layout shifts after initial render:
|
|
472
|
+
|
|
473
|
+
```tsx
|
|
474
|
+
// Force remeasure by adding key prop when layout changes
|
|
475
|
+
<DropDownSelector
|
|
476
|
+
key={layoutKey}
|
|
477
|
+
items={items}
|
|
478
|
+
selectedItem={selectedValue}
|
|
479
|
+
onSelect={setSelectedValue}
|
|
480
|
+
placeholder="Select option"
|
|
481
|
+
/>
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
## 📝 Examples Repository
|
|
485
|
+
|
|
486
|
+
For more examples and complete implementation patterns, check out the [examples folder](https://github.com/shaquillehinds/react-native-dropdown-selector/tree/main/example) in the repository.
|
|
487
|
+
|
|
488
|
+
## 🤝 Contributing
|
|
489
|
+
|
|
490
|
+
Contributions are welcome! Please read our [Contributing Guide](./CONTRIBUTING.md) and [Code of Conduct](./CODE_OF_CONDUCT.md) before submitting pull requests.
|
|
491
|
+
|
|
492
|
+
### Development Setup
|
|
493
|
+
|
|
494
|
+
```bash
|
|
495
|
+
# Clone the repository
|
|
496
|
+
git clone https://github.com/shaquillehinds/react-native-dropdown-selector.git
|
|
497
|
+
|
|
498
|
+
# Install dependencies
|
|
499
|
+
yarn install
|
|
500
|
+
|
|
501
|
+
# Run the example app
|
|
502
|
+
yarn example start
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
## 📄 License
|
|
506
|
+
|
|
507
|
+
MIT © [Shaquille Hinds](https://github.com/shaquillehinds)
|
|
508
|
+
|
|
509
|
+
## 🙏 Acknowledgments
|
|
510
|
+
|
|
511
|
+
Built with:
|
|
512
|
+
|
|
513
|
+
- [@shaquillehinds/react-native-essentials](https://www.npmjs.com/package/@shaquillehinds/react-native-essentials) - Layout and utility components
|
|
514
|
+
- [react-native-reanimated](https://docs.swmansion.com/react-native-reanimated/) - Smooth animations
|
|
515
|
+
- [react-native-gesture-handler](https://docs.swmansion.com/react-native-gesture-handler/) - Touch handling
|
|
516
|
+
- [react-native-svg](https://github.com/software-mansion/react-native-svg) - Vector graphics
|
|
517
|
+
|
|
518
|
+
## 📮 Support
|
|
519
|
+
|
|
520
|
+
- 📧 Email: shaqdulove@gmail.com
|
|
521
|
+
- 🐛 Issues: [GitHub Issues](https://github.com/shaquillehinds/react-native-dropdown-selector/issues)
|
|
522
|
+
- 💬 Discussions: [GitHub Discussions](https://github.com/shaquillehinds/react-native-dropdown-selector/discussions)
|
|
523
|
+
|
|
524
|
+
---
|
|
525
|
+
|
|
526
|
+
Made with ❤️ by [Shaquille Hinds](https://github.com/shaquillehinds)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.DropDownSelectorController = DropDownSelectorController;
|
|
7
|
+
var _reactNativeEssentials = require("@shaquillehinds/react-native-essentials");
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
function DropDownSelectorController(props) {
|
|
10
|
+
const [showItems, setShowItems] = (0, _react.useState)(false);
|
|
11
|
+
const [hasPageY, setHasPageY] = (0, _react.useState)(false);
|
|
12
|
+
const {
|
|
13
|
+
screenHeight,
|
|
14
|
+
relativeY
|
|
15
|
+
} = (0, _reactNativeEssentials.useDeviceOrientation)();
|
|
16
|
+
const pageYRef = (0, _react.useRef)(null);
|
|
17
|
+
const scrollViewRef = (0, _react.useRef)(null);
|
|
18
|
+
const canRenderDownRef = (0, _react.useRef)(null);
|
|
19
|
+
const animateChevronRef = (0, _react.useRef)(null);
|
|
20
|
+
const animateComponentRef = (0, _react.useRef)(null);
|
|
21
|
+
const animateAndroidShadowRef = (0, _react.useRef)(null);
|
|
22
|
+
const unMountDelayInMilliSeconds = (0, _react.useMemo)(() => {
|
|
23
|
+
if (props.expandAnimationConfig?.type === 'timing') return props.expandAnimationConfig?.duration || 300;
|
|
24
|
+
return props.unMountDelayInMilliSeconds || 300;
|
|
25
|
+
}, [props.expandAnimationConfig]);
|
|
26
|
+
const maxHeight = (0, _react.useMemo)(() => props.expandDistance || relativeY(30), [relativeY, props.expandDistance]);
|
|
27
|
+
const label = (0, _react.useMemo)(() => props.items.find(item => item.value === props.selectedItem)?.label, [props.items, props.selectedItem]);
|
|
28
|
+
const canRenderDown = (0, _react.useMemo)(() => {
|
|
29
|
+
if (props.expandDirection === 'up') return false;
|
|
30
|
+
if (props.expandDirection === 'down') return true;
|
|
31
|
+
if (!pageYRef.current) return null;
|
|
32
|
+
if (!showItems && canRenderDownRef.current !== null) return canRenderDownRef.current;
|
|
33
|
+
const distanceToBottom = screenHeight - pageYRef.current;
|
|
34
|
+
if (distanceToBottom < maxHeight) canRenderDownRef.current = false;else canRenderDownRef.current = true;
|
|
35
|
+
return canRenderDownRef.current;
|
|
36
|
+
}, [showItems, screenHeight, maxHeight, hasPageY]);
|
|
37
|
+
const androidShadowAnimationConfig = (0, _react.useMemo)(() => ({
|
|
38
|
+
toValue: 1,
|
|
39
|
+
type: 'timing',
|
|
40
|
+
useNativeDriver: true,
|
|
41
|
+
duration: canRenderDown ? showItems ? 400 : 200 : showItems ? 800 : 100
|
|
42
|
+
}), [canRenderDown, showItems]);
|
|
43
|
+
const scrollViewStyle = (0, _react.useMemo)(() => ({
|
|
44
|
+
overflow: 'hidden',
|
|
45
|
+
maxHeight: maxHeight,
|
|
46
|
+
minHeight: relativeY(5),
|
|
47
|
+
borderRadius: _reactNativeEssentials.radiusSizes.soft,
|
|
48
|
+
transform: [{
|
|
49
|
+
translateY: canRenderDown ? 0 : -maxHeight + relativeY(4)
|
|
50
|
+
}]
|
|
51
|
+
}), [canRenderDown, maxHeight, relativeY]);
|
|
52
|
+
const chevronAnimationConfig = (0, _react.useMemo)(() => ({
|
|
53
|
+
toValue: canRenderDown ? 1 : -1,
|
|
54
|
+
type: 'spring',
|
|
55
|
+
speed: 1,
|
|
56
|
+
bounciness: 1,
|
|
57
|
+
useNativeDriver: true
|
|
58
|
+
}), [canRenderDown]);
|
|
59
|
+
const selectionItemsListAnimationConfig = (0, _react.useMemo)(() => ({
|
|
60
|
+
toValue: 0,
|
|
61
|
+
type: 'spring',
|
|
62
|
+
speed: 1,
|
|
63
|
+
bounciness: 1,
|
|
64
|
+
useNativeDriver: true
|
|
65
|
+
}), []);
|
|
66
|
+
const chevronAnimatedStyle = (0, _react.useCallback)(scaleY => ({
|
|
67
|
+
transform: [{
|
|
68
|
+
scaleY
|
|
69
|
+
}]
|
|
70
|
+
}), []);
|
|
71
|
+
const handleLayout = (0, _react.useCallback)(e => {
|
|
72
|
+
e.currentTarget.measure((_x, _y, _width, _height, _pageX, pageY) => {
|
|
73
|
+
pageYRef.current = pageY || screenHeight / 2;
|
|
74
|
+
setHasPageY(true);
|
|
75
|
+
});
|
|
76
|
+
props.containerProps?.onLayout?.(e);
|
|
77
|
+
}, [props.containerProps?.onLayout]);
|
|
78
|
+
const androidShadowAnimatedStyle = (0, _react.useCallback)(opacity => ({
|
|
79
|
+
opacity,
|
|
80
|
+
right: 0,
|
|
81
|
+
left: 0,
|
|
82
|
+
top: 0,
|
|
83
|
+
bottom: 0,
|
|
84
|
+
position: 'absolute',
|
|
85
|
+
boxShadow: canRenderDown ? '5px 18px 25px 0px rgba(0,0,0,0.15)' : '5px -18px 25px 0px rgba(0,0,0,0.15)',
|
|
86
|
+
borderRadius: _reactNativeEssentials.radiusSizes.soft,
|
|
87
|
+
transform: [{
|
|
88
|
+
translateY: canRenderDown ? 0 : -maxHeight + relativeY(4)
|
|
89
|
+
}]
|
|
90
|
+
}), [canRenderDown, maxHeight, relativeY]);
|
|
91
|
+
const selectionItemsListAnimatedStyle = (0, _react.useCallback)(translateY => ({
|
|
92
|
+
transform: [{
|
|
93
|
+
translateY
|
|
94
|
+
}]
|
|
95
|
+
}), []);
|
|
96
|
+
(0, _react.useEffect)(() => {
|
|
97
|
+
if (animateComponentRef.current && !showItems) animateComponentRef.current.reverse();
|
|
98
|
+
if (animateChevronRef.current) {
|
|
99
|
+
if (showItems) animateChevronRef.current.start();else {
|
|
100
|
+
animateChevronRef.current.reverse();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (_reactNativeEssentials.isAndroid && !showItems) animateAndroidShadowRef.current?.reverse();
|
|
104
|
+
}, [showItems]);
|
|
105
|
+
return {
|
|
106
|
+
showItems,
|
|
107
|
+
setShowItems,
|
|
108
|
+
label,
|
|
109
|
+
canRenderDown,
|
|
110
|
+
relativeY,
|
|
111
|
+
scrollViewRef,
|
|
112
|
+
animateComponentRef,
|
|
113
|
+
animateChevronRef,
|
|
114
|
+
animateAndroidShadowRef,
|
|
115
|
+
pageYRef,
|
|
116
|
+
canRenderDownRef,
|
|
117
|
+
maxHeight,
|
|
118
|
+
handleLayout,
|
|
119
|
+
androidShadowAnimatedStyle,
|
|
120
|
+
androidShadowAnimationConfig,
|
|
121
|
+
scrollViewStyle,
|
|
122
|
+
selectionItemsListAnimatedStyle,
|
|
123
|
+
selectionItemsListAnimationConfig,
|
|
124
|
+
chevronAnimationConfig,
|
|
125
|
+
chevronAnimatedStyle,
|
|
126
|
+
unMountDelayInMilliSeconds
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=DropDownSelector.controller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_reactNativeEssentials","require","_react","DropDownSelectorController","props","showItems","setShowItems","useState","hasPageY","setHasPageY","screenHeight","relativeY","useDeviceOrientation","pageYRef","useRef","scrollViewRef","canRenderDownRef","animateChevronRef","animateComponentRef","animateAndroidShadowRef","unMountDelayInMilliSeconds","useMemo","expandAnimationConfig","type","duration","maxHeight","expandDistance","label","items","find","item","value","selectedItem","canRenderDown","expandDirection","current","distanceToBottom","androidShadowAnimationConfig","toValue","useNativeDriver","scrollViewStyle","overflow","minHeight","borderRadius","radiusSizes","soft","transform","translateY","chevronAnimationConfig","speed","bounciness","selectionItemsListAnimationConfig","chevronAnimatedStyle","useCallback","scaleY","handleLayout","e","currentTarget","measure","_x","_y","_width","_height","_pageX","pageY","containerProps","onLayout","androidShadowAnimatedStyle","opacity","right","left","top","bottom","position","boxShadow","selectionItemsListAnimatedStyle","useEffect","reverse","start","isAndroid"],"sourceRoot":"../../../src","sources":["DropDownSelector/DropDownSelector.controller.tsx"],"mappings":"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","ignoreList":[]}
|