motorinc-media-picker
v1.0.6
Published
A comprehensive React Native media gallery picker with smooth animations, multi-select, single-select, crop functionality, and native iOS/Android support
Maintainers
Readme
MotorInc Media Picker
A comprehensive React Native media gallery picker with smooth animations, multi-select/single-select modes, crop functionality, and native iOS/Android support.
Features
- 🖼️ Modern UI - Smooth scrolling with layered animations
- 📱 Native Performance - Built with native iOS and Android modules
- ✨ Multi/Single Select - Flexible selection modes
- ✂️ Crop Functionality - Built-in image cropping with aspect ratio controls
- 🎬 Video Support - Handle both images and videos
- 🎯 Gesture Controls - Intuitive touch gestures and animations
- 📐 Aspect Ratios - Support for multiple aspect ratios (0.8, 16:9, 1:1)
- 🔄 Permission Handling - Smart permission management
- 📤 Export Options - Base64, URI, and file data support
Installation
npm install motorinc-media-pickeriOS Setup
For React Native 0.60+ (Automatic Linking):
cd ios && pod installFor React Native < 0.60 (Manual Linking):
- Add to your
Podfile:
pod 'MotorincMediaPicker', :path => '../node_modules/motorinc-media-picker'- Run:
cd ios && pod installAndroid Setup
The Android module is automatically linked with React Native 0.60+.
Dependencies
Make sure you have these peer dependencies installed:
npm install react-native-gesture-handler react-native-reanimated react-native-view-shotFollow the setup instructions for:
Usage
Basic Usage
import React from 'react';
import { View } from 'react-native';
import { MainPhotoGallery } from 'motorinc-media-picker';
export default function App() {
const handleAssetSelected = (asset) => {
console.log('Selected asset:', asset);
};
const handleSelectedAssetsChange = (assets) => {
console.log('Selected assets:', assets);
};
return (
<View style={{ flex: 1 }}>
<MainPhotoGallery
mediaType="all"
multiSelect={true}
maxSelectionLimit={10}
onAssetSelected={handleAssetSelected}
onSelectedAssetsChange={handleSelectedAssetsChange}
/>
</View>
);
}Advanced Usage with Crop
import React, { useRef, useState } from 'react';
import { View, Button } from 'react-native';
import { MainPhotoGallery } from 'motorinc-media-picker';
export default function App() {
const galleryRef = useRef(null);
const [selectedAssets, setSelectedAssets] = useState([]);
const [cropParams, setCropParams] = useState(new Map());
const handleCroppedImagesReady = (croppedImages) => {
console.log('Cropped images:', croppedImages);
};
const handleCropCapture = async () => {
if (galleryRef.current) {
await galleryRef.current.triggerCropCapture();
}
};
return (
<View style={{ flex: 1 }}>
<MainPhotoGallery
ref={galleryRef}
mediaType="image"
multiSelect={true}
selectedAssets={selectedAssets}
onSelectedAssetsChange={setSelectedAssets}
showSelectedAssetsHeader={true}
onCropParamsChange={(assetId, params) => {
setCropParams(prev => new Map(prev.set(assetId, params)));
}}
existingCropParams={cropParams}
onCroppedImagesReady={handleCroppedImagesReady}
onAspectRatioChange={(ratio) => console.log('Aspect ratio:', ratio)}
/>
<Button title="Capture Cropped Images" onPress={handleCropCapture} />
</View>
);
}Props
MainPhotoGallery Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| mediaType | 'image' \| 'video' \| 'all' | 'all' | Type of media to display |
| multiSelect | boolean | false | Enable multi-selection mode |
| maxSelectionLimit | number | 10 | Maximum number of assets that can be selected |
| selectedAssets | PhotoAsset[] | [] | Currently selected assets |
| onAssetSelected | (asset: PhotoAsset) => void | - | Callback when a single asset is selected |
| onSelectedAssetsChange | (assets: PhotoAsset[]) => void | - | Callback when selected assets change |
| showSelectedAssetsHeader | boolean | false | Show cropping header for selected assets |
| hideSelectionHeader | boolean | false | Hide the selection mode header |
| onCropParamsChange | (assetId: string, params: CropParams \| null) => void | - | Callback for crop parameter changes |
| existingCropParams | Map<string, CropParams> | - | Existing crop parameters |
| onAspectRatioChange | (ratio: number) => void | - | Callback for aspect ratio changes |
| onCroppedImagesReady | (images: Array<{assetId: string, dataUri: string}>) => void | - | Callback when cropped images are ready |
| onCancel | () => void | - | Cancel button callback |
| onNext | (assets: PhotoAsset[]) => void | - | Next button callback |
| renderPermissionDeniedState | (onRequest?: () => void) => React.ReactNode | - | Custom permission denied state |
Types
PhotoAsset
interface PhotoAsset {
id: string;
uri: string;
filename: string;
width: number;
height: number;
creationDate: number;
mediaType: 'image' | 'video';
duration?: number; // For videos
}CropParams
interface CropParams {
x: number;
y: number;
width: number;
height: number;
scale: number;
aspectRatio: number;
}SelectedImage
interface SelectedImage {
uri: string;
fileName: string;
fileSize: number;
width: number;
height: number;
type: string;
id: string;
base64: string;
}Layered Scroll Behavior
The gallery implements smooth layered scroll behavior:
- Scroll Up: First hides the header section, then allows grid scrolling
- Scroll Down: Grid scrolls down immediately, regardless of header position
- Header Drag: Can always drag header up/down to show/hide sections
- Smooth Animations: Cubic easing for natural feel
Permissions
iOS
Add to your Info.plist:
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to photo library to select images</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs access to save images to photo library</string>Android
Add to your AndroidManifest.xml:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />Changelog
v1.0.6
- HOTFIX: Fixed podspec naming issue that caused "No podspec found for
MotorincMediaPicker" error - FIXED: Aligned pod name with file name for proper React Native auto-linking
- RESOLVED: CocoaPods integration now works seamlessly with
pod install
v1.0.5
- CRITICAL FIX: Fixed React Native auto-linking issues - resolved "package doesn't seem to be linked" error
- FIXED: Created proper
motorinc-media-picker.podspecfile for iOS integration - FIXED: Updated React Native configuration files for seamless automatic linking
- IMPROVED: Now works with React Native 0.60+ automatic linking without manual intervention
v1.0.4
- FIXED: iOS nullability error for
getImageForAssetNSNumber parameters - resolves React Native iOS compilation warnings - ENHANCED:
suppressLimitedAccessAlerthandling - now properly delays photo library access by 2 seconds when set totruewith limited photo access status - ADDED: Auto-trigger permission request on first render when permission is denied or not determined
- ADDED: New native method
preventLimitedAccessPopup()for better limited access guidance - IMPROVED: Better handling of iOS limited photo access popup after app restart
v1.0.3
- Fixed: iOS NSNumber nullability error in
getImageForAssetmethod - Added:
suppressLimitedAccessAlertprop to MainPhotoGallery for better iOS limited access handling - Improved: React Native compatibility with explicit nullable annotations
v1.0.2
- Initial stable release
Contributing
Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.
License
MIT
Support
If you like this project, please consider giving it a ⭐ on GitHub!
