react-photoswipe-gallery
react-photoswipe-gallery
npm i react-photoswipe-gallery
react-photoswipe-gallery

react-photoswipe-gallery

πŸ™ React component wrapper around PhotoSwipe

by dromru

2.2.3 (see all)License:MITTypeScript:Built-In
Categories:React Gallery
npm i react-photoswipe-gallery
Readme

react-photoswipe-gallery

codecov npm

A configurable and flexible React component wrapper around PhotoSwipe.

ℹ️ react-photoswipe-gallery v2 only works with PhotoSwipe v5 and above. Use v1 for PhotoSwipe <= 4.

Basic Usage

import 'photoswipe/dist/photoswipe.css'

import { Gallery, Item } from 'react-photoswipe-gallery'

const MyGallery = () => (
  <Gallery>
    <Item
      original="https://placekitten.com/1024/768?image=1"
      thumbnail="https://placekitten.com/80/60?image=1"
      width="1024"
      height="768"
    >
      {({ ref, open }) => (
        <img ref={ref} onClick={open} src="https://placekitten.com/80/60?image=1" />
      )}
    </Item>
    <Item
      original="https://placekitten.com/1024/768?image=2"
      thumbnail="https://placekitten.com/80/60?image=2"
      width="1024"
      height="768"
    >
      {({ ref, open }) => (
        <img ref={ref} onClick={open} src="https://placekitten.com/80/60?image=2" />
      )}
    </Item>
  </Gallery>
)

Demo

Check out the Storybook to see it in action πŸš€

Stories are written as real-world examples, so you can see them at the bottom of Storybook UI in the Story tab. Or browse the source code on GitHub. It covers most of the use-cases and provides examples for configuration options.

Installation

yarn add photoswipe react-photoswipe-gallery

or

npm install photoswipe react-photoswipe-gallery --save

Hash Navigation

You should pass a unique id prop to <Gallery /> component, to enable hash navigation.

Optionally, you can also pass the id to <Item /> component. Otherwise, the index will be used.

const MyGallery = () => (
  <Gallery id="my-gallery">
    <Item
      id="first-pic"
      {/*...*/}
    />
    <Item
      id="second-pic"
      {/*...*/}
    />
  </Gallery>
)

Example

Captions

If you want to add captions to your slides, you need to pass withCaption prop to the <Gallery /> and pass caption prop to each <Item />. It accepts html as well. If caption isn't provided - it will use alt prop.

const MyGallery = () => (
  <Gallery withCaption>
    <Item
      caption="Foo"
      {/*...*/}
    />
    <Item
      alt="Bar"
      {/*...*/}
    />
  </Gallery>
)

Example

Plugins

You can use native PhotoSwipe plugins with plugins prop. It accepts the function in which you should register all of your plugins, providing pswpLightbox to the plugin constructor.

Example for photoswipe-dynamic-caption-plugin:

import 'photoswipe-dynamic-caption-plugin/photoswipe-dynamic-caption-plugin.css'
import PhotoSwipeDynamicCaption from 'photoswipe-dynamic-caption-plugin'

const MyGallery = () => (
  <Gallery
      plugins={(pswpLightbox) => {
        // register plugin
        const captionPlugin = new PhotoSwipeDynamicCaption(pswpLightbox, {
          captionContent: (slide) => slide.data.alt,
        })

        // register another plugin
        // ...
      }}
  >
    {/*...*/}
  </Gallery>
)

Example

Custom UI Elements

You can add custom UI elements to PhotoSwipe with uiElements prop. It accepts an array of configuration objects for custom UI elements.

const uiElements = [
  // add custom UI element
  {
    name: 'custom-button',
    ariaLabel: 'Custom button',
    order: 9,
    isButton: true,
    html: {
      isCustomSVG: true,
      inner:
        '<path d="<ICON_PATH>" id="pswp__icn-cstm-btn"/>',
      outlineID: 'pswp__icn-cstm-btn',
    },
    appendTo: 'bar',
    onInit: (el, pswpInstance) => {
      // do something on UI element's init event
    },
    onClick: (e, el, pswpInstance) => {
      // do something on UI element's click event
    },
  },

  // add another custom UI element
  // ...
]

const MyGallery = () => (
  <Gallery uiElements={uiElements}>
    {/*...*/}
  </Gallery>
)

Example

Custom slide content

You can add your own custom slide content with content and html props.

const MyGallery = () => (
  <Gallery>
    <Item
      content={<h1>Hi!</h1>}
      {/*...*/}
    />
    <Item
      html="<h1>Hi!</h1>"
      {/*...*/}
    />
  </Gallery>
)

Example

Access to Photoswipe instance

If you need to get access to Photoswipe instance (for example, to subscribe on Photoswipe events or call some Photoswipe method), you can do it via onOpen and onBeforeOpen props of Gallery component.

onBeforeOpen triggers before PhotoSwipe.init() call.

onOpen triggers after PhotoSwipe.init() call.

onBeforeOpen and onOpen will receive PhotoSwipe instance as the first argument.

const onBeforeOpen = (pswpInstance) => {
  pswpInstance.on('change', () => {
    console.log('slide was changed')
  })
}

const onOpen = (pswpInstance) => {
  pswpInstance.currSlide.zoomTo(
    1,
    { x: 0, y: 0 },
    2000,
    false
  )
}

const MyGallery = () => (
  <Gallery onBeforeOpen={onBeforeOpen} onOpen={onOpen}>
    {/*...*/}
  </Gallery>
)

Props

PropTypeRequiredDescription
idNumber or Stringβœ“ (for hash navigation)Item ID, for hash navigation
optionsObjectPhotoSwipe options
pluginsFunctionFunction for registering PhotoSwipe plugins. You should pass photoswipeLightbox to each plugin constructor (example)
uiElementsArrayArray of configuration objects for custom UI elements. Use it for adding custom UI elements (example)
onBeforeOpenFunctionTriggers before PhotoSwipe.init() call. Use it for accessing PhotoSwipe API. It will receive PhotoSwipe instance as the first argument: (photoswipe: PhotoSwipe) => void
onOpenFunctionTriggers after PhotoSwipe.init() call. Use it for accessing PhotoSwipe API. It will receive PhotoSwipe instance as the first argument: (photoswipe: PhotoSwipe) => void
withCaptionBooleanβœ“ (for default captions)Enables built-in caption display. Use the caption prop of the Item component to control caption text (example)
withDownloadButtonBooleanβœ“ (for download button)Adds UI control for downloading the original image of the current slide (example)

Item

Should be children of the Gallery.

PropTypeRequiredDescription
childrenFunctionβœ“Render prop for exposing Gallery API
originalStringUrl of original image
originalSrcsetStringSrcset of original image (example)
thumbnailStringUrl of thumbnail
widthNumber or StringWidth of original image
heightNumber or StringHeight of original image
altStringAlternate text for original image
captionStringText or html for caption (example)
croppedBooleanThumbnail is cropped (example)
contentReactElementCustom slide content (example)
htmlStringCustom slide content (raw html) (example)
idNumber or StringItem ID, for hash navigation (example)

Note about Item's children render prop.

Item accepts only function as children.

type RenderItem = (props: {
  /**
   * Required `ref` object to any html node of item
   *
   * Can be omitted if there is only one item in the gallery
   */
  ref: React.MutableRefObject

  /**
   * Function that opens the gallery at the current item's index
   */
  open: (e: MouseEvent) => void
}) => JSX.Element

<Item>
  {({ ref, open }) => (
    <img ref={ref} onClick={open} />
  ) as RenderItem}
</Item>

<Item>
  {({ ref, open }) => (
    <span ref={ref} onClick={open}>Open gallery</span>
  ) as RenderItem}
</Item>

Hooks

useGallery

The useGallery hook returns an object with some useful methods.

PropertyTypeDescription
open(index: number) => voidThis function allows programmatically open Photoswipe UI at index

useGallery hook gets context provided by Gallery component. So to use useGallery hook you need to store your gallery content as separate component and then wrap it into Gallery component.

const GalleryContent = () => {
  const { open } = useGallery()

  useEffect(() => {
      open(1) // you can open second slide by calling open(1) in useEffect
  }, [open])

  return (
    <div>
      {/* or you can open second slide on button click */}
      <button onClick={() => open(1)}>Open second slide</button>
      <div>
        <Item>...</Item>
        <Item>...</Item>
        <Item>...</Item>
      </div>
    </div>
  )
}

const MyGallery = () => {
  return (
    {/* Gallery component provides context for useGallery hook used in GalleryContent */}
    <Gallery>
      <GalleryContent />
    </Gallery>
  )
}

Example

Requirements

Development

yarn install
yarn sdks vscode

then

yarn storybook

or

yarn start

License

MIT