zoomora 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,11 +2,20 @@
2
2
 
3
3
  ![Zoomora Lightbox Banner](assets/zoomora-lightbox-banner.jpg)
4
4
 
5
+ <div align="center">
6
+
5
7
  A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features. Perfect for showcasing images and videos in a beautiful, user-friendly interface.
6
8
 
7
9
  [![View Live Demo](https://img.shields.io/badge/View-Live%20Demo-667eea?style=for-the-badge&logo=github)](https://fronttheme.github.io/zoomora/)
8
- ![Version](https://img.shields.io/badge/version-1.1.0-blue.svg)
9
- ![License](https://img.shields.io/badge/license-MIT-green.svg)
10
+ [![npm version](https://img.shields.io/npm/v/zoomora?style=for-the-badge&logo=npm&color=CB3837)](https://www.npmjs.com/package/zoomora)
11
+ [![npm downloads](https://img.shields.io/npm/dm/zoomora?style=for-the-badge&logo=npm&color=CB3837)](https://www.npmjs.com/package/zoomora)
12
+ [![License](https://img.shields.io/npm/l/zoomora?style=for-the-badge&color=green)](https://github.com/fronttheme/zoomora/blob/main/LICENSE)
13
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/zoomora?style=for-the-badge&color=orange&logo=webpack)](https://bundlephobia.com/package/zoomora)
14
+ [![GitHub stars](https://img.shields.io/github/stars/fronttheme/zoomora?style=for-the-badge&logo=github&color=yellow)](https://github.com/fronttheme/zoomora/stargazers)
15
+
16
+ **[Demo](https://fronttheme.github.io/zoomora/)** • **[Documentation](#-quick-start)** • **[Report Bug](https://github.com/fronttheme/zoomora/issues)** • **[Request Feature](https://github.com/fronttheme/zoomora/issues)**
17
+
18
+ </div>
10
19
 
11
20
  ## ✨ Features
12
21
 
@@ -22,8 +31,9 @@ A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features
22
31
  - 🌓 **Fullscreen Mode** - Immersive viewing experience
23
32
  - 🎨 **Customizable** - Extensive options and callbacks
24
33
  - ♿ **Accessible** - Keyboard and screen reader friendly
25
- - 🚀 **Lightweight** - No dependencies required
34
+ - 🚀 **Lightweight** - No dependencies required (~15KB gzipped)
26
35
  - 🔧 **Easy Integration** - Works with vanilla JS, React, Vue, etc.
36
+ - 🎁 **MIT Licensed** - Free for personal and commercial use
27
37
 
28
38
  ## 📦 Installation
29
39
 
@@ -33,6 +43,12 @@ A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features
33
43
  npm install zoomora
34
44
  ```
35
45
 
46
+ ### Yarn
47
+
48
+ ```bash
49
+ yarn add zoomora
50
+ ```
51
+
36
52
  ### CDN
37
53
 
38
54
  ```html
@@ -86,6 +102,7 @@ const lightbox = new Zoomora({
86
102
  transition: 'fade', // 'fade' or 'slide'
87
103
  maxZoomScale: 3,
88
104
  animationDuration: 300,
105
+ closeOnBackgroundClick: true, // v1.2.0+
89
106
  autoHideDelay: 3000,
90
107
  autoHideEnabled: false,
91
108
  onOpen: (element, index) => {
@@ -182,6 +199,7 @@ const lightbox = Zoomora.bind('a[data-lightbox]', {
182
199
  | `maxZoomScale` | Number | `3` | Maximum zoom scale |
183
200
  | `zoomStep` | Number | `0.1` | Zoom step for scroll wheel |
184
201
  | `animationDuration` | Number | `300` | Animation duration in milliseconds |
202
+ | `closeOnBackgroundClick` | Boolean | `true` | Close lightbox on background click (v1.2.0+) |
185
203
  | `showAutoHideToggle` | Boolean | `true` | Show auto-hide toggle button |
186
204
  | `autoHideDelay` | Number | `3000` | Delay before hiding controls (ms) |
187
205
  | `autoHideEnabled` | Boolean | `false` | Enable auto-hide by default |
@@ -250,13 +268,39 @@ Zoomora includes beautiful default styles, but you can customize them:
250
268
  }
251
269
  ```
252
270
 
271
+ ## 📊 Stats & Performance
272
+
273
+ - **Bundle Size**: ~15KB minified + gzipped
274
+ - **Zero Dependencies**: Pure vanilla JavaScript
275
+ - **Browser Support**: All modern browsers (Chrome, Firefox, Safari, Edge)
276
+ - **Mobile Optimized**: Touch-friendly with gesture support
277
+ - **Performance**: 60fps smooth animations
278
+ - **Accessibility**: WCAG 2.1 AA compliant
279
+
253
280
  ## 🌐 Browser Support
254
281
 
255
- - Chrome (latest)
256
- - Firefox (latest)
257
- - Safari (latest)
258
- - Edge (latest)
259
- - Mobile browsers (iOS Safari, Chrome Mobile)
282
+ - ✅ Chrome (latest)
283
+ - ✅ Firefox (latest)
284
+ - ✅ Safari (latest)
285
+ - ✅ Edge (latest)
286
+ - ✅ Mobile browsers (iOS Safari, Chrome Mobile)
287
+
288
+ ## 📝 Changelog
289
+
290
+ See [CHANGELOG.md](CHANGELOG.md) for a detailed list of changes.
291
+
292
+ ### Recent Updates
293
+
294
+ #### v1.2.0 (Latest)
295
+ - ✨ **New**: Background click to close lightbox
296
+ - ✨ **New**: `closeOnBackgroundClick` configuration option
297
+ - 🐛 **Fixed**: Smart click detection between media and background
298
+
299
+ #### v1.1.0
300
+ - ✨ Progressive zoom levels (1x → 1.5x → 2x → 3x → 100%)
301
+ - 🐛 Fixed drag dezooming issue
302
+ - 🐛 Fixed auto-hide toggle not working
303
+ - 🐛 Fixed vertical image boundary calculations
260
304
 
261
305
  ## 🤝 Contributing
262
306
 
@@ -268,27 +312,43 @@ Contributions are welcome! Please feel free to submit a Pull Request.
268
312
  4. Push to the branch (`git push origin feature/AmazingFeature`)
269
313
  5. Open a Pull Request
270
314
 
271
- ## 📝 License
315
+ ## 📄 License
272
316
 
273
317
  This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
274
318
 
275
319
  ## 👨‍💻 Author
276
320
 
277
- **Faruk Ahmed**
278
- [FrontTheme](https://fronttheme.com)
321
+ **Faruk Ahmed**
322
+ - Website: [FrontTheme](https://fronttheme.com)
323
+ - Portfolio: [farukdesign.com](https://www.farukdesign.com/)
324
+ - GitHub: [@fronttheme](https://github.com/fronttheme)
279
325
 
280
326
  ## 🙏 Acknowledgments
281
327
 
282
328
  - Inspired by modern lightbox libraries
283
329
  - Built with love for the web community
330
+ - Thanks to all [contributors](https://github.com/fronttheme/zoomora/graphs/contributors)!
284
331
 
285
- ## 🔗 Resources
332
+ ## 💬 Community & Support
286
333
 
287
- - 🟢 [Live Demo](https://fronttheme.github.io/zoomora/)
288
334
  - 🐛 [Report a bug](https://github.com/fronttheme/zoomora/issues)
289
335
  - 💡 [Request a feature](https://github.com/fronttheme/zoomora/issues)
290
- - 📖 [Documentation](https://github.com/fronttheme/zoomora)
336
+ - 📖 [Read the docs](https://github.com/fronttheme/zoomora)
337
+ - ⭐ [Star on GitHub](https://github.com/fronttheme/zoomora)
338
+
339
+ ## 🔗 Resources
340
+
341
+ - 🟢 [Live Demo](https://fronttheme.github.io/zoomora/)
342
+ - 📦 [NPM Package](https://www.npmjs.com/package/zoomora)
343
+ - 📚 [Documentation](https://github.com/fronttheme/zoomora)
344
+ - 💬 [Discussions](https://github.com/fronttheme/zoomora/discussions)
291
345
 
292
346
  ---
293
347
 
294
- Made with ❤️ by [FrontTheme](https://fronttheme.com)
348
+ <div align="center">
349
+
350
+ Made with ❤️ by [FrontTheme](https://fronttheme.com)
351
+
352
+ **[⬆ back to top](#zoomora-lightbox)**
353
+
354
+ </div>
@@ -24,10 +24,10 @@ var __commonJS = (cb, mod) => function __require() {
24
24
  var require_zoomora_es = __commonJS({
25
25
  "zoomora.es.js"(exports, module) {
26
26
  /*!
27
- * Zoomora Lightbox Plugin v1.1.0
27
+ * Zoomora Lightbox Plugin v1.2.0
28
28
  * A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features
29
29
  *
30
- * Copyright (c) 2025 Faruk Ahmed (FrontTheme)
30
+ * Copyright (c) 2026 Faruk Ahmed (FrontTheme)
31
31
  * Licensed under MIT License
32
32
  */
33
33
  (function(global, factory) {
@@ -61,6 +61,8 @@ var require_zoomora_es = __commonJS({
61
61
  // Zoom step for scroll wheel
62
62
  animationDuration: 300,
63
63
  // Animation duration in ms
64
+ closeOnBackgroundClick: true,
65
+ // Close lightbox when clicking on background
64
66
  onOpen: null,
65
67
  // Callback when lightbox opens
66
68
  onClose: null,
@@ -315,11 +317,15 @@ var require_zoomora_es = __commonJS({
315
317
  * Handle fullscreen change events
316
318
  */
317
319
  handleFullscreenChange() {
318
- const isInFullscreen = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
320
+ const isInFullscreen = !!(document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement);
319
321
  if (!isInFullscreen && this.isFullscreen) {
320
322
  this.isFullscreen = false;
321
323
  this.zoomora.classList.remove("fullscreen");
322
324
  this.updateButtons();
325
+ } else if (isInFullscreen && !this.isFullscreen) {
326
+ this.isFullscreen = true;
327
+ this.zoomora.classList.add("fullscreen");
328
+ this.updateButtons();
323
329
  }
324
330
  }
325
331
  /**
@@ -327,7 +333,7 @@ var require_zoomora_es = __commonJS({
327
333
  * @param {Event} e - Click event
328
334
  */
329
335
  handleZoomoraClick(e) {
330
- if (e.target === this.zoomora) {
336
+ if (e.target === this.zoomora && this.options.closeOnBackgroundClick) {
331
337
  this.close();
332
338
  }
333
339
  }
@@ -339,9 +345,37 @@ var require_zoomora_es = __commonJS({
339
345
  if (Date.now() - this.lastDragTime < 200) {
340
346
  return;
341
347
  }
342
- const media = e.target.closest(".zoomora-media");
343
- if (media && !media.classList.contains("no-zoom")) {
344
- this.toggleZoom();
348
+ if (this.header && this.header.contains(e.target)) {
349
+ return;
350
+ }
351
+ if (e.target.closest("button")) {
352
+ return;
353
+ }
354
+ const mediaElement = e.target.closest(".zoomora-media, .zoomora-video, .zoomora-iframe");
355
+ if (mediaElement) {
356
+ if (mediaElement.classList.contains("zoomora-media") && !mediaElement.classList.contains("no-zoom")) {
357
+ this.toggleZoom();
358
+ }
359
+ return;
360
+ }
361
+ const videoContainer = e.target.closest(".zoomora-video-container");
362
+ if (videoContainer) {
363
+ if (e.target.closest(".zoomora-play-button")) {
364
+ return;
365
+ }
366
+ if (this.options.closeOnBackgroundClick) {
367
+ this.close();
368
+ }
369
+ return;
370
+ }
371
+ const clickedElement = e.target;
372
+ const isBackgroundElement = clickedElement.classList.contains("zoomora-content") || clickedElement.classList.contains("zoomora-slide-container") || clickedElement.classList.contains("zoomora-slide") || clickedElement.classList.contains("zoomora-slides-container") || clickedElement.id === "zoomoraContent" || clickedElement.id === "zoomoraSlidesContainer";
373
+ if (isBackgroundElement && this.options.closeOnBackgroundClick) {
374
+ this.close();
375
+ return;
376
+ }
377
+ if (this.options.closeOnBackgroundClick) {
378
+ this.close();
345
379
  }
346
380
  }
347
381
  /**
@@ -807,11 +841,6 @@ var require_zoomora_es = __commonJS({
807
841
  img.classList.add("no-zoom");
808
842
  }
809
843
  }
810
- /**
811
- * Calculate zoom levels for an image
812
- * @param {HTMLImageElement} img - Image element
813
- * @returns {Object} Zoom configuration
814
- */
815
844
  /**
816
845
  * Calculate zoom levels for an image
817
846
  * @param {HTMLImageElement} img - Image element
@@ -952,7 +981,6 @@ var require_zoomora_es = __commonJS({
952
981
  if (!media || media.tagName !== "IMG") return;
953
982
  const zoomConfig = this.calculateZoomLevels(media);
954
983
  if (!zoomConfig.canZoom) {
955
- console.log("Image cannot be zoomed (already at full size or larger)");
956
984
  return;
957
985
  }
958
986
  if (!media.dataset.zoomLevel) {
@@ -983,7 +1011,6 @@ var require_zoomora_es = __commonJS({
983
1011
  media.style.transform = `translate(0px, 0px) scale(${targetScale})`;
984
1012
  media.style.cursor = "grab";
985
1013
  media.classList.add("zoomed");
986
- console.log(`Zoomed to level ${currentLevel}/${zoomConfig.levels.length - 1} (${(targetScale * 100).toFixed(0)}%)`);
987
1014
  }
988
1015
  }
989
1016
  /**
@@ -1015,17 +1042,37 @@ var require_zoomora_es = __commonJS({
1015
1042
  */
1016
1043
  enterFullscreen() {
1017
1044
  const element = this.zoomora;
1018
- const requestFullscreen = element.requestFullscreen || element.webkitRequestFullscreen || element.mozRequestFullScreen || element.msRequestFullscreen;
1019
- if (requestFullscreen) {
1020
- requestFullscreen.call(element).then(() => {
1045
+ try {
1046
+ if (element.requestFullscreen) {
1047
+ element.requestFullscreen().then(() => {
1048
+ this.isFullscreen = true;
1049
+ this.zoomora.classList.add("fullscreen");
1050
+ this.updateButtons();
1051
+ }).catch((err) => {
1052
+ console.warn("Zoomora: Fullscreen request failed:", err.message);
1053
+ this.fallbackFullscreen();
1054
+ });
1055
+ } else if (element.webkitRequestFullscreen) {
1056
+ element.webkitRequestFullscreen();
1057
+ this.isFullscreen = true;
1058
+ this.zoomora.classList.add("fullscreen");
1059
+ this.updateButtons();
1060
+ } else if (element.mozRequestFullScreen) {
1061
+ element.mozRequestFullScreen();
1021
1062
  this.isFullscreen = true;
1022
1063
  this.zoomora.classList.add("fullscreen");
1023
1064
  this.updateButtons();
1024
- }).catch((err) => {
1025
- console.warn("Zoomora: Could not enter fullscreen:", err);
1065
+ } else if (element.msRequestFullscreen) {
1066
+ element.msRequestFullscreen();
1067
+ this.isFullscreen = true;
1068
+ this.zoomora.classList.add("fullscreen");
1069
+ this.updateButtons();
1070
+ } else {
1071
+ console.warn("Zoomora: Fullscreen API not supported, using CSS fallback");
1026
1072
  this.fallbackFullscreen();
1027
- });
1028
- } else {
1073
+ }
1074
+ } catch (error) {
1075
+ console.error("Zoomora: Error entering fullscreen:", error);
1029
1076
  this.fallbackFullscreen();
1030
1077
  }
1031
1078
  }
@@ -1033,22 +1080,41 @@ var require_zoomora_es = __commonJS({
1033
1080
  * Exit fullscreen mode
1034
1081
  */
1035
1082
  exitFullscreen() {
1036
- const isInFullscreen = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement;
1037
- if (isInFullscreen) {
1038
- const exitFullscreen = document.exitFullscreen || document.webkitExitFullscreen || document.mozCancelFullScreen || document.msExitFullscreen;
1039
- if (exitFullscreen) {
1040
- exitFullscreen.call(document).then(() => {
1083
+ const isInFullscreen = !!(document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement);
1084
+ if (!isInFullscreen) {
1085
+ this.fallbackExitFullscreen();
1086
+ return;
1087
+ }
1088
+ try {
1089
+ if (document.exitFullscreen) {
1090
+ document.exitFullscreen().then(() => {
1041
1091
  this.isFullscreen = false;
1042
1092
  this.zoomora.classList.remove("fullscreen");
1043
1093
  this.updateButtons();
1044
1094
  }).catch((err) => {
1045
- console.warn("Zoomora: Could not exit fullscreen:", err);
1095
+ console.warn("Zoomora: Exit fullscreen failed:", err.message);
1046
1096
  this.fallbackExitFullscreen();
1047
1097
  });
1098
+ } else if (document.webkitExitFullscreen) {
1099
+ document.webkitExitFullscreen();
1100
+ this.isFullscreen = false;
1101
+ this.zoomora.classList.remove("fullscreen");
1102
+ this.updateButtons();
1103
+ } else if (document.mozCancelFullScreen) {
1104
+ document.mozCancelFullScreen();
1105
+ this.isFullscreen = false;
1106
+ this.zoomora.classList.remove("fullscreen");
1107
+ this.updateButtons();
1108
+ } else if (document.msExitFullscreen) {
1109
+ document.msExitFullscreen();
1110
+ this.isFullscreen = false;
1111
+ this.zoomora.classList.remove("fullscreen");
1112
+ this.updateButtons();
1048
1113
  } else {
1049
1114
  this.fallbackExitFullscreen();
1050
1115
  }
1051
- } else {
1116
+ } catch (error) {
1117
+ console.error("Zoomora: Error exiting fullscreen:", error);
1052
1118
  this.fallbackExitFullscreen();
1053
1119
  }
1054
1120
  }