# VistaView v2 Documentation - Full
> Generated: 2026-08-02T13:28:37.836Z
> This file contains the complete VistaView documentation in a single document.
> Website: https://vistaview.jujiplay.com
> GitHub: https://github.com/juji/vistaview
> npm: https://www.npmjs.com/package/vistaview
## About VistaView
VistaView is a lightweight, modern image lightbox library for the web. Zero dependencies, and highly customizable.
## Table of Contents
1. [Index](#index)
2. [Core](#core)
3. [Framework Integrations](#framework-integrations)
4. [Extensions](#extensions)
5. [Styling & Theming](#styling--theming)
6. [API Reference](#api-reference)
---
## Index
---
# VistaView
A lightweight, modern image lightbox library for the web. Zero dependencies, and highly customizable.
Path: /index
import CreateGallerySection from '../../components/home/CreateGallerySection.astro';
import ThemeSelection from '../../components/home/ThemeSelection.astro';
import ExtensionsSection from '../../components/home/ExtensionsSection.astro';
import FileSizesSection from '../../components/home/FileSizesSection.astro';
---
## Core
---
# Installation
How to install VistaView in your project
Path: /core/installation

VistaView is a lightweight image lightbox library that can be installed via npm or used directly from a CDN.
## Package Manager Installation
import { Tabs, TabItem } from '@astrojs/starlight/components';
```bash
npm install vistaview
```
```bash
yarn add vistaview
```
```bash
pnpm add vistaview
```
```bash
bun add vistaview
```
## CDN Installation
For quick prototyping or non-bundler environments, use the UMD build via CDN. Use these URLs for the latest published version:
### unpkg
```html
```
### jsDelivr
```html
```
## Bundle Sizes
VistaView is lightweight and optimized for production. Bundle sizes are for v2:
- **Core Library (ESM):** 0.71 KB (0.24 KB gzip)
- **Core Library (UMD):** 40.16 KB (10.73 KB gzip)
- **CSS:** 7.71 KB (1.80 KB gzip)
## Browser Support
VistaView works in all modern browsers:
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
## Framework Integrations
VistaView provides official bindings for popular frameworks. Each integration ships a component (recommended) and a hook/composable for more advanced use cases:
- **[React](/integrations/react)** – `VistaView` component + `useVistaView` hook, exports `VistaViewProps` and `VistaComponentRef` types
- **[Vue 3](/integrations/vue)** – `VistaView` component + `useVistaView` composable, exports `VistaViewProps` and `VistaComponentRef` types
- **[Svelte](/integrations/svelte)** – `VistaView` component + `useVistaView` hook, exports `VistaViewProps` and `VistaComponentRef` types
- **[Solid](/integrations/solid)** – `VistaView` component + `useVistaView` hook, exports `VistaViewProps` type
- **[Vanilla JS](/integrations/vanilla)** – Direct `vistaView()` API, no wrapper needed
All framework packages are imported from the same `vistaview` package using subpath exports:
```ts
import { VistaView, useVistaView } from 'vistaview/react';
import { VistaView, useVistaView } from 'vistaview/vue';
import { VistaView, useVistaView } from 'vistaview/svelte';
import { VistaView, useVistaView } from 'vistaview/solid';
```
## Next Steps
- Follow an [Integration guide](/integrations/react) for your framework
- Explore [configuration options](/core/configuration/complete)
- Learn about [extensions](/extensions/overview)
---
# Lifecycle Functions
Override default lifecycle behavior with custom functions
Path: /core/configuration/advanced
You can override default lifecycle functions to customize behavior at different stages:
```typescript
import {
vistaView,
// lifecycle functions
init,
open,
imageSetup,
transition,
close,
} from 'vistaview';
vistaView({
elements: '#gallery a',
// Custom initialization (runs once on instance creation)
initFunction: (vistaView) => {
console.log('Custom init');
init(vistaView); // Call default init
},
// Custom open behavior (runs when lightbox opens)
openFunction: (vistaView) => {
console.log('Custom open');
open(vistaView); // Call default open
},
// Custom setup when navigating between images
imageSetupFunction: (data, vistaView) => {
console.log('Setting up image:', data.index.to);
imageSetup(data, vistaView); // Call default imageSetup
},
// Custom transition animation
transitionFunction: async (data, abortSignal, vistaView) => {
console.log('Custom transition');
// Use default transition
return transition(data, abortSignal, vistaView);
},
// Custom close behavior (runs when lightbox closes)
closeFunction: (vistaView) => {
console.log('Custom close');
close(vistaView); // Call default close
},
});
```
See the [API Reference](/api-reference/main-function) for more details on these functions.
---
# Animation Options
Configure animation timing and behavior in VistaView
Path: /core/configuration/animation
## animationDurationBase
Base multiplier for all animation timings in VistaView. This unitless value is multiplied to create different animation durations throughout the lightbox.
**How it works:**
- The base value is multiplied by `1ms`, `2ms`, etc. to create proportional timings
- Primary animations (open, close, transitions): `333ms` (1× base)
- Delays and sequential animations: `666ms` (2× base)
- Changing this value scales all animations proportionally, maintaining timing relationships
**Default:** `333`
```typescript
vistaView({
elements: '#gallery a',
animationDurationBase: 333, // default
});
```
## rapidLimit
Defines the time threshold (in milliseconds) for detecting rapid navigation. When users navigate faster than this limit, VistaView skips transition animations for better performance.
**How it works:**
- If the time between image swaps is **less than** `rapidLimit`, it's considered a "rapid swap"
- During rapid swaps, transition animations are skipped and images swap instantly
- After rapid navigation stops, there's a 333ms cooldown before normal transitions resume
- This prevents stuttering when users rapidly click next/prev or hold down arrow keys
**Default:** `222` (222ms)
```typescript
vistaView({
elements: '#gallery a',
rapidLimit: 222, // default
});
```
---
# Basic Configuration
Get started with basic VistaView configuration
Path: /core/configuration/basic
Learn the fundamentals of configuring VistaView for your image galleries.
## Minimal Setup
The simplest way to use VistaView requires just two things: importing the library and specifying which elements to use.
### Using Anchor Tags (Recommended)
The recommended approach uses anchor tags wrapping images:
```html
```
```typescript
import { vistaView } from 'vistaview';
import 'vistaview/style.css';
vistaView({
elements: '#gallery a',
});
```
Benefits:
- Progressive loading from thumbnail to full-size
- Works without JavaScript
- SEO-friendly
### Using Images Directly
You can also select images directly:
```html
```
```typescript
vistaView({
elements: '#gallery img',
});
```
### Using Array of Images
You can also pass an array of image configuration objects directly:
```typescript
import type { VistaImgConfig } from 'vistaview';
const images: VistaImgConfig[] = [
{ src: '/images/photo1.jpg', alt: 'Photo 1' },
{ src: '/images/photo2.jpg', alt: 'Photo 2' },
{
src: '/images/photo3.jpg',
alt: 'Photo 3',
srcSet: '/images/photo3-800.jpg 800w, /images/photo3-1200.jpg 1200w',
},
];
vistaView({
elements: images,
});
```
**VistaImgConfig Type:**
```typescript
interface VistaImgConfig {
src: string; // Full-size image URL (required)
alt?: string; // Alt text for the image
srcSet?: string; // Responsive image srcset attribute
}
```
**Note:** Thumbnails are not supported when using an array. This approach is best for programmatically generated galleries.
## Return Value
The `vistaView` function returns an instance with methods to control the lightbox programmatically:
```typescript
const vista = vistaView({
elements: '#gallery a',
});
// Available methods:
vista.open(0); // Open lightbox at index 0
vista.close(); // Close the lightbox
vista.next(); // Navigate to next image
vista.prev(); // Navigate to previous image
vista.view(2); // Jump to image at index 2
vista.zoomIn(); // Zoom in
vista.zoomOut(); // Zoom out
vista.getCurrentIndex(); // Get current image index
vista.reset(); // Recalculate elements; for selectors: re-queries DOM and re-attaches click listeners; for arrays: updates element count only
vista.destroy(); // Clean up and remove lightbox
```
**VistaInterface Type:**
```typescript
interface VistaInterface {
open: (startIndex?: number) => void; // Open at specific index
close: () => Promise; // Close lightbox
reset: () => void; // For selectors: re-queries DOM & re-attaches click listeners; For arrays: updates count only
next: () => void; // Go to next image
prev: () => void; // Go to previous image
zoomIn: () => void; // Zoom in current image
zoomOut: () => void; // Zoom out current image
destroy: () => void; // Remove lightbox completely
getCurrentIndex: () => number; // Get current image index
view: (index: number) => void; // Navigate to specific index
}
```
## Multiple Gallery Configurations
When you need different lightbox configurations across different sections of your application, you have two main approaches:
### Approach 1: Multiple Instances (Recommended)
Create separate VistaView instances for each gallery with different configurations:
```typescript
// Product gallery with zoom enabled
const productGallery = vistaView({
elements: '#product-images a',
maxZoomLevel: 3,
arrowOnSmallScreens: true,
controls: {
topRight: ['zoomIn', 'zoomOut', 'close'],
},
});
// Portfolio gallery with minimal UI
const portfolioGallery = vistaView({
elements: '#portfolio a',
maxZoomLevel: 1, // No zoom
keyboardListeners: false,
controls: {
topRight: ['close'],
},
});
// Blog gallery with downloads
import { download } from 'vistaview/extensions/download';
const blogGallery = vistaView({
elements: '#blog-post img',
extensions: [download()],
});
```
**Advantages:**
- Each gallery is independent with its own configuration
- Different extensions per gallery
- No need to reconfigure or reset
- Straightforward and maintainable
**Memory:**
- Each instance maintains its own state and event listeners
- Automatically cleaned up when you call `destroy()`
### Approach 2: Single Instance with Dynamic Content
Use a single instance and update content dynamically. The approach differs based on whether you use selectors or arrays:
#### With String Selectors (DOM-based)
Update the DOM, then call `reset()` to re-query elements and re-attach listeners:
```typescript
const vista = vistaView({
elements: '#dynamic-gallery a',
maxZoomLevel: 2,
});
// Example Async function to fetch and update gallery
async function updateGallery(category: string) {
const response = await fetch(`/api/images?category=${category}`);
const images = await response.json();
const gallery = document.querySelector('#dynamic-gallery');
// Update DOM
gallery.innerHTML = images
.map(
(img: { src: string; alt: string }) => `
`
)
.join('');
// Re-query DOM and re-attach click listeners
vista.reset();
}
```
**How `reset()` works with selectors:**
- Re-queries the DOM using the original selector
- Updates `state.elmLength`
- Removes and re-attaches click event listeners
- Images become clickable automatically
#### With Arrays (Programmatic)
Mutate the array reference, then call `reset()` to update count:
```typescript
// Create array that will be mutated
const currentImages: VistaImgConfig[] = [];
const vista = vistaView({
elements: currentImages, // Stores the array reference
maxZoomLevel: 2,
});
// Example Async function to fetch and update gallery
async function updateGallery(category: string) {
const response = await fetch(`/api/images?category=${category}`);
const images = await response.json();
// Mutate the original array (don't reassign!)
currentImages.length = 0;
currentImages.push(...images);
// Update element count
vista.reset();
}
```
**How `reset()` works with arrays:**
- Reads `this.elements.length` to update count
- Does NOT attach click listeners (arrays have no DOM elements)
- You must call `open()` programmatically
**Advantages (both):**
- Single instance reduces memory
- Good for SPAs with dynamic content
- All content shares same configuration
**Limitations (both):**
- Cannot change configuration after initialization
- All galleries share same settings (zoom, extensions, controls)
### When to Destroy Instances
Always destroy instances when they're no longer needed:
```typescript
// Before page navigation in SPAs
function cleanup() {
productGallery.destroy();
portfolioGallery.destroy();
blogGallery.destroy();
}
// the following example in react and Vue
// is only needed if you are using
// hooks, composable, or creating and managing you own instance.
// In React - basic cleanup
useEffect(() => {
const vista = vistaView({ elements: '#gallery a' });
return () => vista.destroy();
}, []);
// In React - destroy and recreate when data changes
const [images, setImages] = useState([]);
useEffect(() => {
const vista = vistaView({
elements: images, // Works for both: arrays, or '#gallery a' when DOM re-renders
maxZoomLevel: 2,
});
return () => vista.destroy();
}, [images]);
// In Vue
onUnmounted(() => {
vista.destroy();
});
```
## Next Steps
- Explore [Animation Options](/core/configuration/animation) for timing control
- Discover [Controls](/core/configuration/controls) for UI customization
- See all available options in the [Complete Options](/core/configuration/complete)
---
# Options
Complete reference of all VistaView configuration options
Path: /core/configuration/complete
This page provides a comprehensive reference of all available configuration options for VistaView.
## Default Options
The value you see here are the default values.
```typescript
vistaView({
// Required: specify elements
elements: string | VistaImgConfig[],
// Animation & Timing
animationDurationBase: 333, // Base animation duration in ms
rapidLimit: 222, // Minimum time between rapid actions in ms
// Zoom & Navigation
maxZoomLevel: 2, // Maximum zoom multiplier (1 = 100%, 2 = 200%, etc.)
// Number of adjacent images to preload on each side
preloads: 1,
// UI Controls
keyboardListeners: true, // Enable keyboard navigation
arrowOnSmallScreens: false, // Show prev/next arrows on screens < 768px
initialZIndex: 1, // Starting z-index for the lightbox
// Control Placement
controls: {
topLeft: ['indexDisplay'], // Array of control names
topRight: ['zoomIn', 'zoomOut', 'close'],
topCenter: [],
bottomLeft: ['description'],
bottomRight: [],
bottomCenter: [],
},
// Extensions
extensions: [], // Array of extension objects
// Event Callbacks
onOpen: (vistaView) => {}, // Called when lightbox opens
onClose: (vistaView) => {}, // Called when lightbox closes
onImageView: (data, vistaView) => {}, // Called when viewing an image
onContentChange: (content, vistaView) => {}, // Called when image content changes
// Lifecycle: Custom Behavior Functions (override defaults)
initFunction: undefined, // Custom initialization (default: sets up swipe gestures)
openFunction: undefined, // Custom open behavior (default: positions image container)
imageSetupFunction: undefined, // Custom setup when navigating (default: none)
transitionFunction: undefined, // Custom transition animation (default: slide animation)
closeFunction: undefined, // Custom close behavior (default: none)
});
```
## Detailed Documentation
For detailed explanations and examples of each option, refer to the specific configuration sections:
- **[Basic Configuration](/core/configuration/basic)** - Getting started essentials
- **[Animation Options](/core/configuration/animation)** - Timing and transitions
- **[Zoom Options](/core/configuration/zoom)** - Zoom behavior
- **[Preloading](/core/configuration/preloading)** - Image preloading settings
- **[Control Configuration](/core/configuration/controls)** - UI controls placement
- **[Keyboard & UI Options](/core/configuration/keyboard)** - Keyboard and mobile settings
- **[Z-Index Configuration](/core/configuration/z-index)** - Z-index stacking
- **[Event Callbacks](/core/configuration/events)** - Lifecycle events
- **[Data Attributes](/core/configuration/data-attributes)** - HTML data attributes
- **[Lifecycle Functions](/core/configuration/lifecycle)** - Custom behavior overrides
---
# Control Configuration
Configure UI controls placement and behavior
Path: /core/configuration/controls
## Built-in Controls
VistaView includes these built-in controls:
| Control | Description |
| -------------- | ----------------------------------------- |
| `indexDisplay` | Shows current image index (e.g., "1 / 5") |
| `zoomIn` | Zoom into the image |
| `zoomOut` | Zoom out of the image |
| `close` | Close the lightbox |
| `description` | Shows the image alt text |
## Control Placement
```typescript
vistaView({
elements: '#gallery a',
controls: {
topLeft: ['indexDisplay'],
topRight: ['zoomIn', 'zoomOut', 'close'],
bottomLeft: ['description'],
bottomRight: [],
bottomCenter: [],
},
});
```
## Adding Extension Controls
Extensions can add custom controls. See the [Extensions documentation](/extensions/overview) for available extensions.
```typescript
import { download } from 'vistaview/extensions/download';
vistaView({
elements: '#gallery a',
controls: {
topRight: ['zoomIn', 'zoomOut', 'download', 'close'], // Add 'download'
},
extensions: [download()], // Register extension
});
```
---
# Event Callbacks
Handle VistaView lifecycle events
Path: /core/configuration/events
## onOpen
Called when the lightbox opens:
```typescript
import type { VistaView } from 'vistaview';
vistaView({
elements: '#gallery a',
onOpen: (vistaView: VistaView) => {
console.log('Lightbox opened', vistaView);
},
});
```
## onClose
Called when the lightbox closes:
```typescript
import type { VistaView } from 'vistaview';
vistaView({
elements: '#gallery a',
onClose: (vistaView: VistaView) => {
console.log('Lightbox closed', vistaView);
},
});
```
## onImageView
Called when viewing an image (including on open):
```typescript
import type { VistaView, VistaData, VistaBox } from 'vistaview';
vistaView({
elements: '#gallery a',
onImageView: (data: VistaData, vistaView: VistaView) => {
console.log('Viewing image:', data.index.to);
console.log('Previous image:', data.index.from);
console.log('Navigation direction:', data.via);
// Access the current and previous images
if (data.images.to) {
console.log('Current images:', data.images.to);
}
// Access HTML elements
if (data.htmlElements.to) {
console.log('Current HTML elements:', data.htmlElements.to);
}
},
});
```
**Parameters:**
- `data: VistaData` - Navigation data
- `vistaView: VistaView` - The VistaView instance
**VistaData type:**
```typescript
type VistaData = {
htmlElements: {
from: HTMLElement[] | null; // Previous HTML elements
to: HTMLElement[] | null; // Current HTML elements
};
images: {
from: VistaBox[] | null; // Previous VistaBox instances
to: VistaBox[] | null; // Current VistaBox instances
};
index: {
from: number | null; // Previous image index (null on initial open)
to: number | null; // Current image index
};
via: {
next: boolean; // True if navigated via next
prev: boolean; // True if navigated via prev
};
};
```
## onContentChange
Called when the current image's content state changes (after zoom, pan, or when image finishes loading):
```typescript
import type { VistaView, VistaImageClone } from 'vistaview';
vistaView({
elements: '#gallery a',
onContentChange: (content: VistaImageClone, vistaView: VistaView) => {
console.log('Image state changed');
console.log('Current dimensions:', content.state.width, content.state.height);
console.log('Transform:', content.state.transform);
console.log('Zoom level:', content.state.transform.scale);
},
});
```
**Use cases:**
- Track zoom level changes
- Monitor image dimensions during resize
- Sync image state with external UI
- Analytics for user interactions
**Parameters:**
- `content: VistaImageClone` - Current image state (dimensions, transform, config)
- `vistaView: VistaView` - The VistaView instance
**VistaImageClone type:**
```typescript
type VistaImageClone = {
config: {
src: string; // Image source URL
alt?: string; // Alt text
srcSet?: string; // Responsive image srcset
};
origin: {
src: string; // Original source from HTML
srcSet: string; // Original srcset from HTML
borderRadius: string; // Original border radius
objectFit: string; // Original object-fit value
} | null;
parsedSrcSet?: {
src: string;
width: number;
}[];
element: string; // HTML string of the image element
thumb?: string; // HTML string of thumbnail (if exists)
index: number; // Image index in gallery
pos: number; // Position relative to current (-1, 0, 1)
state: {
width: number; // Current display width (px)
height: number; // Current display height (px)
transform: {
x: number; // Transform X offset (px)
y: number; // Transform Y offset (px)
scale: number; // Scale factor (1 = normal)
};
translate: {
x: number; // CSS translate X (px)
y: number; // CSS translate Y (px)
};
};
};
```
---
# Data Attributes
Use HTML data attributes to customize VistaView behavior
Path: /core/configuration/data-attributes
VistaView uses data attributes to customize how images are displayed in the lightbox. These attributes provide fine-grained control over individual images without requiring JavaScript configuration.
## Available Attributes
| Attribute | Description | Priority |
| ----------------------- | ----------------------- | -------- |
| `data-vistaview-src` | Full-size image URL | Highest |
| `data-vistaview-srcset` | Responsive image srcset | Highest |
| `data-vistaview-alt` | Alt text for lightbox | Highest |
## Attribute Priority
VistaView follows a specific priority order when parsing elements:
### Image Source (`src`)
1. `data-vistaview-src` (highest priority)
2. `href` attribute (for `` tags)
3. `src` attribute (on the element itself)
4. `src` attribute (on child `` tag)
### Responsive Images (`srcset`)
1. `data-vistaview-srcset` (highest priority)
2. `srcset` attribute (on the element itself)
3. `srcset` attribute (on child `` tag)
### Alt Text (`alt`)
1. `data-vistaview-alt` (highest priority)
2. `alt` attribute (on the element itself)
3. `alt` attribute (on child `` tag)
## Examples
### Basic Override
Override the lightbox image URL while keeping the thumbnail:
```html
```
### Responsive Images
Provide different images based on the displayed image size. VistaView dynamically selects the most appropriate image as the image size changes:
```html
```
**How it works:**
- VistaView monitors the **image's display width** (not viewport width) and automatically switches to the optimal image from the srcset
- The image display width depends on the viewport and the image's aspect ratio (portrait images are constrained by height, landscape by width)
- Accounts for device pixel ratio (DPI) for high-resolution displays (e.g., Retina screens)
- Selects the smallest image that meets or exceeds the required display width
- Dynamically swaps images during opening animation and zoom gestures
**Format:** `"url {width}w, url {width}w, ..."` where width descriptors specify the image's actual pixel width.
:::note[Width descriptors only]
VistaView only supports the `w` (width) descriptor. Density descriptors like `1x` or `2x` are **not supported**. Use width descriptors with pixel values (e.g., `800w`, `1200w`) to enable responsive image selection.
:::
**Example with pixel calculations:**
```html
```
### Custom Alt Text
Display different text in the thumbnail vs lightbox:
```html
```
### Combining Attributes
Use multiple attributes together. When both `src` and `srcset` are provided, `srcset` takes precedence and `src` serves as fallback:
```html
```
**Priority order:** If `srcset` is available, VistaView uses responsive selection. The `src` attribute (or `data-vistaview-src`) is used only when `srcset` is not provided.
---
# Configuration
Complete configuration reference for VistaView
Path: /core/configuration
---
# Keyboard & Touch Navigation
Configure keyboard shortcuts and touch gestures for desktop and mobile users
Path: /core/configuration/keyboard
## Keyboard Navigation
VistaView includes **built-in keyboard navigation** that's enabled by default.
### Keyboard Shortcuts
When the lightbox is open, the following keyboard shortcuts are available:
- **Arrow Left** (←) - Navigate to previous image
- **Arrow Right** (→) - Navigate to next image
- **Arrow Up** (↑) - Zoom in
- **Arrow Down** (↓) - Zoom out
- **Escape** (Esc) - Close lightbox
### Configuration
Control keyboard navigation via the `keyboardListeners` option:
```typescript
vistaView({
elements: '#gallery a',
keyboardListeners: true, // Default: enabled
});
```
To disable keyboard navigation:
```typescript
vistaView({
elements: '#gallery a',
keyboardListeners: false,
});
```
## Touch Gestures
VistaView automatically handles touch gestures with **no configuration needed**. All gestures work out-of-the-box on mobile devices.
### Pinch-to-Zoom
Use two fingers to zoom in and out:
- **Two-finger pinch out** - Zoom in
- **Two-finger pinch in** - Zoom out
The zoom is centered around the touch point (centroid of your fingers) for intuitive interaction. VistaView includes a cooldown period (111ms) after pinch gestures to prevent conflicts with other touch interactions.
### Swipe Navigation
Single-finger swipe gestures for navigation:
- **Horizontal swipe right** (>64px) - Navigate to previous image
- **Horizontal swipe left** (>64px) - Navigate to next image
- **Vertical swipe down** (>144px) - Close lightbox
**Note:** Swipe gestures only work when the image is not zoomed in. When zoomed, single-finger drag is used for panning.
### Pan/Drag
When an image is zoomed in:
- **Single finger drag** - Pan around the zoomed image
Pan is disabled at normal zoom level to allow swipe gestures for navigation and closing.
### Scroll-to-Zoom
On devices with a mouse or trackpad:
- **Scroll wheel** - Zoom in/out around cursor position
## Mobile-Specific Options
### arrowOnSmallScreens
Control whether navigation arrows are shown on mobile devices:
```typescript
vistaView({
elements: '#gallery a',
arrowOnSmallScreens: true, // Show arrows on screens < 768px (default: false)
});
```
By default, navigation arrows are hidden on screens smaller than 768px to provide a cleaner interface where users can swipe. Enable this option if you want to show arrow buttons on mobile devices.
## Advanced: Custom Touch Handling
For custom touch behaviors and gesture tracking, use the `registerPointerListener()` method:
```typescript
const vista = vistaView({ elements: '#gallery a' });
vista.registerPointerListener((e) => {
// Track pointer events
console.log('Event type:', e.event); // 'down' | 'move' | 'up' | 'cancel'
console.log('Active pointers:', e.pointers.length);
console.log('Pointer position:', e.pointer.x, e.pointer.y);
console.log('Zoom/pinch active:', e.hasInternalExecution);
// Access current state
console.log('Is zoomed:', e.state.zoomedIn);
console.log('Current index:', e.state.currentIndex);
});
```
### VistaExternalPointerListenerArgs Properties
- `event` - Event type: `'down'`, `'move'`, `'up'`, or `'cancel'`
- `pointer` - Current pointer data (x, y, movementX, movementY, id)
- `pointers` - Array of all active touch points/pointers
- `lastPointerLen` - Previous number of active pointers
- `state` - Current [VistaState](/api-reference/classes/vistastate) instance
- `hasInternalExecution` - `true` when VistaView is handling the gesture (zoom/pinch)
- `abortController` - Controller to abort ongoing animations
### Example: Custom Gesture Detection
```typescript
vista.registerPointerListener((e) => {
// Skip if VistaView is handling the event (zooming/pinching)
if (e.hasInternalExecution) return;
// Detect three-finger tap
if (e.event === 'down' && e.pointers.length === 3) {
console.log('Three-finger tap detected!');
// Custom action here
}
// Track swipe velocity
if (e.event === 'move' && e.pointers.length === 1) {
const velocity = Math.sqrt(e.pointer.movementX ** 2 + e.pointer.movementY ** 2);
console.log('Swipe velocity:', velocity);
}
});
```
## Customizing Swipe Behavior
The default swipe gesture behavior is implemented in VistaView's `initFunction` lifecycle hook. You can extend or replace this behavior:
```typescript
import { init as defaultInit } from 'vistaview/defaults/init';
vistaView({
elements: '#gallery a',
initFunction: (vistaView) => {
// Call default behavior (sets up swipe gestures)
defaultInit(vistaView);
// Add your custom initialization
vistaView.registerPointerListener((e) => {
// Your custom gesture handling
if (e.event === 'down' && e.pointers.length === 3) {
console.log('Three-finger tap!');
}
});
},
});
```
**Default initFunction behavior:**
- Registers a pointer listener for single-touch swipe gestures
- Vertical swipe down (>144px) closes the lightbox
- Horizontal swipe left/right (>64px) navigates between images
- Provides visual feedback during swipe (translates the image container)
To completely replace the default swipe behavior, provide your own `initFunction` without calling `defaultInit()`.
See [Lifecycle Functions](/core/configuration/lifecycle) for more details on customizing behavior.
## Related
- [VistaPointers API](/api-reference/classes/vistapointers) - Low-level pointer tracking
- [registerPointerListener()](/api-reference/classes/vistaview#registerpointerlistener) - Method documentation
- [VistaState](/api-reference/classes/vistastate) - State management
- [Lifecycle Functions](/core/configuration/lifecycle) - Custom behavior overrides
---
# Extensions
Add extended functionality to VistaView
Path: /core/configuration/extensions
## extensions
Array of extension functions that add functionality to VistaView. Extensions can add UI controls, handle different content types (videos, maps), or modify lightbox behavior.
See the [Extensions Overview](/extensions/overview) for complete documentation on all available extensions and their usage.
**Type:** `VistaExtension[]`
**Default:** `[]` (no extensions)
```typescript
import { vistaView } from 'vistaview';
import { download } from 'vistaview/extensions/download';
import { youtubeVideo } from 'vistaview/extensions/youtube-video';
vistaView({
elements: '#gallery a',
controls: {
// Add 'download' to controls for download extension
topRight: ['zoomIn', 'zoomOut', 'download', 'close'],
},
extensions: [download(), youtubeVideo()],
});
```
**Note:** Some extensions like `download` require adding their control name to the `controls` configuration.
## Available Extensions
VistaView provides optional extensions for:
- **UI Controls** - Download buttons, image story overlays
- **Video Platforms** - YouTube, Vimeo, Dailymotion, Wistia, Vidyard, Streamable
- **Maps** - Google Maps, Mapbox, OpenStreetMap
- **Development** - Logger for debugging
See the [Extensions Overview](/extensions/overview) for complete documentation on all available extensions and their usage.
---
# Lifecycle Functions
Override default lifecycle behavior with custom functions
Path: /core/configuration/lifecycle
You can override default lifecycle functions to customize behavior at different stages:
```typescript
import {
vistaView,
// lifecycle functions
init,
open,
imageSetup,
transition,
close,
} from 'vistaview';
import type { VistaView, VistaData } from 'vistaview';
vistaView({
elements: '#gallery a',
// Custom initialization (runs once on instance creation)
initFunction: (vistaView: VistaView) => {
console.log('Custom init');
// default init, just here to show the actual init
init(vistaView);
},
// Custom open behavior (runs when lightbox opens)
openFunction: (vistaView: VistaView) => {
console.log('Custom open');
// default open, just here to show the actual open
open(vistaView);
},
// Custom setup when navigating between images
imageSetupFunction: (data: VistaData, vistaView: VistaView) => {
console.log('Setting up image:', data.index.to);
// default imageSetup, just here to show the actual imageSetup
imageSetup(data, vistaView);
},
// Custom transition animation
transitionFunction: async (
data: VistaData,
abortSignal: AbortSignal,
vistaView: VistaView
): Promise<{ cleanup: () => void; transitionEnded: Promise } | undefined> => {
console.log('Custom transition');
// default transition, just here to show the actual transition
return transition(data, abortSignal, vistaView);
},
// Custom close behavior (runs when lightbox closes)
closeFunction: (vistaView: VistaView) => {
console.log('Custom close');
// default close, just here to show the actual close
close(vistaView);
},
});
```
## VistaData Type
The `data` parameter passed to lifecycle functions contains information about the current and previous images:
```typescript
interface VistaData {
htmlElements: {
from: HTMLElement[] | null;
to: HTMLElement[] | null;
};
images: {
from: VistaBox[] | null;
to: VistaBox[] | null;
};
index: {
from: number | null;
to: number | null;
};
via: {
next: boolean;
prev: boolean;
};
}
```
See the [API Reference](/api-reference/main-function) for more details on these functions.
---
# Preloading
Configure image preloading for better navigation performance
Path: /core/configuration/preloading
## preloads
Number of adjacent images to preload:
```typescript
vistaView({
elements: '#gallery a',
preloads: 1, // default
});
```
**How it works:**
- Preloads adjacent images on both sides (previous and next)
- `preloads: 1` → loads 3 images total (current + 1 before + 1 after)
- `preloads: 2` → loads 5 images total (current + 2 before + 2 after)
- `preloads: 0` → only loads current image (saves bandwidth but causes loading delays)
**Trade-offs:**
- Higher values: Faster navigation, smoother experience, more bandwidth usage
- Lower values: Less bandwidth, but visible loading delays when navigating
---
# Z-Index Configuration
Configure z-index stacking for the lightbox
Path: /core/configuration/z-index
## initialZIndex
Set the z-index for the lightbox when opening or closing. When active, the lightbox automatically uses the maximum z-index (`2147483647`) to appear above all content.
**Default:** `1`
**Most users should leave this at the default value.**
```typescript
vistaView({
elements: '#gallery a',
initialZIndex: 1, // default
});
```
## Why leave it at 1?
VistaView renders its container at the bottom of the page (end of DOM). With the default `initialZIndex: 1`, it then brings the image to the center and raises the z-index to the maximum z-index. In effect, this requires z-index ordering:
- Your **sticky header** should use `z-index: 2` or higher to appear above the opening/closing lightbox
## Example with sticky header
```css
/* Your sticky header */
.site-header {
position: sticky;
z-index: 2; /* Appears above closed lightbox (z-index: 1) */
}
```
## How it works
- **Closed state:** Uses `initialZIndex` value (default: 1)
- **Active state:** Switches to `2147483647` (max z-index) in the middle of animation - always above everything
- **Closing state:** Transitions back to `initialZIndex` during animation
:::tip
Only change `initialZIndex` if you have z-index stacking context conflicts. For typical sticky headers, just set your header to `z-index: 2` or higher.
:::
---
# Zoom Options
Configure zoom behavior in VistaView
Path: /core/configuration/zoom
## maxZoomLevel
Defines the maximum zoom level as a multiplier of the image's natural dimensions.
**How it works:**
- VistaView maintains three zoom levels:
- **Minimum (0.5×)**: 50% of fitted size - zooming below this triggers close
- **Fitted**: Image fitted to viewport while maintaining aspect ratio
- **Maximum**: Natural image dimensions × `maxZoomLevel`
- Zoom automatically corrects if exceeded:
- Over maximum → animates back to max
- Under normal (but not closing) → animates back to fitted size
**Default:** `2` (200% of natural size)
```typescript
vistaView({
elements: '#gallery a',
maxZoomLevel: 2, // default - allows zoom to 200% of natural size
});
```
**Example:**
If an image is 1600×1200px and displays at 800×600px to fit the viewport:
- Minimum zoom: 400×300px (50% of fitted)
- Normal zoom: 800×600px (fitted to viewport)
- Maximum zoom: 3200×2400px (200% of natural 1600×1200px)
---
## Framework Integrations
---
# Getting Started with React
Learn how to integrate VistaView with React applications
Path: /integrations/react
VistaView provides official React bindings that offer both declarative components and hooks for React applications.
## Installation
import { Tabs, TabItem } from '@astrojs/starlight/components';
```bash
npm install vistaview
```
```bash
yarn add vistaview
```
```bash
pnpm add vistaview
```
```bash
bun add vistaview
```
## Component Approach (Recommended)
The `VistaView` component provides a declarative way to create image galleries:
```tsx
'use client'; // Required for Next.js and other React Server Components frameworks
import { VistaView } from 'vistaview/react';
import 'vistaview/style.css';
function Gallery() {
return (
);
}
```
### With Ref for Imperative Control
We expose the API and root container on the component ref as `{ vistaView, container }`.
💡 **Types:** You can import `VistaComponentRef` from `vistaview/react` (see the [Type Reference](#type-reference)):
```tsx
'use client'; // Required for Next.js and other React Server Components frameworks
import { useRef } from 'react';
import { VistaView } from 'vistaview/react';
import type { VistaComponentRef } from 'vistaview/react';
import 'vistaview/style.css';
function Gallery() {
const compRef = useRef(null);
return (
<>
>
);
}
```
### With Options
```tsx
'use client'; // Required for Next.js and other React Server Components frameworks
import { VistaView } from 'vistaview/react';
import type { VistaOpt, VistaView } from 'vistaview';
import 'vistaview/style.css';
// Define options outside component to prevent recreation on every render
const options: VistaOpt = {
maxZoomLevel: 3,
preloads: 2,
animationDurationBase: 400,
onOpen: (vistaView: VistaView): void => {
console.log('Gallery opened');
},
onClose: (vistaView: VistaView): void => {
console.log('Gallery closed');
},
};
function Gallery() {
return (
// selector defaults to '> a'
);
}
```
## With Extensions
```tsx
'use client'; // Required for Next.js and other React Server Components frameworks
import { VistaView } from 'vistaview/react';
import { download } from 'vistaview/extensions/download';
import 'vistaview/style.css';
// Define options outside component to prevent recreation on every render
const extensionOptions = {
controls: {
topRight: ['zoomIn', 'zoomOut', 'download', 'close'],
},
extensions: [download()],
};
function Gallery() {
return (
);
}
```
## Hook Approach
Use the `useVistaView` hook for more control over the gallery instance:
```tsx
'use client'; // Required for Next.js and other React Server Components frameworks
import { useVistaView } from 'vistaview/react';
import { download } from 'vistaview/extensions/download';
import 'vistaview/style.css';
function Gallery() {
const vista = useVistaView({
elements: '#gallery > a',
controls: {
topRight: ['zoomIn', 'zoomOut', 'download', 'close'],
},
extensions: [download()],
});
return (
);
}
```
### Type Reference
**`VistaViewProps`**
```ts
interface VistaViewProps {
children: ReactNode;
selector?: string; // defaults to "> a"
options?: VistaOpt; // passes through to core options
ref?: React.Ref;
}
```
- **children**: The gallery markup (usually `` items).
- **selector**: CSS selector used to locate items inside the container.
- **options**: Configuration passed to the core `VistaView` instance (`VistaOpt`).
- **ref**: React ref that receives a `VistaComponentRef` for imperative control.
**`VistaComponentRef`**
```ts
type VistaComponentRef = {
vistaView: VistaInterface | null;
container: HTMLDivElement | null
} | null;
```
- **vistaView**: The runtime API instance (`VistaInterface`) — use it to call `.open()`, `.next()`, `.prev()`, `.zoomIn()`, `.zoomOut()`, `.close()`, `.destroy()`, etc.
- **container**: The root DOM element that wraps the gallery — useful for queries or DOM measurements.
**Related types**
- `VistaOpt` — core configuration object (see `/core/configuration/complete` or `main/src/lib/types.ts` for full shape).
- `VistaInterface` — runtime API methods available on `vistaView`.
**Import example**
```ts
import type { VistaComponentRef, VistaViewProps } from 'vistaview/react';
```
## Next Steps
- Explore [configuration options](/core/configuration/complete)
- Learn about [extensions](/extensions/overview)
- Customize the [styling](/styling/themes)
---
# Getting Started with Solid
Learn how to integrate VistaView with Solid applications
Path: /integrations/solid
VistaView provides a `useVistaView` hook for SolidJS applications.
## Installation
import { Tabs, TabItem } from '@astrojs/starlight/components';
```bash
npm install vistaview
```
```bash
yarn add vistaview
```
```bash
pnpm add vistaview
```
```bash
bun add vistaview
```
## Component Approach (Recommended)
The `VistaView` component is the recommended way to use VistaView in Solid applications:
```tsx
import { VistaView } from 'vistaview/solid';
import 'vistaview/style.css';
function Gallery() {
return (
);
}
```
## Hook Approach
Use the `useVistaView` hook when you need more control:
```tsx
import { useVistaView } from 'vistaview/solid';
import 'vistaview/style.css';
function Gallery() {
const galleryId = 'vistaview-demo';
const vista = useVistaView({
elements: `#${galleryId} > a`,
});
return (
<>
>
);
}
```
## Imperative Control with Component
Access the API through the `componentRef` callback prop:
```tsx
import { VistaView } from 'vistaview/solid';
import type { VistaInterface } from 'vistaview';
import 'vistaview/style.css';
function Gallery() {
let vista: VistaInterface | null = null;
let container: HTMLDivElement | undefined;
return (
<>
{
vista = api?.vistaView ?? null;
container = api?.container;
}}
>
>
);
}
```
## With Options
```tsx
import { useVistaView } from 'vistaview/solid';
import type { VistaOpt } from 'vistaview';
import 'vistaview/style.css';
// Define options outside component to prevent recreation on every render
const options: VistaOpt = {
maxZoomLevel: 3,
preloads: 2,
animationDurationBase: 400,
onOpen: (vistaView) => console.log('Gallery opened'),
onClose: (vistaView) => console.log('Gallery closed'),
};
function Gallery() {
const id = 'gallery-' + Math.random().toString(36).slice(2);
const vista = useVistaView({
elements: `#${id} > a`,
...options,
});
return (
);
}
```
## With Extensions
```tsx
import { useVistaView } from 'vistaview/solid';
import { download } from 'vistaview/extensions/download';
import 'vistaview/style.css';
function Gallery() {
const id = 'gallery-' + Math.random().toString(36).slice(2);
const vista = useVistaView({
elements: `#${id} > a`,
controls: {
topRight: ['zoomIn', 'zoomOut', 'download', 'close'],
},
extensions: [download()],
});
return (
);
}
```
## Reactive Updates
VistaView works with Solid's reactive system:
```tsx
import { createSignal } from 'solid-js';
import { useVistaView } from 'vistaview/solid';
import 'vistaview/style.css';
function Gallery() {
const [images, setImages] = createSignal([
{ src: '/images/photo1.jpg', alt: 'Photo 1' },
{ src: '/images/photo2.jpg', alt: 'Photo 2' },
]);
const id = 'gallery-' + Math.random().toString(36).slice(2);
const vista = useVistaView({
elements: `#${id} > a`,
});
return (
{images().map((img) => (
))}
);
}
```
## SolidStart
VistaView works with SolidStart. Make sure to use client-side rendering:
```tsx
import { lazy } from 'solid-js';
const Gallery = lazy(() => import('./Gallery'));
function Page() {
return (
);
}
```
## Next Steps
- Explore [configuration options](/core/configuration/complete)
- Learn about [extensions](/extensions/overview)
- Customize the [styling](/styling/themes)
---
# Getting Started with Svelte
Learn how to integrate VistaView with Svelte applications
Path: /integrations/svelte
VistaView provides a `VistaView` Svelte component (recommended) and a lower-level `useVistaView` hook for advanced use cases.
## Installation
import { Tabs, TabItem } from '@astrojs/starlight/components';
```bash
npm install vistaview
```
```bash
yarn add vistaview
```
```bash
pnpm add vistaview
```
```bash
bun add vistaview
```
## Component-first usage (recommended)
The recommended, primary way to use VistaView in Svelte is the `VistaView` component. It handles lifecycle, DOM changes, and provides a simple imperative API via `bind:this` and `getApi()`.
### Basic example
```svelte
```
### Imperative Control
If you need programmatic access to the gallery API, use the `vistaRef` callback prop:
```svelte
{
vista = api?.vistaView ?? null;
container = api?.container ?? null;
}}>
```
### Options
```svelte
```
### Extensions
```svelte
```
> **Tip:** prefer the component when your gallery content is dynamic, as it observes DOM changes and re-initializes automatically.
## Hook approach (advanced)
The `useVistaView` hook is a lower-level API. Use it for non-component contexts or when you need manual control. The hook handles lifecycle internally (`onMount`/`onDestroy`), so you can call it at the top level.
```svelte
```
## Low-level usage
You can call the core `vistaView` function directly when embedding in non-component contexts:
```svelte
```
## SvelteKit
Use the `VistaView` component in SvelteKit apps; it handles lifecycle and DOM updates automatically. If you need the hook, initialize it inside `onMount` to avoid SSR issues.
## Types
```ts
import type { VistaViewProps, VistaComponentRef } from 'vistaview/svelte';
```
## Best practices & troubleshooting
- Prefer the component for most cases (dynamic content, SvelteKit, simpler lifecycle).
- Keep `options` objects stable (define outside render scope) to avoid unnecessary re-initializations.
- Use optional chaining (e.g., `comp?.getApi()?.vistaView?.open(0)`) when calling methods that may not be ready yet.
- If using the hook and the DOM changes dynamically, re-initialize or prefer the component.
## Next Steps
- Explore [configuration options](/core/configuration/complete)
- Learn about [extensions](/extensions/overview)
- Customize the [styling](/styling/themes)
---
# Getting Started with Vanilla JavaScript
Learn how to use VistaView with vanilla JavaScript
Path: /integrations/vanilla
VistaView works perfectly with vanilla JavaScript - no framework needed!
## Installation
import { Tabs, TabItem } from '@astrojs/starlight/components';
```bash
npm install vistaview
```
```bash
yarn add vistaview
```
```bash
pnpm add vistaview
```
```bash
bun add vistaview
```
```javascript
import { vistaView } from 'vistaview';
import 'vistaview/style.css';
const gallery = vistaView({
elements: '#gallery a',
});
```
### Using CDN (UMD)
For quick prototyping or non-bundler environments:
```html
```
## Using Data Attributes
You can use `data-vistaview-src` to specify high-resolution images:
```html
```
## With Extensions (ESM)
```html
```
## With Extensions (UMD)
```html
```
## Using with Images Array
Instead of DOM elements, you can pass an array of image objects:
```javascript
vistaView({
elements: [
{ src: '/images/photo1.jpg', alt: 'Photo 1' },
{
src: '/images/photo2-800.jpg',
alt: 'Photo 2',
srcSet: '/images/photo2-800.jpg 800w, /images/photo2-1200.jpg 1200w',
},
],
});
```
**Note:** When using an array, thumbnails are not supported. Use DOM elements if you need progressive loading.
## Available Methods
```javascript
const gallery = vistaView({ elements: '#gallery a' });
// Open lightbox at specific index (0-based)
gallery.open(0);
// Close lightbox
gallery.close();
// Navigate to next image
gallery.next();
// Navigate to previous image
gallery.prev();
// Go to specific image
gallery.view(2);
// Get current image index
const currentIndex = gallery.getCurrentIndex();
// Destroy instance and cleanup
gallery.destroy();
```
## Event Callbacks
```javascript
vistaView({
elements: '#gallery a',
onOpen: (vistaView) => {
console.log('Gallery opened');
},
onClose: (vistaView) => {
console.log('Gallery closed');
},
onImageView: (data) => {
console.log('Viewing image:', data.index.to);
},
});
```
## Next Steps
- Explore [configuration options](/core/configuration/complete)
- Learn about [extensions](/extensions/overview)
- Customize the [styling](/styling/themes)
---
# Getting Started with Vue
Learn how to integrate VistaView with Vue 3 applications
Path: /integrations/vue
VistaView provides official Vue 3 bindings with both a declarative component and a composable.
## Installation
import { Tabs, TabItem } from '@astrojs/starlight/components';
```bash
npm install vistaview
```
```bash
yarn add vistaview
```
```bash
pnpm add vistaview
```
```bash
bun add vistaview
```
## Component Approach (Recommended)
The `VistaView` component provides a declarative way to create image galleries. Any additional HTML attributes (e.g., `class`, `style`, `data-*`, `aria-*`) passed to the component are forwarded to the root `
```
## With Extensions
Extensions can be used with both the component and composable approaches.
### Component with Extensions
```vue
```
### Composable with Extensions
```vue
```
## Options API
If you prefer the Options API:
```vue
```
## Next Steps
- Explore [configuration options](/core/configuration/complete)
- Learn about [extensions](/extensions/overview)
- Customize the [styling](/styling/themes)
---
## Extensions
---
# Extensions Overview
Extend VistaView with powerful extensions
Path: /extensions/overview
VistaView provides optional extensions for additional functionality. Extensions are available in both ESM and UMD formats and can add UI controls, handle different content types, or modify behavior.
## Extension Types
### UI Extensions
Add interactive controls to the lightbox:
- **[Download](/extensions/download)** - Download button for saving high-resolution images
- **[Image Story](/extensions/image-story)** - Display rich HTML content alongside images
### Video Platform Extensions
Embed videos from popular platforms:
- **[YouTube](/extensions/youtube-video)** - Embed YouTube videos
- **[Vimeo](/extensions/vimeo-video)** - Embed Vimeo videos
- **[Dailymotion](/extensions/dailymotion-video)** - Embed Dailymotion videos
- **[Wistia](/extensions/wistia-video)** - Embed Wistia videos
- **[Vidyard](/extensions/vidyard-video)** - Embed Vidyard videos
- **[Streamable](/extensions/streamable-video)** - Embed Streamable videos
- **[Native Video](/extensions/native-video)** - Play direct video file URLs (mp4, webm, blob, etc.)
### Map Extensions
Embed interactive maps:
- **[Google Maps](/extensions/google-maps)** - Embed Google Maps (requires API key)
- **[Mapbox](/extensions/mapbox)** - Embed Mapbox GL JS maps (requires access token)
- **[OpenStreetMap](/extensions/openstreetmap)** - Embed OpenStreetMap with Leaflet.js (free)
### Development Extensions
- **[Logger](/extensions/logger)** - Debug extension that logs all lifecycle events
## Using Extensions
### ESM (Module Bundlers)
```javascript
import { vistaView } from 'vistaview';
import { download } from 'vistaview/extensions/download';
import { youtubeVideo } from 'vistaview/extensions/youtube-video';
vistaView({
elements: '#gallery > a',
controls: {
topRight: ['zoomIn', 'zoomOut', 'download', 'close'],
},
extensions: [download(), youtubeVideo()],
});
```
### UMD (CDN)
```html
```
## Extension Sizes
All extensions are optimized for minimal bundle size:
| Extension | ESM Size | UMD Size |
| ----------------- | ------------------------ | ----------------------- |
| logger | 0.60 KB (0.26 KB gzip) | 0.72 KB (0.36 KB gzip) |
| download | 1.58 KB (0.78 KB gzip) | 1.50 KB (0.81 KB gzip) |
| streamable-video | 2.53 KB (1.13 KB gzip) | 2.22 KB (1.12 KB gzip) |
| vimeo-video | 2.44 KB (1.12 KB gzip) | 2.18 KB (1.11 KB gzip) |
| vidyard-video | 2.53 KB (1.13 KB gzip) | 2.24 KB (1.11 KB gzip) |
| dailymotion-video | 2.63 KB (1.15 KB gzip) | 2.30 KB (1.14 KB gzip) |
| wistia-video | 2.73 KB (1.24 KB gzip) | 2.45 KB (1.24 KB gzip) |
| youtube-video | 2.89 KB (1.30 KB gzip) | 2.56 KB (1.28 KB gzip) |
| native-video | 2.73 KB (1.27 KB gzip) | 2.46 KB (1.23 KB gzip) |
| google-maps | 3.53 KB (1.54 KB gzip) | 3.07 KB (1.49 KB gzip) |
| openstreetmap | 4.75 KB (1.88 KB gzip) | 4.10 KB (1.77 KB gzip) |
| mapbox | 4.91 KB (1.90 KB gzip) | 4.32 KB (1.80 KB gzip) |
| image-story | 29.56 KB (10.06 KB gzip) | 23.36 KB (9.27 KB gzip) |
## Creating Custom Extensions
Want to create your own extension? Check out the [Extensions Authoring Guide](/extensions/authoring).
## Extension Capabilities
Extensions can:
- **Add UI controls** - Buttons, panels, overlays
- **Handle custom content** - Videos, maps, 3D models, etc.
- **Modify behavior** - Custom transitions, interactions
- **Track events** - Analytics, logging, debugging
- **Enhance functionality** - Download, share, annotations
## Next Steps
- Browse individual [extension documentation](/extensions/download)
- Learn to [create your own extensions](/extensions/authoring)
- See the [API Reference](/api-reference/main-function)
---
# Native Video Extension
Play direct video file URLs in the lightbox
Path: /extensions/native-video
The Native Video extension plays direct video file URLs (blob URLs, same-origin files, signed S3/CDN URLs, or any remote `.mp4`/`.webm`/`.mov` URL) using the browser's native `