@reo-tech/reo-expo-file-picker
v1.3.4
Published
A file picker component for Expo applications.
Downloads
189
Readme
ReoExpoFilePicker
ReoExpoFilePicker is a versatile React Native component designed for Expo applications, enabling seamless file and image selection with customizable options and intuitive user interactions.
Features
- Dual File Picking Modes:
- Tap (Single Press): Opens the camera to capture a new image or record a video.
- Long Press: Opens the device's media library (for images/videos) or document picker (for other file types like PDFs), based on the
documentTypeprop.
- Permission Handling: Automatically requests necessary permissions for camera, media library, or documents before attempting to access them.
- Haptic Feedback: Provides haptic feedback (vibration) on long press for an enhanced user experience.
- Customizable UI:
- Allows specifying custom text and styles for the picker button.
- Supports custom icons (e.g., from
MaterialCommunityIcons) for the button.
- File Type Specificity: The
documentTypeprop dictates whether to open the image gallery or the document picker on long press. - Callback for Selection: The
onFilesSelectedprop provides a callback function that receives an array of selected file URIs. - TypeScript Support: Written in TypeScript for better type safety and developer experience.
Installation
npm install reo-expo-file-picker
# or
yarn add reo-expo-file-pickerEnsure you have expo-image-picker, expo-document-picker, and react-native-vector-icons (if using custom icons) installed and configured in your Expo project.
expo install expo-image-picker expo-document-picker
# If using MaterialCommunityIcons or other icon sets
npm install react-native-vector-icons
# or
yarn add react-native-vector-iconsUsage
import React, { useState } from 'react';
import { View, Text, Image, StyleSheet } from 'react-native';
import ReoExpoFilePicker from 'reo-expo-file-picker';
import { MaterialCommunityIcons } from '@expo/vector-icons'; // Optional
export default function App() {
const [selectedFiles, setSelectedFiles] = useState<string[]>([]);
const handleFilesSelected = (uris: string[]) => {
console.log('Selected files:', uris);
setSelectedFiles(uris);
};
return (
<View style={styles.container}>
<Text style={styles.title}>ReoExpoFilePicker Demo</Text>
<ReoExpoFilePicker
onFilesSelected={handleFilesSelected}
buttonText="Select File"
buttonStyle={styles.customButton}
textStyle={styles.customButtonText}
documentType="image/*" // or "application/pdf", "all", etc.
// iconComponent={
// <MaterialCommunityIcons name="paperclip" size={24} color="white" />
// }
/>
<Text style={styles.infoText}>
Tap to open camera, Long press to open gallery/documents.
</Text>
{selectedFiles.length > 0 && (
<View style={styles.previewContainer}>
<Text style={styles.previewTitle}>Selected Files:</Text>
{selectedFiles.map((uri, index) => (
<View key={index} style={styles.filePreview}>
{uri.startsWith('file:') && (uri.endsWith('.jpg') || uri.endsWith('.png') || uri.endsWith('.jpeg')) ? (
<Image source={{ uri }} style={styles.imagePreview} />
) : (
<Text>{uri.split('/').pop()}</Text>
)}
</View>
))}
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
backgroundColor: '#f0f0f0',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 20,
},
customButton: {
backgroundColor: '#007AFF',
paddingHorizontal: 20,
paddingVertical: 12,
borderRadius: 8,
flexDirection: 'row',
alignItems: 'center',
},
customButtonText: {
color: 'white',
fontSize: 16,
marginLeft: 8, // If using an icon
},
infoText: {
marginTop: 15,
fontSize: 12,
color: 'gray',
},
previewContainer: {
marginTop: 30,
alignItems: 'center',
},
previewTitle: {
fontSize: 18,
fontWeight: 'bold',
marginBottom: 10,
},
filePreview: {
marginVertical: 5,
},
imagePreview: {
width: 100,
height: 100,
resizeMode: 'contain',
borderRadius: 5,
},
});Props
| Prop | Type | Required | Default | Description |
| ----------------- | ----------------------------------------- | -------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| onFilesSelected | (uris: string[]) => void | Yes | - | Callback function triggered when files are selected. Returns an array of file URIs. |
| documentType | string | Yes | - | The type of document to pick on long press (e.g., "image/", "application/pdf", "audio/", "/" for all). Determines picker behavior. |
| buttonText | string | No | "Select File" | Text displayed on the picker button. |
| buttonStyle | StyleProp<ViewStyle> | No | { backgroundColor: 'blue', padding: 10 } | Custom styles for the button container. |
| textStyle | StyleProp<TextStyle> | No | { color: 'white' } | Custom styles for the button text. |
| iconComponent | React.ReactNode | No | null | Optional icon component (e.g., from @expo/vector-icons) to display on the button. |
| allowMultiple | boolean | No | false | (For Document Picker) Whether to allow multiple file selection. |
| maxFileSize | number | No | undefined | (For Image Picker) Maximum file size in bytes for selected images. |
| mediaTypes | ImagePicker.MediaTypeOptions | No | ImagePicker.MediaTypeOptions.All | (For Image Picker - camera) Media types to allow when capturing (Images, Videos, All). |
| videoMaxDuration| number | No | undefined | (For Image Picker - camera) Maximum duration for recorded videos in seconds. |
| quality | 0 \| 0.1 \| ... \| 1 | No | 0.2 | (For Image Picker) Compression quality for images (0 to 1). |
| base64 | boolean | No | false | (For Image Picker) Whether to include base64 encoded image data in the result. |
| exif | boolean | No | false | (For Image Picker) Whether to include EXIF data for images. |
Note: Some props like maxFileSize, mediaTypes, videoMaxDuration, quality, base64, exif are specific to expo-image-picker and apply when the camera or image library is launched.
The allowMultiple prop is specific to expo-document-picker.
How it Works
- Single Tap:
- Requests camera permissions (
ImagePicker.requestCameraPermissionsAsync). - If granted, launches the device camera (
ImagePicker.launchCameraAsync). - Selected media URI is passed to
onFilesSelected.
- Requests camera permissions (
- Long Press:
- Checks
documentType:- If
documentTypeindicates images (e.g., "image/*", "image/jpeg"), it requests media library permissions (ImagePicker.requestMediaLibraryPermissionsAsync). - Otherwise, it requests document picker permissions (implicitly handled by
DocumentPicker.getDocumentAsync).
- If
- If permissions are granted, vibrates the device (
Vibration.vibrate()). - Launches the appropriate picker:
ImagePicker.launchImageLibraryAsyncfor images.DocumentPicker.getDocumentAsyncfor other document types.
- Selected file URI(s) are passed to
onFilesSelected.
- Checks
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository.
- Create your feature branch (
git checkout -b feature/AmazingFeature). - Commit your changes (
git commit -m 'Add some AmazingFeature'). - Push to the branch (
git push origin feature/AmazingFeature). - Open a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details (if available, otherwise assume MIT).
