npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

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

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-picker

iOS Setup

For React Native 0.60+ (Automatic Linking):

cd ios && pod install

For React Native < 0.60 (Manual Linking):

  1. Add to your Podfile:
pod 'MotorincMediaPicker', :path => '../node_modules/motorinc-media-picker'
  1. Run:
cd ios && pod install

Android 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-shot

Follow 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.podspec file 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 getImageForAsset NSNumber parameters - resolves React Native iOS compilation warnings
  • ENHANCED: suppressLimitedAccessAlert handling - now properly delays photo library access by 2 seconds when set to true with 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 getImageForAsset method
  • Added: suppressLimitedAccessAlert prop 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!