@molecule/app-gallery-photoswipe
Provider bond · gallery · App (browser) · v1.0.2 · Apache-2.0
Headless gallery state provider for @molecule/app-gallery (PhotoSwipe-compatible interface, no lightbox UI)
npm install @molecule/app-gallery-photoswipenpm · Source on GitHub · Implements @molecule/app-gallery
How it works
@molecule/app-gallery-photoswipe is a provider bond on the app (browser) side: it implements the gallery core interface (@molecule/app-gallery) with a concrete vendor or library behind it.
Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.
// REQUIRED — also `import 'photoswipe/style.css'` in your app entry (see @remarks)
import { provider } from '@molecule/app-gallery-photoswipe'
import { setProvider, requireProvider } from '@molecule/app-gallery'
setProvider(provider) // once, at app startup (bonds.ts)
const gallery = requireProvider().createGallery({
items: [{ src: '/photos/1.jpg', width: 1200, height: 800, alt: 'Sunset' }],
zoomable: true,
})
gallery.open(0) // opens the PhotoSwipe lightbox at item 0Works with: @molecule/app-gallery
Live demos
Running apps built with Molecule that install this package — open the app or study the template.
Reference
PhotoSwipe v5 gallery provider for @molecule/app-gallery.
Drives the real PhotoSwipe lightbox: open() constructs a PhotoSwipe
instance from the core GalleryItem[] (mapped to PhotoSwipe slides) and calls
.init() to actually display it; close() and navigation delegate to the
live instance. This is a real, rendering provider — not headless state.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
// REQUIRED — also `import 'photoswipe/style.css'` in your app entry (see @remarks)
import { provider } from '@molecule/app-gallery-photoswipe'
import { setProvider, requireProvider } from '@molecule/app-gallery'
setProvider(provider) // once, at app startup (bonds.ts)
const gallery = requireProvider().createGallery({
items: [{ src: '/photos/1.jpg', width: 1200, height: 800, alt: 'Sunset' }],
zoomable: true,
})
gallery.open(0) // opens the PhotoSwipe lightbox at item 0
Type
provider
Installation
npm install @molecule/app-gallery-photoswipe @molecule/app-gallery photoswipe
API
Interfaces
PhotoSwipeConfig
Provider-specific configuration options.
interface PhotoSwipeConfig {
/** Whether to enable zoom by default. Defaults to `true`. */
zoomable?: boolean
/** Whether to show counter by default. Defaults to `true`. */
showCounter?: boolean
}
Functions
createProvider(config)
Creates a PhotoSwipe-based gallery provider.
Per-gallery GalleryOptions (zoomable, showCounter) override the
provider-level PhotoSwipeConfig; both default to PhotoSwipe's own defaults.
function createProvider(config?: PhotoSwipeConfig): GalleryProvider
config— Optional provider-level configuration.
Returns: A configured GalleryProvider backed by PhotoSwipe v5.
Constants
provider
Default PhotoSwipe gallery provider instance.
const provider: GalleryProvider
Core Interface
Implements @molecule/app-gallery interface.
Bond Wiring
Setup function to register this provider with the core interface:
import { setProvider } from '@molecule/app-gallery'
import { provider } from '@molecule/app-gallery-photoswipe'
export function setupGalleryPhotoswipe(): void {
setProvider(provider)
}
Injection Notes
Requirements
Peer dependencies:
@molecule/app-gallery^1.0.1
Runtime Dependencies
-
@molecule/app-gallery -
photoswipe -
Import PhotoSwipe's stylesheet yourself — this package does not:
import 'photoswipe/style.css'(akaphotoswipe/dist/photoswipe.css). Without it the lightbox opens unstyled/invisible. -
Browser-only.
open()runsnew PhotoSwipe(...).init(), which needs a live DOM — construct/open galleries in a client-only effect, never during SSR. -
open()renders the real lightbox (unlike a headless provider). EachGalleryItemmaps to a PhotoSwipe slide —src,width,height,alt;thumbnail→msrc(low-res placeholder);captioncarried through — opened atstartIndex/the given index.getCurrentIndex()follows PhotoSwipe's own navigation (arrows/swipe/keyboard) via itschangeevent. -
GalleryOptionsdrive PhotoSwipe:onClosefires on the lightboxcloseevent;zoomable→ PhotoSwipe'szoombutton,showCounter→ itscounter(per-gallery options override the provider-levelPhotoSwipeConfig; both default on).showThumbnailshas no effect — PhotoSwipe core has no thumbnail strip (it needs a separate plugin). -
Wire it with
setProvider()from@molecule/app-galleryorbond('gallery', provider)from@molecule/app-bond— both route through the shared registry;requireProvider()throws until one has run.
E2E Tests
Integration checklist - drive the real UI (live preview, no mocks), adapt each item to this app's actual gallery screen, and check every box off one by one. A box you can't check is an integration bug to fix - not a skip:
- The gallery grid/layout renders every item, and each image actually loads - a real rendered <img> with natural dimensions > 0, not a broken-image icon or empty box. Thumbnails (when an item sets one) load in the grid instead of the full-res src.
- Clicking a grid image opens the lightbox showing THAT image: getCurrentIndex() equals the clicked index and the overlay displays the matching full-res src (the headless instance renders nothing on its own - your overlay must actually appear on open()).
- next()/previous() step through the items in order - getCurrentIndex() moves by one and the displayed image changes to match; at the first/last item they wrap or stop exactly as the UI is designed to, never going blank.
- goTo(i) and the thumbnail strip (when showThumbnails) jump straight to item i; the counter (when showCounter, the default) reads the correct "current / total".
- alt text and captions render when the item provides them; zoom (when zoomable, the default) actually magnifies the open image.
- If the grid lazy-loads, offscreen images are NOT all fetched up front - they load as they scroll into view; each one loads (no broken image).
- Closing the lightbox (close(), the close control, or Escape when supported) fires onClose and returns to the grid with no overlay left covering the page.
- Keyboard navigation works wherever the UI supports it - arrow keys move prev/next and Escape closes, matching the pointer behaviour above.
- Every image loads from the app's own origin (uploaded or bundled assets), not a broken external hotlink - no image request 404s or is blocked by egress.