Imported from bearholmes/iv-viewer-ts (
AGENTS.md). Install upstream withnpx skills add bearholmes/iv-viewer-ts. Copyright stays with the author.
AGENTS.md - iv-viewer-ts Project Guide
Project Overview
iv-viewer-ts is a TypeScript-based image viewer library that provides Google Photos-like zooming and panning functionality for web images. It's a fork of the original s-yadav/iv-viewer project, enhanced with TypeScript for better type safety and developer experience.
Key Capabilities
- Smooth image dragging and panning with momentum physics
- Multi-touch gesture support (pinch zoom, double-tap)
- Mouse wheel zoom with smooth animations
- Progressive image loading (low-res preview, then high-res)
- Snap view minimap for navigating zoomed images
- Three usage modes: Full-Screen, Container, and Image Mode
- Zero external dependencies
Package Information
- Version: 2.2.0
- License: MIT
- Main Entry:
dist/iv-viewer-ts.js(CommonJS) - Module Entry:
dist/iv-viewer-ts.mjs(ES Module) - Types:
dist/types/index.d.ts
Technology Stack
Core Technologies
- TypeScript 5.7 - Type-safe JavaScript with an ES2015 target
- Vite 6 - Library bundler (ES/CJS/UMD) and dev server
- SASS 1.83 - SCSS preprocessing for styles
Build Tools
- vite-plugin-dts - TypeScript declaration file generation
- PostCSS 8.4.49 with Autoprefixer and cssnano (minifies
dist/iv-viewer-ts.min.css) - ESLint 9 with TypeScript support
Distribution Formats
- CommonJS (
.js) - Node.js compatibility - ES Module (
.mjs) - Modern bundlers - UMD (
.umd.js) - Browser globals - TypeScript Declarations (
.d.ts) - IDE support
Project Structure
iv-viewer-ts/
├── src/ # TypeScript source files
│ ├── ImageViewer.ts # Core viewer class (~1200 lines)
│ ├── FullScreen.ts # Full-screen viewer extension (71 lines)
│ ├── Slider.ts # Touch/mouse drag handler (131 lines)
│ ├── util.ts # Utility functions
│ ├── dist.ts # Distribution entry point
│ ├── index.ts # Main export file
│ └── scss/ # Styles
│ ├── _variables.scss # SCSS variables
│ ├── _iv-viewer.scss # Main styles
│ └── build.scss # Build entry point
├── example/ # Working examples
│ ├── container-mode/ # Gallery with navigation
│ ├── fullscreen-mode/ # Click-to-open viewer
│ ├── image-mode/ # Direct image zoom
│ └── index.html # Demo landing page
├── dist/ # Built output
│ ├── types/ # TypeScript declarations
│ ├── iv-viewer-ts.js # CommonJS bundle
│ ├── iv-viewer-ts.mjs # ES Module bundle
│ ├── iv-viewer-ts.umd.js # UMD bundle
│ └── iv-viewer-ts.css # Compiled styles
├── package.json # Project metadata
├── tsconfig.json # TypeScript config
└── vite.config.ts # Vite build config and CSS pipeline
Key Components
1. ImageViewer (src/ImageViewer.ts)
Responsibility: Core image viewer engine handling all viewing modes and interactions.
Key Methods:
constructor(element, options)- Initialize viewer with element or selectorload(imageSrc, hiResImageSrc?)- Load images with optional high-res version (reuseimageSrcif only one asset)zoom(percentage, point?)- Programmatic zoom controlresetZoom()- Return to default zoom levelrefresh()- Recalculate dimensions after resizedestroy()- Clean up and remove all references
State Management:
_state: {
zoomValue: number,
loaded: boolean,
imageDim: {w, h},
containerDim: {w, h},
snapImageDim: {w, h},
zooming: boolean,
snapViewVisible: boolean,
zoomSliderLength: number,
snapHandleDim: {w, h}
}
Options:
{
zoomValue: number, // Initial zoom (100-maxZoom)
maxZoom: number, // Maximum zoom level (default: 500)
snapView: boolean, // Enable snap view minimap
refreshOnResize: boolean, // Auto-refresh on window resize
zoomOnMouseWheel: boolean,// Enable mouse wheel zoom
hasZoomButtons: boolean, // Render zoom in/out buttons (default false)
zoomStep: number, // Increment for zoom buttons
listeners: { // Event callbacks
onInit, onDestroy, onImageLoaded,
onImageError, onZoomChange
}
}
2. FullScreenViewer (src/FullScreen.ts)
Responsibility: Extends ImageViewer for full-screen display mode.
Key Methods:
show(imageSrc, hiResImageSrc?)- Display image in fullscreen overlayhide()- Close fullscreen viewerdestroy()- Cleanup fullscreen elements
Features:
- Creates fullscreen DOM overlay
- Disables body scroll when active
- Provides close button
- Inherits all ImageViewer functionality
3. Slider (src/Slider.ts)
Responsibility: Abstract drag interaction handler for touch and mouse events.
Usage: Three instances composed into ImageViewer:
- ImageSlider - Image panning
- SnapSlider - Snap view handle dragging
- ZoomSlider - Zoom slider control
Key Methods:
init()- Attach event listenersstartHandler()- Begin drag operationmoveHandler()- Track position changesendHandler()- End drag and cleanupdestroy()- Remove all listeners
4. Utility Functions (src/util.ts)
Key Functions:
easeOutQuart()- Smooth animation timing functioncreateElement()- DOM element creation helperaddClass/removeClass()- Class managementcss()- Style getter/setterimageLoaded()- Check if image is loadedassignEvent()- Event listener wrapper
Build and Development
Build Commands
# Primary build (Vite + TypeScript)
npm run build # Builds bundles and declarations
# Additional checks
npm run type-check # Standalone TS verification
npm run test:run # Unit tests
Build Pipeline
Vite Library Build (vite.config.ts):
- Entry:
src/index.tswith library formatses,cjs, andumd(output todist/) - Bundles and minifies with Vite (Rollup internal pipeline) and outputs source maps
- Generates TypeScript declarations via
vite-plugin-dts - Emits CSS from
src/scss/build.scss(custombuild-csshook):dist/iv-viewer-ts.cssvia autoprefixerdist/iv-viewer-ts.min.cssvia autoprefixer + cssnano
TypeScript Check (tsc --noEmit):
- Ensures the compiler configuration passes outside of the Vite build
Development Workflow
- Code Changes: Edit TypeScript files in
src/ - Style Changes: Edit SCSS files in
src/scss/ - Build: Run
npm run buildor individual build commands - Test: Open
example/index.htmlto test changes - Type Check: Run
npm run type-checkto validate the TS config
TypeScript Configuration
Compiler Settings (tsconfig.json)
{
"compilerOptions": {
"target": "es2015",
"useDefineForClassFields": true,
"module": "esnext",
"lib": ["dom", "es2015", "es2016", "es2017"],
"moduleResolution": "Node",
"strict": false,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"noEmit": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"skipLibCheck": true,
"downlevelIteration": true
}
}
ESLint Configuration
- TypeScript parser enabled
- Unused variables detection
- Consistent code style enforcement
Important Patterns and Guidelines
1. Class-Based Architecture
- ImageViewer: Main viewer class
- FullScreenViewer extends ImageViewer: Inheritance pattern
- Slider: Reusable composition pattern
2. Event-Driven Design
listeners: {
(onInit(data), // Instance initialized
onDestroy(), // Instance destroyed
onImageLoaded(data), // Image successfully loaded
onImageError(data), // Image load failed
onZoomChange(data)); // Zoom value changed
}
3. State Management
- Private
_stateobject holds all viewer state - Private
_elementsobject holds DOM references - Private
_optionsobject holds configuration - Public API methods manipulate state safely
4. Animation and Performance
- Uses
requestAnimationFrame()for 60fps animations easeOutQuart()timing function for natural motion- Momentum-based panning with physics simulation
- Proper cleanup of animation frames in
_clearFrames()
5. Memory Management
destroy() {
// 1. Clear animation frames
this._clearFrames();
// 2. Destroy slider instances
this._sliders.imageSlider?.destroy();
// 3. Remove event listeners
assignEvent(window, 'resize', this.refresh, true);
// 4. Clear references
this._elements = {};
this._state = {};
}
6. CSS Namespacing
- All classes prefixed with
.iv-to prevent conflicts - Example:
.iv-image-view,.iv-snap-view,.iv-zoom-slider
7. SCSS Variables
Customizable theme through SCSS variables in src/scss/_variables.scss:
$color-1: #222;
$color-2: #ccc;
$color-3: #888;
$color-4: #fff;
$snap-view-width: 150px;
$snap-view-height: 150px;
Common Tasks for Agents
Adding a New Feature
- Read: Understand the relevant component (
ImageViewer.ts, etc.) - Modify: Add the feature with proper TypeScript types
- Update: Add any new options to the Options interface
- Test: Verify in
example/HTML files - Build: Run
npm run buildto verify compilation - Document: Update README.md if needed
Fixing a Bug
- Locate: Use grep to find relevant code
- Read: Understand the affected component
- Fix: Make minimal changes to resolve the issue
- Test: Verify fix doesn't break existing functionality
- Build: Ensure TypeScript compilation succeeds
Updating Dependencies
- Check: Review
package.jsondevDependencies - Update: Modify version numbers carefully
- Test: Run
npm run buildandnpm run type-checkto verify compatibility - Verify: Check that examples still work
Modifying Styles
- Edit: Modify SCSS files in
src/scss/ - Build: Run
npm run build(CSS emitted via Vite plugin) - Test: Check visual changes in
example/pages - Verify: Ensure both minified and unminified CSS are generated in
dist/
File Naming Conventions
- Source: PascalCase for classes (
ImageViewer.ts) - Utilities: camelCase for utilities (
util.ts) - Config: kebab-case for configs (
vite.config.ts) - Styles: kebab-case with underscore for partials (
_variables.scss) - Distribution: kebab-case (
iv-viewer-ts.js)
Testing Considerations
Manual Testing
- Use
example/directory HTML files - Test all three modes: fullscreen, container, image
- Verify on desktop (mouse) and touch devices
- Check browser console for errors
What to Test
- Image loading (low-res, high-res)
- Zoom controls (wheel, buttons, pinch)
- Panning/dragging
- Snap view functionality
- Event listeners firing correctly
- Responsive behavior on resize
- Touch gestures (if possible)
Recent Changes (Git History)
- Update devDependencies (v2.2.0)
- Refine API docs: Updated defaults (
hasZoomButtonsfalse) and callback payloads - Clarify image loading:
load/showaccept an optional hi-res URL; pass the same URL if only one asset is available - Destroy cleanup:
destroy()now returns void
Key Dependencies (Development Only)
{
"vite": "^6.0.5",
"typescript": "^5.7.2",
"sass": "^1.83.0",
"eslint": "^9.17.0",
"postcss": "^8.4.49",
"autoprefixer": "^10.4.20", // prefixes CSS for dist builds
"cssnano": "^7.0.6", // minifies dist CSS via the build-css hook
"vite-plugin-dts": "^4.3.0"
}
Production Dependencies: None (zero dependencies)
Agent Guidelines
When Making Changes
- Always read files first before modifying
- Prefer strict typing - avoid implicit
anyand tighten types when touching code - Maintain backward compatibility when possible
- Follow existing patterns in the codebase
- Test in examples before committing
- Clean up properly - remove unused variables
- Preserve formatting and code style
Code Quality Standards
- No unused variables or parameters
- Proper TypeScript types for all functions
- Event listeners must be cleaned up in
destroy() - Animation frames must be cleared in
_clearFrames() - All public APIs should be documented with JSDoc
Build Verification
Before committing, ensure:
npm run build # Must succeed without errors
npm run type-check # Must succeed without errors
npm run test:run # Must succeed without errors
Summary
iv-viewer-ts is a well-architected, TypeScript-based image viewer library with:
- Clean separation of concerns (viewer, fullscreen, slider, utilities)
- Zero dependencies for maximum portability
- Multiple bundle formats for broad compatibility
- Type-safe API with full TypeScript support
- Event-driven architecture for extensibility
- Performance-focused with smooth animations and progressive loading
When working with this project, prioritize maintaining its lightweight nature, type safety, and clean API design.