Skip to content

nandorojo/galeria

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Galeria πŸ“·

An image viewer for React (+ Native). It works with any image component - bring your own image component (BYOICβ„’)

galeria.shorter-2.mp4

The video makes Web look a bit weird, but don't worry. Here is why – it's just because of FlashList's Masonry List, which wraps the views with additional cells breaking z-index. But it isn't a fundamental Galeria issue.

Features

  • Shared element transitions
  • Pinch to zoom
  • Double tap to zoom
  • Pan to close
  • Multi-image support
  • React Native Modal support
  • FlashList support
  • Clean API
  • Web support
  • Remote URLs & local images
  • New Architecture support
  • Supports different images when collapsed and expanded
    • This lets you show smaller thumbnails with higher resolution expanded images
  • Works with any image component
    • <Image /> from react-native
    • <SolitoImage /> from solito/image
    • <Image /> from next/image
    • <Image /> from expo-image
    • <FastImage /> from react-native-fast-image
    • <img /> on web
    • ...etc

For iOS and Android, the implementation uses Swift (ImageViewer.swift) and Kotlin (imageviewer) respectively – see credits.

Web support is a simplified version of the native experience powered by Framer Motion. It currently supports a single image at a time.

Resources

Usage

One Image

import { Galeria } from '@nandorojo/galeria'
import { Image } from 'react-native' // works with ANY image component!

const url = 'https://my-image.com/image.jpg'

export const SingleImage = ({ style }) => (
  <Galeria urls={[url]}>
    <Galeria.Image>
      <Image source={{ uri: url }} style={style} />
    </Galeria.Image>
  </Galeria>
)

Multiple Images

Simply pass an array to urls.

import { Galeria } from '@nandorojo/galeria'
import { Image } from 'react-native' // works with ANY image component!

import localImage from './assets/local-image.png'

const urls = ['https://my-image.com/image.jpg', localImage]

export const MutliImage = ({ style }) => (
  <Galeria urls={urls}>
    {urls.map((url, index) => (
       <Galeria.Image index={index} key={...}>
         <Image source={typeof url === 'string' ? { uri: url } : url} style={style} />
       </Galeria.Image>
     )}
  </Galeria>
)

Dark Mode

import { Galeria } from '@nandorojo/galeria'

export const DarkMode = () => (
  <Galeria urls={urls} theme="dark">
    ...
  </Galeria>
)

FlashList

import { Galeria } from '@nandorojo/galeria'
import { Image, type ImageAssetSource } from 'react-native' // works with ANY image component!
import { FlashList } from '@shopify/flash-list'

import localImage from './assets/local-image.png'

const urls = ['https://my-image.com/image.jpg', localImage]
const size = 100
export const FlashListSupport = () => {
  return (
    <Galeria urls={urls}>
      <FlashList
        data={urls}
        renderItem={({ item, index }) => {
          // you should put this in a memoized component
          return (
            <Galeria.Image index={index}>
              <Image
                style={styles.image}
                source={src(item)}
                recyclingKey={item + index}
                style={{ width: size, height: size }}
              />
            </Galeria.Image>
          )
        }}
        numColumns={3}
        estimatedItemSize={size}
        keyExtractor={(item, i) => item + i}
      />
    </Galeria>
  )
}

const src = (s) => (typeof s === 'string' ? { uri: s } : s) // πŸ€·β€β™‚οΈ

Plain Web Support

Galeria does not use any React Native code on the web. It is a pure React component library.

So you can even use <img /> if you want to only use it on web.

import { Galeria } from '@nandorojo/galeria'

const urls = ['https://my-image.com/image.jpg']

export const WebSupport = () => (
  <Galeria urls={urls}>
    <Galeria.Image>
      <img src={urls[0]} width={100} height={100} />
    </Galeria.Image>
  </Galeria>
)

Solito Image

import { SolitoImage } from 'solito/image'

const urls = ['https://my-image.com/image.jpg']

export const SolitoSupport = () => (
  <Galeria urls={urls}>
    <Galeria.Image>
      <SolitoImage src={urls[0]} />
    </Galeria.Image>
  </Galeria>
)

Next.js Image

'use client'
import { Galeria } from '@nandorojo/galeria'
import Image from 'next/image'

const urls = ['https://my-image.com/image.jpg']

export const NextJS = () => (
  <Galeria urls={urls}>
    <Galeria.Image>
      <Image
        src={urls[0]}
        width={100}
        height={100}
        // edit these props for your use case
        unoptimized
      />
    </Galeria.Image>
  </Galeria>
)

Expo Image

import { Galeria } from '@nandorojo/galeria'
import { Image } from 'expo-image'

const urls = ['https://my-image.com/image.jpg']

export const ExpoImage = () => (
  <Galeria urls={urls}>
    <Galeria.Image>
      <Image source={urls[0]} style={{ width: 100, height: 100 }} />
    </Galeria.Image>
  </Galeria>
)

React Native Fast Image

import { Galeria } from '@nandorojo/galeria'
import FastImage from 'react-native-fast-image'

const urls = ['https://my-image.com/image.jpg']

export const FastImage = () => (
  <Galeria urls={urls}>
    <Galeria.Image>
      <FastImage
        source={{ uri: urls[0] }}
        style={{ width: 100, height: 100 }}
      />
    </Galeria.Image>
  </Galeria>
)

Installation

yarn add @nandorojo/galeria

# or

npm i @nandorojo/galeria

Next.js / Solito

Add @nandorojo/galeria to transpilePackages in your next.config.js.

module.exports = {
  transpilePackages: ['@nandorojo/galeria'],
}

Expo

Galeria uses native libraries on iOS and Android, so it does not work with Expo Go. You will need to use a dev client.

After installing it, rebuild your native code:

npx expo prebuild
npx expo run:ios # or npx expo run:android

Credits

  • Under the hood, Galeria uses native libraries on iOS and Android.
  • On Web, Galeria uses Framer Motion.
  • Thanks to Michael Henry for the iOS Image Viewer
  • Thanks to iielse for the Android Image Viewer
  • Thanks to Alan for building the Android integration.
Screenshot 2024-05-23 at 1 02 03β€―PM