{"id":25436948,"url":"https://github.com/mdjfs/expo-image-multiple-picker","last_synced_at":"2026-03-05T08:30:55.191Z","repository":{"id":54668877,"uuid":"473842605","full_name":"mdjfs/expo-image-multiple-picker","owner":"mdjfs","description":"Fully customizable image picker for react native","archived":false,"fork":false,"pushed_at":"2025-07-29T18:02:22.000Z","size":2567,"stargazers_count":18,"open_issues_count":7,"forks_count":8,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-11T10:51:31.042Z","etag":null,"topics":["customizable","expo","image","library","media","multiple","picker","react-native","typescript"],"latest_commit_sha":null,"homepage":"https://npmjs.com/expo-image-multiple-picker","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mdjfs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-03-25T02:30:52.000Z","updated_at":"2025-07-29T18:02:27.000Z","dependencies_parsed_at":"2025-09-09T06:20:51.075Z","dependency_job_id":"17bbba39-3d7d-49b7-af37-441c3382db22","html_url":"https://github.com/mdjfs/expo-image-multiple-picker","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mdjfs/expo-image-multiple-picker","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdjfs%2Fexpo-image-multiple-picker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdjfs%2Fexpo-image-multiple-picker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdjfs%2Fexpo-image-multiple-picker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdjfs%2Fexpo-image-multiple-picker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mdjfs","download_url":"https://codeload.github.com/mdjfs/expo-image-multiple-picker/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mdjfs%2Fexpo-image-multiple-picker/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30115910,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-05T08:19:04.902Z","status":"ssl_error","status_checked_at":"2026-03-05T08:17:37.148Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["customizable","expo","image","library","media","multiple","picker","react-native","typescript"],"created_at":"2025-02-17T08:31:24.923Z","updated_at":"2026-03-05T08:30:55.125Z","avatar_url":"https://github.com/mdjfs.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Expo Images Picker\n\nFully customizable image picker for react native,\nto select one or multiple images\n\n\u003e **Nice features for 4.7.0 version!** More information at the bottom\n\n![Image](https://imgur.com/lRkMQgk.png)\n\n## Demo\n\n[Expo Snack Demo](https://snack.expo.dev/@marvin_mmm/expo-image-multiple-picker-demo)\n\n## Installation\n\nInstall with expo\n\n```bash\n  expo install expo-image-multiple-picker react-native-svg expo-media-library\n```\n\nor npm\n\n```bash\n  npm i expo-image-multiple-picker react-native-svg expo-media-library\n```\n\nor yarn\n\n```bash\n  yarn add expo-image-multiple-picker react-native-svg expo-media-library\n```\n\n## Usage/Examples\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  return (\n    \u003cImagePicker\n      onSave={(assets) =\u003e console.log(assets)}\n      onCancel={() =\u003e console.log('no permissions or user go back')}\n    /\u003e\n  )\n}\n```\n\nThis will show the image picker to select the album\nand then select the images\n\nThe image picker calls `onSave` when the user selects the images\nand calls `onCancel` when don't have permissions or the user wants to go back without select\n\n#### Multiple Selection\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  return (\n    \u003cImagePicker\n      onSave={(assets) =\u003e console.log(assets)}\n      onCancel={() =\u003e console.log('no permissions or user go back')}\n      multiple\n    /\u003e\n  )\n}\n```\n\nThe `multiple` property will allow multiple selection\n\n#### Select from all sources\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  return (\n    \u003cImagePicker\n      onSave={(assets) =\u003e console.log(assets)}\n      onCancel={() =\u003e console.log('no permissions or user go back')}\n      noAlbums\n    /\u003e\n  )\n}\n```\n\nThe `noAlbums` property will open the gallery without selecting album, showing all the images on the phone\n\n#### Selection limit\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  return (\n    \u003cImagePicker\n      onSave={(assets) =\u003e console.log(assets)}\n      onCancel={() =\u003e console.log('no permissions or user go back')}\n      limit={5}\n    /\u003e\n  )\n}\n```\n\nThe `limit` property will limit the number of images selected\n\n#### Common usage\n\nUsually, you want render the picker conditionally inside your logic, there is an example:\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  const [open, setOpen] = useState(false)\n\n  if (open) {\n    return (\n      \u003cImagePicker\n        onSave={(assets) =\u003e {\n          doWhatEverWithTheAssets(assets)\n          setOpen(false)\n        }}\n        onCancel={() =\u003e {\n          doWhatEverWhenYourUserSucks()\n          setOpen(false)\n        }}\n      /\u003e\n    )\n  }\n\n  return (\n    \u003cView\u003e\n      \u003cText\u003eHello Mars!\u003c/Text\u003e\n    \u003c/View\u003e\n  )\n}\n```\n\n_Important Note_\n\nReact Native doesn't provide **fixed** containers. Then, obviously, ensure when you render the picker, is the\nunique element on the phone. For `stack screens` you will need the `headerShown: false`\n\n#### (Advanced) Track album and selected assets\n\nWe can know and track the album and selected assets. And also call the picker which specific Album or\nselected assets. There is a common way to do that:\n\n```jsx\nimport { ImagePicker, Album, Asset } from 'expo-image-multiple-picker'\n\nfunction App() {\n  const [open, setOpen] = useState(false)\n  const [album, setAlbum] = useState\u003cAlbum | undefined\u003e()\n  const [assets, setAssets] = useState\u003cAsset[]\u003e([])\n\n  if (open) {\n    return (\n      \u003cImagePicker\n        onSave={(assets) =\u003e {\n          setAssets(assets)\n          setOpen(false)\n        }}\n        onCancel={() =\u003e {\n          setAssets([])\n          setAlbum(undefined)\n          setOpen(false)\n        }}\n        onSelectAlbum={(album) =\u003e setAlbum(album)}\n        selected={assets}\n        selectedAlbum={album}\n      /\u003e\n    )\n  }\n\n  return (\n    \u003cView\u003e\n      \u003cText\u003eHello Pluto!\u003c/Text\u003e\n    \u003c/View\u003e\n  )\n}\n```\n\n_Important Note_\n\nReact Native doesn't provide **fixed** containers. Then, obviously, ensure when you render the picker, is the\nunique element on the phone. For `stack screens` you will need the `headerShown: false`\n\n## Customizing\n\n#### Change number of columns in the album or photo viewer\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  return (\n    \u003cImagePicker\n      onSave={(assets) =\u003e console.log(assets)}\n      onCancel={() =\u003e console.log('no permissions or user go back')}\n      galleryColumns={3}\n      albumColumns={3}\n    /\u003e\n  )\n}\n```\n\nThe `galleryColumns` property will change the number of columns in the image viewer\n\nThe `albumColumns` property will change the number of columns in the album viewer\n\nObviously, there is no selection limit, this is how the image selector looks like with 32 columns (and it works):\n\n![Image](https://imgur.com/nURr9g2.png)\n\n## Theming\n\nLet's make a Whats App style image picker theme\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  return (\n    \u003cImagePicker\n      theme={{\n        header: WhatsAppHeader,\n        album: WhatsAppAlbum,\n        check: WhatsAppCheck,\n      }}\n      onSave={(assets) =\u003e console.log(assets)}\n      onCancel={() =\u003e console.log('no permissions or user go back')}\n      galleryColumns={4}\n      multiple\n    /\u003e\n  )\n}\n```\n\nLooks like\n\n![Image](https://imgur.com/NLBOi7F.png)\n\n---\n\nThe `theme` property will take three optionals components:\n\n- header\n\nIt is the navigator, and its props is the `HeaderData` interface\n\n```ts\ntype Album = MediaLibrary.Album\n\ninterface HeaderData {\n  view: Views\n  goToAlbum?: () =\u003e void\n  imagesPicked: number\n  multiple: boolean\n  picked: boolean\n  album?: Album\n  noAlbums: boolean\n  save?: () =\u003e void\n}\n```\n\nImportant note: The header must have a fixed height, if it resizes when selected the first time, you will experience a nasty scroll top\n\n- album\n\nIt is the one who renders the images of the album viewer, and its props is the `AlbumData` interface\n\n```ts\ntype Asset = MediaLibrary.Asset\ntype Album = MediaLibrary.Album\n\ninterface AlbumData {\n  thumb: Asset\n  album: Album\n  goToGallery: (album: Album) =\u003e void\n}\n```\n\nImportant note: If the album doesn't have a fixed height, it just won't show.\n\n- check\n\nIt is the component that is displayed when a photo has been selected, has no props\n\n---\n\nHere it is the code of the components for the WhatsApp Theme:\n\n```jsx\nconst WhatsAppHeader = (props: HeaderData) =\u003e {\n  return (\n    \u003cView\n      style={{\n        paddingTop: 40,\n        padding: 10,\n        height: 80,\n        width: '100%',\n        backgroundColor: '#252f39',\n        flexDirection: 'row',\n        justifyContent: 'space-between',\n        alignItems: 'center',\n      }}\n    \u003e\n      {props.view == 'album' \u0026\u0026 (\n        \u003cText style={{ color: 'white', fontSize: 20 }}\u003eSelect an album\u003c/Text\u003e\n      )}\n      {props.view == 'gallery' \u0026\u0026 (\n        \u003c\u003e\n          \u003cTouchableOpacity onPress={props.goToAlbum}\u003e\n            \u003cIonIcon name='arrow-back' size={30} color='#EDF8F5' /\u003e\n          \u003c/TouchableOpacity\u003e\n          {props.imagesPicked \u003e 0 \u0026\u0026 (\n            \u003c\u003e\n              \u003cText style={{ color: 'white', fontSize: 20 }}\u003e\n                {props.imagesPicked} selected\n              \u003c/Text\u003e\n              \u003cTouchableOpacity onPress={props.save}\u003e\n                \u003cText style={{ color: 'white', fontSize: 16 }}\u003eOK\u003c/Text\u003e\n              \u003c/TouchableOpacity\u003e\n            \u003c/\u003e\n          )}\n        \u003c/\u003e\n      )}\n    \u003c/View\u003e\n  )\n}\n```\n\n```ts\nconst WhatsAppAlbum = (props: AlbumData) =\u003e {\n  return (\n    \u003cTouchableOpacity\n      onPress={() =\u003e props.goToGallery(props.album)}\n      style={{ flex: 1, height: 200 }}\n    \u003e\n      \u003cImage\n        source={{ uri: props.thumb.uri }}\n        style={{ width: '100%', height: '100%' }}\n        blurRadius={10}\n      \u003e\u003c/Image\u003e\n      \u003cView\n        style={{\n          position: 'absolute',\n          width: '100%',\n          height: '100%',\n          backgroundColor: 'rgba(0,0,0,0.2)',\n          justifyContent: 'flex-end',\n        }}\n      \u003e\n        \u003cView style={{ padding: 5, flexDirection: 'row' }}\u003e\n          \u003cEntypoIcon name='folder' color='white' size={16} /\u003e\n          \u003cText\n            style={{\n              color: 'white',\n              fontSize: 16,\n              marginLeft: 5,\n            }}\n          \u003e\n            {props.album.title}\n          \u003c/Text\u003e\n        \u003c/View\u003e\n      \u003c/View\u003e\n    \u003c/TouchableOpacity\u003e\n  )\n}\n```\n\n```ts\nconst WhatsAppCheck = () =\u003e {\n  return (\n    \u003cView\n      style={{\n        width: '100%',\n        height: '100%',\n        alignItems: 'center',\n        justifyContent: 'center',\n        backgroundColor: 'rgba(0,0,0,0.4)',\n      }}\n    \u003e\n      \u003cFeatherIcon color='white' name='check' size={32} /\u003e\n    \u003c/View\u003e\n  )\n}\n```\n\n## 4.7.0 Features\n\nIt had been a while without updating the library or touching react native code. But when i realized that the community\nreally uses this library, with the downloads increasing, issues, feedback, pull request. Was amazing. I love that feedback.\n\nThen, after writing a lot of sweet things, there is the updates:\n\n### + Performance\n\nWith the new version of expo-media-library (15.0.0) fetching assets is more faster! And with that, for every fetch, the picker\ncan fetch until `70` images per time! x3.5 more than old version fetching 20 images per time... (Anyway, its more noticeable with a large number of galleryColumns) (use the last version of expo-media-library if you want this speed)\n\n### Video Support\n\nYes! We needed that from the start\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  return (\n    \u003cImagePicker\n      onSave={(assets) =\u003e console.log(assets)}\n      onCancel={() =\u003e console.log('no permissions or user go back')}\n      video\n    /\u003e\n  )\n}\n```\n\nThe `video` property will make it possible to select videos in addition to images\n\nAlso, the component rendered in a video asset is customizable.\nThe `theme` property will receive `video` param. This param accept\na function with an asset argument returning the JSX.Element\n\n### Only Select Videos\n\nDisplay an image picker just to select videos\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  return (\n    \u003cImagePicker\n      onSave={(assets) =\u003e console.log(assets)}\n      onCancel={() =\u003e console.log('no permissions or user go back')}\n      video\n      image={false}\n    /\u003e\n  )\n}\n```\n\nThe `image` boolean property is true by default, just set the `video` property true and the `image` property false\n\n### Time Slider\n\nDo you remember when you select an asset. Then you need uncheck that asset but hey.\nYou don't remember where is it. Then you need search in the gallery where is it.\n\nSay GOODBYE to the old times. Now we have a **Time Slider**\n\n![Image](https://imgur.com/6OjEvfb.jpg)\n\nSimilar to google photos time slider, but with a difference, shows the current assets picked and their position, to find them\nin an easy way\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  return (\n    \u003cImagePicker\n      onSave={(assets) =\u003e console.log(assets)}\n      onCancel={() =\u003e console.log('no permissions or user go back')}\n      timeSlider\n    /\u003e\n  )\n}\n```\n\nThe `timeSlider` will enable the default time slider for the picker\n\nIf you want use your own custom time slider, there is some tips:\n\n```jsx\nimport { ImagePicker } from 'expo-image-multiple-picker'\n\nfunction App() {\n  return (\n    \u003cImagePicker\n      onSave={(assets) =\u003e console.log(assets)}\n      onCancel={() =\u003e console.log('no permissions or user go back')}\n      timeSlider\n      timeSliderHeight={500}\n    /\u003e\n  )\n}\n```\n\nThe `timeSliderHeight` will adjust the height for the slider\n\nBuild your own Custom Slider:\n\n```ts\ninterface SliderItem {\n  date: Date\n  top: number\n  styles?: ViewStyle\n}\n\ninterface SliderBalloon extends SliderItem {\n  quantity: number\n}\n\nexport interface SliderData {\n  balloons: SliderBalloon[]\n  button?: SliderItem\n  height: number\n  isMoving: boolean\n  buttonProps?: ViewProps\n}\n```\n\nThe `theme` property will receive `slider` param. This param accept\na function with an `SliderData` argument returning the JSX.Element\n\n## Under the hood\n\nThis image picker uses `expo-media-library` under the hood to fetch the photos from the phone\n\nThen it uses FlatList to render the images and does mathematical calculations according to the columns to know what size they will be\n\nThe most important thing in the development was to avoid unnecessary rendering and to minimize the rendered components while scrolling\n\nFinally, if I am doing the documentation, it is because it has had an acceptable performance\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdjfs%2Fexpo-image-multiple-picker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmdjfs%2Fexpo-image-multiple-picker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmdjfs%2Fexpo-image-multiple-picker/lists"}