{"_id":"@alekstar79/comparison-slider","_rev":"2-aa343509540c53673660cccff8ed1a77","name":"@alekstar79/comparison-slider","dist-tags":{"latest":"1.0.1"},"versions":{"1.0.0":{"name":"@alekstar79/comparison-slider","version":"1.0.0","keywords":["typescript","images","comparison","slider","library"],"author":{"name":"Aleksey Tarasenko","email":"alekstar79@yandex.ru"},"license":"MIT","_id":"@alekstar79/comparison-slider@1.0.0","maintainers":[{"name":"alekstar79","email":"alekstar79@yandex.ru"}],"homepage":"https://github.com/alekstar79/comparison-slider.git","bugs":{"url":"https://github.com/alekstar79/comparison-slider/issues"},"dist":{"shasum":"1ab95fa8a45a8abe342e3eb772f87e9e2fed2657","tarball":"https://registry.npmjs.org/@alekstar79/comparison-slider/-/comparison-slider-1.0.0.tgz","fileCount":74,"integrity":"sha512-HUOCJSBWUkSRtpv4ZD3HxUgAxH4PGnDzGZ8ScEjK6cIDOGRpXjyb2gg9OBKFp1EeHsNTRNhcpl5qx1PRmpVyEA==","signatures":[{"sig":"MEYCIQDCDa52sfO3HYuFuV8YYstzPlS0I4Z3SDToWFdSaxsLKQIhAMqXyqR23XYDhUGcP0pFB136HW7mCrqfad3ApydSde9b","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":125285},"main":"./lib/index.js","type":"module","types":"./lib/index.d.ts","module":"./lib/index.js","engines":{"npm":">=9.0.0","node":">=18.0.0"},"exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.js"},"./plugins/*":{"types":"./lib/plugins/*.d.ts","import":"./lib/plugins/*.js"},"./styles/core.css":"./lib/styles/core.css","./styles/SavePlugin.css":"./lib/styles/SavePlugin.css","./styles/LabelPlugin.css":"./lib/styles/LabelPlugin.css","./styles/FilterPlugin.css":"./lib/styles/FilterPlugin.css","./styles/ImagePanPlugin.css":"./lib/styles/ImagePanPlugin.css","./styles/ImageSetPlugin.css":"./lib/styles/ImageSetPlugin.css","./styles/MagnifierPlugin.css":"./lib/styles/MagnifierPlugin.css","./styles/FullscreenPlugin.css":"./lib/styles/FullscreenPlugin.css"},"gitHead":"ee3f577ba7f7766828e60721335548b6fed13dcd","private":false,"scripts":{"dev":"vite","test":"vitest run","build":"yarn build:lib && vite -c vite.config.ts build","preview":"vite preview","coverage":"vitest run --coverage","build:lib":"vite -c vite.lib.config.ts build"},"_npmUser":{"name":"alekstar79","email":"alekstar79@yandex.ru"},"repository":{"url":"git+https://github.com/alekstar79/comparison-slider.git","type":"git"},"_npmVersion":"10.9.4","description":"A powerful, modern, and highly customizable TypeScript library that seamlessly combines an image comparison slider with a feature-rich image gallery.","directories":{},"sideEffects":["**/*.css"],"_nodeVersion":"22.21.1","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"glob":"^13.0.0","vite":"^5.2.11","jsdom":"^24.1.0","vitest":"^1.6.0","typescript":"^5.4.5","@types/node":"^20.12.12","vite-plugin-dts":"^3.9.1","@vitest/coverage-v8":"^1.6.0"},"_npmOperationalInternal":{"tmp":"tmp/comparison-slider_1.0.0_1769892918787_0.17848472247502567","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@alekstar79/comparison-slider","description":"A powerful, modern, and highly customizable TypeScript library that seamlessly combines an image comparison slider with a feature-rich image gallery.","version":"1.0.1","private":false,"type":"module","main":"./lib/index.js","module":"./lib/index.js","types":"./lib/index.d.ts","license":"MIT","author":{"name":"Aleksey Tarasenko","email":"alekstar79@yandex.ru"},"homepage":"https://github.com/alekstar79/comparison-slider.git","repository":{"type":"git","url":"git+https://github.com/alekstar79/comparison-slider.git"},"bugs":{"url":"https://github.com/alekstar79/comparison-slider/issues"},"keywords":["typescript","images","comparison","slider","library"],"sideEffects":["**/*.css"],"exports":{".":{"types":"./lib/index.d.ts","import":"./lib/index.js"},"./plugins/*":{"types":"./lib/plugins/*.d.ts","import":"./lib/plugins/*.js"},"./styles/core.css":"./lib/styles/core.css","./styles/FilterPlugin.css":"./lib/styles/FilterPlugin.css","./styles/LabelPlugin.css":"./lib/styles/LabelPlugin.css","./styles/MagnifierPlugin.css":"./lib/styles/MagnifierPlugin.css","./styles/SavePlugin.css":"./lib/styles/SavePlugin.css","./styles/ImageSetPlugin.css":"./lib/styles/ImageSetPlugin.css","./styles/FullscreenPlugin.css":"./lib/styles/FullscreenPlugin.css","./styles/ImagePanPlugin.css":"./lib/styles/ImagePanPlugin.css"},"scripts":{"dev":"vite","build":"yarn build:lib && vite -c vite.config.ts build","build:lib":"vite -c vite.lib.config.ts build","preview":"vite preview","test":"vitest run","coverage":"vitest run --coverage"},"devDependencies":{"@types/node":"^20.12.12","@vitest/coverage-v8":"^1.6.0","glob":"^13.0.0","jsdom":"^24.1.0","typescript":"^5.4.5","vite":"^5.2.11","vite-plugin-dts":"^3.9.1","vitest":"^1.6.0"},"engines":{"node":">=18.0.0","npm":">=9.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_id":"@alekstar79/comparison-slider@1.0.1","gitHead":"3b98edc9ba7e41bed7a3cf890f0f6d3709004d1c","_nodeVersion":"22.21.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-9NfXfqbZ1VcP+W+Ievrp76J8Wn+DA5c7xLEOQnZydtLmwU4Ajc1LKIce4LxKUbOXLE5qsWhbf240Xph72+dZ5Q==","shasum":"c8eeda9fe91f59f8730b791c4352eade18b4ce12","tarball":"https://registry.npmjs.org/@alekstar79/comparison-slider/-/comparison-slider-1.0.1.tgz","fileCount":74,"unpackedSize":125147,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD2RRiUds8i/xxxFDr56LYkTz7ZORKSoB6u2OVOJSSNogIhAMdoaUlnzxkyQVER/PAjH1+BOLACkMzJ20x2V+diAf3B"}]},"_npmUser":{"name":"alekstar79","email":"alekstar79@yandex.ru"},"directories":{},"maintainers":[{"name":"alekstar79","email":"alekstar79@yandex.ru"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/comparison-slider_1.0.1_1769975465780_0.22209105055604117"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-31T20:55:18.700Z","modified":"2026-02-01T19:51:06.035Z","1.0.0":"2026-01-31T20:55:18.953Z","1.0.1":"2026-02-01T19:51:05.924Z"},"bugs":{"url":"https://github.com/alekstar79/comparison-slider/issues"},"author":{"name":"Aleksey Tarasenko","email":"alekstar79@yandex.ru"},"license":"MIT","homepage":"https://github.com/alekstar79/comparison-slider.git","keywords":["typescript","images","comparison","slider","library"],"repository":{"type":"git","url":"git+https://github.com/alekstar79/comparison-slider.git"},"description":"A powerful, modern, and highly customizable TypeScript library that seamlessly combines an image comparison slider with a feature-rich image gallery.","maintainers":[{"name":"alekstar79","email":"alekstar79@yandex.ru"}],"readme":"# ✨ Comparison Slider TS\n\n[![NPM Version](https://img.shields.io/npm/v/comparison-slider.svg)](https://www.npmjs.com/package/@alekstar79/comparison-slider)\n[![License](https://img.shields.io/badge/License-MIT-blue)](LICENSE)\n[![GitHub](https://img.shields.io/badge/github-repo-green.svg?style=flat)](https://github.com/alekstar79/comparison-slider)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue?style=flat-square)](https://www.typescriptlang.org)\n[![Coverage](https://img.shields.io/badge/coverage-97.76%25-brightgreen.svg)](https://github.com/alekstar79/comparison-slider)\n\n**Comparison Slider TS** is a powerful, modern, and highly customizable TypeScript library that seamlessly combines the functionality of an image comparison slider with a feature-rich image gallery. Built with TypeScript and a flexible plugin architecture, it's designed for performance, extensibility, and a superior user experience.\n\nThis is not just another before-and-after slider. It's a comprehensive toolkit for interactive image presentation, allowing you to compare, filter, magnify, and navigate through image sets with smooth, hardware-accelerated effects.\n\n![slider](slider.svg)\n\n**[View Live Demo](https://alekstar79.github.io/comparison-slider)**\n\n---\n\n## 📖 Table of Contents\n\n<!-- TOC -->\n* [✨ Comparison Slider TS](#-comparison-slider-ts)\n  * [📖 Table of Contents](#-table-of-contents)\n  * [🌟 Core Concepts](#-core-concepts)\n  * [🚀 Getting Started](#-getting-started)\n    * [Installation](#installation)\n    * [Importing Styles](#importing-styles)\n    * [HTML Setup](#html-setup)\n    * [Initialization](#initialization)\n  * [⚙️ Configuration](#-configuration)\n    * [Via Object](#via-object)\n    * [Via `data-` Attributes](#via-data--attributes)\n    * [Detailed Configuration Options](#detailed-configuration-options)\n  * [🔌 Plugins API](#-plugins-api)\n  * [🎨 Transition Effects](#-transition-effects)\n  * [👨‍💻 API Reference](#-api-reference)\n    * [`new ComparisonSlider(image, config)`](#new-comparisonsliderimage-config)\n    * [`.mount()`](#mount)\n    * [`.updateImage(newImage, reset)`](#updateimagenewimage-reset)\n    * [`.toggleComparisonView()`](#togglecomparisonview)\n    * [`.use(plugin)`](#useplugin)\n  * [🤝 Contributing](#-contributing)\n    * [Development Setup](#development-setup)\n  * [📜 License](#-license)\n<!-- TOC -->\n\n---\n\n## 🌟 Core Concepts\n\n1.  **Hybrid Engine**: The library can function as a classic two-image comparison tool or as a multi-image gallery, or both at the same time. This is controlled by the `comparison` and `data-imgset` options.\n2.  **Plugin-Driven Architecture**: Core features like the magnifier, image set navigation, and panning are implemented as independent plugins. This keeps the core light and allows you to bundle only the functionality you need.\n3.  **Canvas Rendering**: Instead of manipulating DOM elements, the library renders images onto an HTML5 Canvas. This enables high-performance pixel-level effects, transitions, and filtering that are impossible with standard `<img>` tags.\n4.  **Declarative and Imperative Configuration**: Configure everything declaratively via `data-` attributes in your HTML for simplicity, or use a detailed JavaScript object for maximum control and type safety.\n\n---\n\n## 🚀 Getting Started\n\n### Installation\n\nInstall the package from the npm registry:\n\n```bash\nnpm install @alekstar79/comparison-slider\n\n# or\n\nyarn add @alekstar79/comparison-slider\n```\n\n### Importing Styles\n\nThe library requires a core stylesheet and optional stylesheets for each plugin you use.\n\n```typescript\n// Import core styles\nimport '@alekstar79/comparison-slider-ts/styles/core.css'\n\n// Import styles for the plugins you are using\nimport '@alekstar79/comparison-slider-ts/styles/ImageSetPlugin.css'\nimport '@alekstar79/comparison-slider-ts/styles/MagnifierPlugin.css'\n// ... and so on for other plugins\n```\n\n### HTML Setup\n\nThe slider is initialized from a standard `<img>` element. The library will replace it with the full slider component.\n\n```html\n<!-- Basic Usage -->\n<img id=\"my-slider\" src=\"images/before.jpg\" alt=\"Before and After\" />\n\n<!-- Comparison Slider -->\n<img\n  src=\"./images/l1.jpg\"\n  class=\"slider-large\"\n  data-comparison-slide\n  data-action-buttons=\"{ top: '50%', transform: 'translateY(-50%)', left: '10px' }\"\n  data-features-buttons=\"{ top: '50%', transform: 'translateY(-50%)', right: '10px' }\"\n  data-action-buttons-direction=\"vertical\"\n  data-features-buttons-direction=\"vertical\"\n  data-direction=\"vertical\"\n  data-init-x=\"300\"\n  data-init-y=\"150\"\n  data-filters=\"all\"\n  alt=\"Before and After\"\n>\n\n<!-- Image Gallery Slider -->\n<img\n  class=\"slider-large\"\n  data-imgset=\"./images/img1.jpg,./images/img2.jpg,./images/img3.jpg,./images/img4.jpg\"\n  data-comparison-slide\n  data-direction=\"vertical\"\n  data-filters=\"all\"\n  data-init-x=\"200\"\n  data-init-y=\"300\"\n  alt=\"My Awesome Gallery\"\n  src=\"\"\n>\n```\n\n### Initialization\n\nImport the `ComparisonSlider` class, create a new instance with your image element and a configuration object, and then call `.mount()`.\n\n```typescript\nimport { ComparisonSlider, defaultConfig } from '@alekstar79/comparison-slider'\n\nconst imageElement = document.getElementById('my-slider')\n\n// You can start with the defaultConfig and override properties\nconst myConfig = JSON.parse(JSON.stringify(defaultConfig))\nmyConfig.hoverToSlide = true\nmyConfig.magnifier.defaultZoom = 3\n\n// Create and mount the slider\nconst slider = new ComparisonSlider(imageElement, myConfig)\nslider.mount()\n```\n\n---\n\n## ⚙️ Configuration\n\nYou have two ways to configure the slider, which can be used together.\n\n### Via Object\n\nThis is the most powerful method, giving you access to all options with full type-safety if you're using TypeScript.\n\n```typescript\nconst slider = new ComparisonSlider(imageElement, {\n  ...defaultConfig,\n  direction: 'vertical',\n  imageSet: {\n    ...defaultConfig.imageSet,\n    autoplay: true,\n  }\n})\n```\n\n### Via `data-` Attributes\n\nFor quick setup, most configuration options can be set directly in HTML. The library automatically parses these attributes.\n\n-   **Simple values**: `data-direction=\"vertical\"`\n-   **Nested values**: Use kebab-case for nested properties. `data-image-set-autoplay=\"true\"`\n-   **Complex objects**: For properties that are objects (like UI block positions), pass a JavaScript-like object string.\n\n    ```html\n    <img\n      id=\"my-slider\"\n      src=\"images/before.jpg\"\n      data-action-buttons=\"{ top: '50%', left: '1rem', transform: 'translateY(-50%)' }\"\n      data-nav-buttons-direction=\"vertical\"\n      alt=\"\"\n    />\n    ```\n\n### Detailed Configuration Options\n\nBelow is a comprehensive list of all available options found in the [defaultConfig](/src/config.ts).\n\n| Property                    | Type        | Default        | `data-` Attribute                  | Description                                                                                    |\n|:----------------------------|:------------|:---------------|:-----------------------------------|:-----------------------------------------------------------------------------------------------|\n| `comparison`                | `boolean`   | `true`         | `data-comparison`                  | Enables the core before/after comparison functionality.                                        |\n| `hoverToSlide`              | `boolean`   | `false`        | `data-hover-to-slide`              | If `true`, the handle follows the mouse without clicking.                                      |\n| `direction`                 | `string`    | `'horizontal'` | `data-direction`                   | Orientation of the slider: `'horizontal'` or `'vertical'`.                                     |\n| `labels.before`             | `string`    | `'Before'`     | `data-labels-before`               | Text for the \"before\" label.                                                                   |\n| `labels.after`              | `string`    | `'After'`      | `data-labels-after`                | Text for the \"after\" label.                                                                    |\n| `labels.position`           | `string`    | `'top-left'`   | `data-labels-position`             | Position of the labels.                                                                        |\n| `imageSet.autoplay`         | `boolean`   | `false`        | `data-image-set-autoplay`          | Enables automatic transitioning between images in a set.                                       |\n| `imageSet.interval`         | `number`    | `5000`         | `data-image-set-interval`          | Time in milliseconds between transitions in autoplay mode.                                     |\n| `imageSet.pauseOnHover`     | `boolean`   | `false`        | `data-image-set-pause-on-hover`    | Pauses autoplay when the mouse is over the slider.                                             |\n| `imageSet.cyclic`           | `boolean`   | `false`        | `data-image-set-cyclic`            | Allows navigation to loop from the last image to the first.                                    |\n| `imageSet.transitionEffect` | `string`    | `'slide'`      | `data-image-set-transition-effect` | The animation effect to use. See [Transition Effects](#-transition-effects).                   |\n| `imageSet.duration`         | `number`    | `1000`         | `data-image-set-duration`          | Duration of the transition effect in milliseconds.                                             |\n| `magnifier.enabled`         | `boolean`   | `true`         | `data-magnifier-enabled`           | Enables the magnifier plugin.                                                                  |\n| `magnifier.size`            | `number`    | `180`          | `data-magnifier-size`              | Diameter of the magnifier circle in pixels.                                                    |\n| `magnifier.defaultZoom`     | `number`    | `2`            | `data-magnifier-default-zoom`      | The initial zoom level.                                                                        |\n| `magnifier.zoomLevels`      | `number[]`  | `[2, 3, 4]`    | `data-magnifier-zoom-levels`       | Array of available zoom levels in the panel.                                                   |\n| `uiBlocks`                  | `UIBlock[]` | *(array)*      | `data-[block-id]`                  | Defines the layout of UI elements. See [SliderHtmlBuilder.ts](/src/core/SliderHtmlBuilder.ts). |\n\n---\n\n## 🔌 Plugins API\n\nThe plugin architecture is the heart of the library's extensibility. Each plugin is a class that hooks into the slider's lifecycle to add new functionality. They are initialized automatically by the main `ComparisonSlider` class.\n\n-   **[`ImageSetPlugin`](/src/plugins/ImageSetPlugin.ts)**: Manages image galleries defined by `data-imgset`. It handles navigation (next/prev), autoplay, and orchestrates the transition effects between images.\n\n-   **[`MagnifierPlugin`](/src/plugins/MagnifierPlugin.ts)**: Adds an interactive magnifying glass. It creates a separate canvas that follows the cursor, rendering a zoomed-in portion of the main canvas, including any applied filters and UI elements.\n\n-   **[`FilterPlugin`](/src/plugins/FilterPlugin.ts)**: Manages the filter selection UI. It dynamically adds/removes an \"Original\" filter button when switching between comparison and single-view modes and ensures the correct filter is applied.\n\n-   **[`ImagePanPlugin`](/src/plugins/ImagePanPlugin.ts)**: Automatically detects if the source image has a different aspect ratio than the container. If so, it enables panning by clicking and dragging on the image, allowing users to explore the entire image.\n\n-   **[`SavePlugin`](/src/plugins/SavePlugin.ts)**: Adds a \"Save\" button. When clicked, it creates a new temporary canvas, redraws the current image with any active filters applied, and triggers a browser download of the resulting image.\n\n-   **[`FullscreenPlugin`](/src/plugins/FullscreenPlugin.ts)**: Provides a button to toggle the slider's container into and out of the browser's fullscreen mode.\n\n-   **[`LabelPlugin`](/src/plugins/LabelPlugin.ts)**: Manages the visibility and positioning of the \"Before\" and \"After\" labels, ensuring they are correctly clipped as the handle moves.\n\n---\n\n## 🎨 Transition Effects\n\nWhen using the `ImageSetPlugin`, you can choose from several visually impressive transition effects.\n\n| Effect         | Description                                                                          |\n|:---------------|:-------------------------------------------------------------------------------------|\n| **`slide`**    | The new image slides in smoothly over the old one.                                   |\n| **`dissolve`** | A cross-fade effect where the old image dissolves into the new one.                  |\n| **`blinds`**   | The new image is revealed through a series of animated vertical or horizontal slats. |\n| **`wipe`**     | A classic directional wipe transition.                                               |\n| **`wave`**     | A modern, GLSL-powered wave distortion effect that ripples across the image.         |\n\n---\n\n## 👨‍💻 API Reference\n\nWhile most functionality can be controlled via the configuration object, the `ComparisonSlider` instance provides several public methods for imperative control.\n\n### `new ComparisonSlider(image, config)`\n\nCreates a new slider instance.\n-   `image`: The `HTMLImageElement` to enhance.\n-   `config`: A configuration object to override the defaults.\n\n### `.mount()`\n\nInitializes all plugins, builds the required DOM structure, and replaces the original `<img>` element. This method is asynchronous and returns a `Promise` that resolves when the initial image is fully loaded and the slider is ready.\n\n### `.updateImage(newImage, reset)`\n\nUpdates the slider with a new source image.\n-   `newImage`: An `HTMLImageElement` or a URL `string` for the new image.\n-   `reset`: A `boolean` (`true` by default). If `true`, resets the handle to its initial position.\n\n### `.toggleComparisonView()`\n\nProgrammatically toggles the comparison view on or off.\n\n### `.use(plugin)`\n\nRegisters a custom plugin with the slider instance. This allows for extending the slider with your own functionality.\n\n---\n\n## 🤝 Contributing\n\nContributions are highly welcome! If you find a bug, have a feature request, or want to improve the documentation, please open an issue or submit a pull request.\n\n### Development Setup\n\n1.  Clone the repository.\n2.  Install dependencies: `npm install`\n3.  Start the development server: `npm run dev`\n4.  Run tests: `npm test`\n\n---\n\n## 📜 License\n\nThis project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.\n","readmeFilename":"README.md"}