zoomora 1.0.0 → 1.1.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.
@@ -22,7 +22,7 @@ var __spreadValues = (a, b) => {
22
22
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
23
23
 
24
24
  /*!
25
- * Zoomora Lightbox Plugin v1.0.0
25
+ * Zoomora Lightbox Plugin v1.1.0
26
26
  * A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features
27
27
  *
28
28
  * Copyright (c) 2025 Faruk Ahmed (FrontTheme)
@@ -100,6 +100,7 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
100
100
  this.autoHideDelay = 3e3;
101
101
  this.isControlsVisible = true;
102
102
  this.idleTimer = null;
103
+ this.lastDragTime = 0;
103
104
  this.boundMethods = {
104
105
  handleDocumentClick: this.handleDocumentClick.bind(this),
105
106
  handleKeydown: this.handleKeydown.bind(this),
@@ -152,6 +153,11 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
152
153
  console.warn("Zoomora: Lightbox already exists in DOM");
153
154
  return;
154
155
  }
156
+ const autoHideButtonHTML = this.options.showAutoHideToggle ? `
157
+ <button class="zoomora-btn" id="zoomoraAutoHideBtn" title="Toggle Auto-Hide Controls">
158
+ <i class="zoomorai-controls-off"></i>
159
+ </button>
160
+ ` : "";
155
161
  const zoomoraHTML = `
156
162
  <div class="zoomora" id="zoomoraLightbox">
157
163
  <div class="zoomora-container">
@@ -161,9 +167,7 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
161
167
  <button class="zoomora-btn" id="zoomoraThumbnailBtn" title="Toggle Thumbnails">
162
168
  <i class="zoomorai-thumbnails"></i>
163
169
  </button>
164
- <button class="zoomora-btn" id="zoomoraAutoHideBtn" title="Toggle Auto-Hide Controls">
165
- <i class="zoomorai-controls-off"></i>
166
- </button>
170
+ ${autoHideButtonHTML}
167
171
  <button class="zoomora-btn" id="zoomoraZoomBtn" title="Zoom">
168
172
  <i class="zoomorai-zoom"></i>
169
173
  </button>
@@ -237,10 +241,12 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
237
241
  this.addEventListener(this.content, "touchstart", this.boundMethods.handleTouchStart, { passive: false });
238
242
  this.addEventListener(this.content, "touchmove", this.boundMethods.handleTouchMove, { passive: false });
239
243
  this.addEventListener(this.content, "touchend", this.boundMethods.handleTouchEnd);
240
- this.addEventListener(document.getElementById("zoomoraAutoHideBtn"), "click", () => this.toggleAutoHide());
241
- this.addEventListener(this.zoomora, "mousemove", () => this.handleUserActivity());
242
- this.addEventListener(this.zoomora, "touchstart", () => this.handleUserActivity());
243
- this.addEventListener(this.zoomora, "keydown", () => this.handleUserActivity());
244
+ if (this.options.showAutoHideToggle) {
245
+ this.addEventListener(document.getElementById("zoomoraAutoHideBtn"), "click", () => this.toggleAutoHide());
246
+ this.addEventListener(this.zoomora, "mousemove", () => this.handleUserActivity());
247
+ this.addEventListener(this.zoomora, "touchstart", () => this.handleUserActivity());
248
+ this.addEventListener(this.zoomora, "keydown", () => this.handleUserActivity());
249
+ }
244
250
  }
245
251
  /**
246
252
  * Add event listener with cleanup tracking
@@ -328,8 +334,11 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
328
334
  * @param {Event} e - Click event
329
335
  */
330
336
  handleContentClick(e) {
337
+ if (Date.now() - this.lastDragTime < 200) {
338
+ return;
339
+ }
331
340
  const media = e.target.closest(".zoomora-media");
332
- if (media && !media.classList.contains("no-zoom") && !this.isDragging) {
341
+ if (media && !media.classList.contains("no-zoom")) {
333
342
  this.toggleZoom();
334
343
  }
335
344
  }
@@ -570,6 +579,10 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
570
579
  console.error("Zoomora: No source found for item");
571
580
  return;
572
581
  }
582
+ this.isZoomed = false;
583
+ this.currentX = 0;
584
+ this.currentY = 0;
585
+ this.currentScale = 1;
573
586
  this.loading.style.display = "block";
574
587
  if (this.slidesContainer) {
575
588
  this.slidesContainer.innerHTML = "";
@@ -792,6 +805,48 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
792
805
  img.classList.add("no-zoom");
793
806
  }
794
807
  }
808
+ /**
809
+ * Calculate zoom levels for an image
810
+ * @param {HTMLImageElement} img - Image element
811
+ * @returns {Object} Zoom configuration
812
+ */
813
+ /**
814
+ * Calculate zoom levels for an image
815
+ * @param {HTMLImageElement} img - Image element
816
+ * @returns {Object} Zoom configuration
817
+ */
818
+ calculateZoomLevels(img) {
819
+ if (!img || !img.naturalWidth || !img.naturalHeight) {
820
+ return { canZoom: false, levels: [], currentLevel: 0 };
821
+ }
822
+ const container = this.content.getBoundingClientRect();
823
+ const containerWidth = container.width;
824
+ const containerHeight = container.height;
825
+ const naturalWidth = img.naturalWidth;
826
+ const naturalHeight = img.naturalHeight;
827
+ const scaleToFitWidth = containerWidth / naturalWidth;
828
+ const scaleToFitHeight = containerHeight / naturalHeight;
829
+ const fitScale = Math.min(scaleToFitWidth, scaleToFitHeight);
830
+ if (fitScale >= 0.95) {
831
+ return { canZoom: false, levels: [], currentLevel: 0 };
832
+ }
833
+ const levels = [1];
834
+ if (fitScale * 1.5 <= 1) levels.push(1.5);
835
+ if (fitScale * 2 <= 1) levels.push(2);
836
+ if (fitScale * 3 <= 1) levels.push(3);
837
+ const actualSizeScale = 1 / fitScale;
838
+ if (actualSizeScale > levels[levels.length - 1]) {
839
+ levels.push(actualSizeScale);
840
+ }
841
+ return {
842
+ canZoom: levels.length > 1,
843
+ levels,
844
+ currentLevel: 0,
845
+ baseScale: fitScale,
846
+ naturalWidth,
847
+ naturalHeight
848
+ };
849
+ }
795
850
  /**
796
851
  * Update counter display
797
852
  */
@@ -892,25 +947,55 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
892
947
  */
893
948
  toggleZoom() {
894
949
  const media = this.content.querySelector(".zoomora-media");
895
- if (!media || media.tagName !== "IMG" || media.classList.contains("no-zoom")) return;
896
- this.isZoomed = !this.isZoomed;
897
- media.classList.toggle("zoomed", this.isZoomed);
898
- if (this.isZoomed) {
899
- const zoomRatio = parseFloat(media.dataset.zoomRatio) || 2;
900
- let zoomScale = Math.min(zoomRatio, this.options.maxZoomScale);
901
- if (zoomRatio > 2.5) {
902
- zoomScale = Math.min(zoomRatio * 0.7, 2.5);
903
- }
904
- media.style.transform = `scale(${zoomScale})`;
905
- media.style.cursor = "grab";
906
- media.dataset.currentZoomScale = zoomScale;
907
- this.currentScale = zoomScale;
908
- } else {
950
+ if (!media || media.tagName !== "IMG") return;
951
+ const zoomConfig = this.calculateZoomLevels(media);
952
+ if (!zoomConfig.canZoom) {
953
+ console.log("Image cannot be zoomed (already at full size or larger)");
954
+ return;
955
+ }
956
+ if (!media.dataset.zoomLevel) {
957
+ media.dataset.zoomLevel = "0";
958
+ }
959
+ let currentLevel = parseInt(media.dataset.zoomLevel) || 0;
960
+ currentLevel++;
961
+ if (currentLevel >= zoomConfig.levels.length) {
962
+ currentLevel = 0;
963
+ }
964
+ const targetScale = zoomConfig.levels[currentLevel];
965
+ media.dataset.zoomLevel = currentLevel.toString();
966
+ if (currentLevel === 0) {
967
+ this.isZoomed = false;
968
+ this.isDragging = false;
969
+ media.classList.remove("dragging");
909
970
  media.style.transform = "";
910
- media.style.cursor = "";
971
+ media.style.cursor = "pointer";
972
+ media.classList.remove("zoomed");
911
973
  this.currentX = 0;
912
974
  this.currentY = 0;
913
975
  this.currentScale = 1;
976
+ } else {
977
+ this.isZoomed = true;
978
+ this.currentScale = targetScale;
979
+ this.currentX = 0;
980
+ this.currentY = 0;
981
+ media.style.transform = `translate(0px, 0px) scale(${targetScale})`;
982
+ media.style.cursor = "grab";
983
+ media.classList.add("zoomed");
984
+ console.log(`Zoomed to level ${currentLevel}/${zoomConfig.levels.length - 1} (${(targetScale * 100).toFixed(0)}%)`);
985
+ }
986
+ }
987
+ /**
988
+ * Update image transform based on current state
989
+ * @param {HTMLElement} media - Media element
990
+ */
991
+ updateImageTransform(media) {
992
+ if (!media) return;
993
+ if (this.currentScale === 1) {
994
+ media.style.transform = "";
995
+ } else {
996
+ const translateX = this.currentX / this.currentScale;
997
+ const translateY = this.currentY / this.currentScale;
998
+ media.style.transform = `scale(${this.currentScale}) translate(${translateX}px, ${translateY}px)`;
914
999
  }
915
1000
  }
916
1001
  /**
@@ -1008,15 +1093,19 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
1008
1093
  const media = this.content.querySelector(".zoomora-media");
1009
1094
  if (!media || !this.isZoomed) return;
1010
1095
  this.isDragging = true;
1096
+ media.classList.add("dragging");
1011
1097
  media.style.cursor = "grabbing";
1012
1098
  this.startX = e.clientX || e.touches && e.touches[0].clientX || 0;
1013
1099
  this.startY = e.clientY || e.touches && e.touches[0].clientY || 0;
1014
- const transform = media.style.transform;
1015
- const scaleMatch = transform.match(/scale\(([^)]+)\)/);
1016
- const translateMatch = transform.match(/translate\(([^,]+),\s*([^)]+)\)/);
1017
- this.currentScale = scaleMatch ? parseFloat(scaleMatch[1]) : 1;
1018
- this.currentX = translateMatch ? parseFloat(translateMatch[1]) : 0;
1019
- this.currentY = translateMatch ? parseFloat(translateMatch[2]) : 0;
1100
+ const transform = window.getComputedStyle(media).transform;
1101
+ if (transform && transform !== "none") {
1102
+ const matrix = new DOMMatrix(transform);
1103
+ this.currentX = matrix.m41;
1104
+ this.currentY = matrix.m42;
1105
+ } else {
1106
+ this.currentX = 0;
1107
+ this.currentY = 0;
1108
+ }
1020
1109
  e.preventDefault();
1021
1110
  }
1022
1111
  /**
@@ -1026,21 +1115,33 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
1026
1115
  drag(e) {
1027
1116
  if (!this.isDragging) return;
1028
1117
  e.preventDefault();
1118
+ const media = this.content.querySelector(".zoomora-media");
1119
+ if (!media) return;
1029
1120
  const clientX = e.clientX || e.touches && e.touches[0].clientX || 0;
1030
1121
  const clientY = e.clientY || e.touches && e.touches[0].clientY || 0;
1031
1122
  const deltaX = clientX - this.startX;
1032
1123
  const deltaY = clientY - this.startY;
1033
- const newX = this.currentX + deltaX;
1034
- const newY = this.currentY + deltaY;
1035
- const media = this.content.querySelector(".zoomora-media");
1036
- if (!media) return;
1124
+ let newX = this.currentX + deltaX;
1125
+ let newY = this.currentY + deltaY;
1126
+ const container = this.content.getBoundingClientRect();
1037
1127
  const mediaRect = media.getBoundingClientRect();
1038
- const scale = this.currentScale;
1039
- const maxX = mediaRect.width * (scale - 1) / 2;
1040
- const maxY = mediaRect.height * (scale - 1) / 2;
1041
- const constrainedX = Math.max(-maxX, Math.min(maxX, newX));
1042
- const constrainedY = Math.max(-maxY, Math.min(maxY, newY));
1043
- media.style.transform = `scale(${scale}) translate(${constrainedX}px, ${constrainedY}px)`;
1128
+ const overflowX = Math.max(0, (mediaRect.width - container.width) / 2);
1129
+ const overflowY = Math.max(0, (mediaRect.height - container.height) / 2);
1130
+ if (overflowX > 0) {
1131
+ newX = Math.max(-overflowX, Math.min(overflowX, newX));
1132
+ } else {
1133
+ newX = 0;
1134
+ }
1135
+ if (overflowY > 0) {
1136
+ newY = Math.max(-overflowY, Math.min(overflowY, newY));
1137
+ } else {
1138
+ newY = 0;
1139
+ }
1140
+ media.style.transform = `translate(${newX}px, ${newY}px) scale(${this.currentScale})`;
1141
+ this.startX = clientX;
1142
+ this.startY = clientY;
1143
+ this.currentX = newX;
1144
+ this.currentY = newY;
1044
1145
  }
1045
1146
  /**
1046
1147
  * End drag operation
@@ -1048,9 +1149,13 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
1048
1149
  endDrag() {
1049
1150
  if (!this.isDragging) return;
1050
1151
  this.isDragging = false;
1152
+ this.lastDragTime = Date.now();
1051
1153
  const media = this.content.querySelector(".zoomora-media");
1052
- if (media && this.isZoomed) {
1053
- media.style.cursor = "grab";
1154
+ if (media) {
1155
+ media.classList.remove("dragging");
1156
+ if (this.isZoomed) {
1157
+ media.style.cursor = "grab";
1158
+ }
1054
1159
  }
1055
1160
  }
1056
1161
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"zoomora.umd.js","sources":["../src/zoomora.js"],"sourcesContent":["/*!\n * Zoomora Lightbox Plugin v1.0.0\n * A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features\n *\n * Copyright (c) 2025 Faruk Ahmed (FrontTheme)\n * Licensed under MIT License\n */\n\n// Import styles\nimport './styles/zoomora.scss';\n\n(function (global, factory) {\n 'use strict';\n\n if (typeof module === 'object' && typeof module.exports === 'object') {\n // CommonJS/Node.js\n module.exports = factory();\n } else if (typeof define === 'function' && define.amd) {\n // AMD\n define(factory);\n } else {\n // Browser globals\n global.Zoomora = factory();\n }\n}(typeof window !== 'undefined' ? window : this, function () {\n 'use strict';\n\n /**\n * Zoomora Lightbox Plugin\n * @class\n */\n class Zoomora {\n /**\n * Default configuration options\n * @type {Object}\n */\n static get defaults() {\n return {\n selector: '[data-zoomora]',\n showCounter: true,\n showThumbnails: true,\n showFullscreen: true,\n showZoom: true,\n transition: 'fade', // 'fade' or 'slide'\n useHref: false, // Use href instead of data-src\n maxZoomScale: 3, // Maximum zoom scale\n zoomStep: 0.1, // Zoom step for scroll wheel\n animationDuration: 300, // Animation duration in ms\n onOpen: null, // Callback when lightbox opens\n onClose: null, // Callback when lightbox closes\n onNext: null, // Callback when navigating to next item\n onPrev: null, // Callback when navigating to previous item\n\n // Auto-hide controls\n showAutoHideToggle: true, // Show auto-hide toggle button\n autoHideDelay: 3000, // Delay in ms before hiding controls\n autoHideEnabled: false, // Default state of auto-hide\n };\n }\n\n /**\n * Constructor\n * @param {Object} options - Configuration options\n */\n constructor(options = {}) {\n this.options = {...Zoomora.defaults, ...options};\n this.currentIndex = 0;\n this.items = [];\n this.isZoomed = false;\n this.isFullscreen = false;\n this.isDragging = false;\n this.thumbnailsVisible = true;\n this.startX = 0;\n this.startY = 0;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n this.isInitialized = false;\n this.eventListeners = new Map();\n\n // Auto-hide controls\n this.autoHideEnabled = false;\n this.autoHideTimeout = null;\n this.autoHideDelay = 3000;\n this.isControlsVisible = true;\n this.idleTimer = null;\n\n // Bound methods for event listeners\n this.boundMethods = {\n handleDocumentClick: this.handleDocumentClick.bind(this),\n handleKeydown: this.handleKeydown.bind(this),\n handleFullscreenChange: this.handleFullscreenChange.bind(this),\n handleZoomoraClick: this.handleZoomoraClick.bind(this),\n handleContentClick: this.handleContentClick.bind(this),\n handleMouseDown: this.handleMouseDown.bind(this),\n handleMouseMove: this.handleMouseMove.bind(this),\n handleMouseUp: this.handleMouseUp.bind(this),\n handleTouchStart: this.handleTouchStart.bind(this),\n handleTouchMove: this.handleTouchMove.bind(this),\n handleTouchEnd: this.handleTouchEnd.bind(this),\n };\n\n this.init();\n }\n\n /**\n * Initialize the plugin\n */\n init() {\n if (this.isInitialized) {\n console.warn('Zoomora: Plugin already initialized');\n return;\n }\n\n try {\n this.createLightbox();\n this.bindEvents();\n\n this.isInitialized = true;\n } catch (error) {\n console.error('Zoomora: Initialization failed', error);\n }\n }\n\n /**\n * Static method to bind to anchor tags with href\n * @param {string} selector - CSS selector\n * @param {Object} options - Configuration options\n * @returns {Zoomora} - New Zoomora instance\n */\n static bind(selector, options = {}) {\n const enhancedOptions = {\n ...options,\n selector: selector,\n useHref: true\n };\n return new Zoomora(enhancedOptions);\n }\n\n /**\n * Create lightbox HTML structure\n */\n createLightbox() {\n // Check if lightbox already exists\n if (document.getElementById('zoomoraLightbox')) {\n console.warn('Zoomora: Lightbox already exists in DOM');\n return;\n }\n\n const zoomoraHTML = `\n <div class=\"zoomora\" id=\"zoomoraLightbox\">\n <div class=\"zoomora-container\">\n <div class=\"zoomora-header\" id=\"zoomoraHeader\">\n <div class=\"zoomora-counter\" id=\"zoomoraCounter\">1 / 1</div>\n <div class=\"zoomora-controls\">\n <button class=\"zoomora-btn\" id=\"zoomoraThumbnailBtn\" title=\"Toggle Thumbnails\">\n <i class=\"zoomorai-thumbnails\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraAutoHideBtn\" title=\"Toggle Auto-Hide Controls\">\n <i class=\"zoomorai-controls-off\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraZoomBtn\" title=\"Zoom\">\n <i class=\"zoomorai-zoom\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraFullscreenBtn\" title=\"Fullscreen\">\n <i class=\"zoomorai-expand\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraCollapseBtn\" title=\"Exit Fullscreen\" style=\"display: none;\">\n <i class=\"zoomorai-collapse\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraCloseBtn\" title=\"Close\">\n <i class=\"zoomorai-close\"></i>\n </button>\n </div>\n </div>\n \n <div class=\"zoomora-content\" id=\"zoomoraContent\">\n <div class=\"zoomora-loading\" id=\"zoomoraLoading\"></div>\n <div class=\"zoomora-slides-container\" id=\"zoomoraSlidesContainer\"></div>\n </div>\n \n <button class=\"zoomora-nav prev\" id=\"zoomoraPrevBtn\">\n <i class=\"zoomorai-arrow-left\"></i>\n </button>\n <button class=\"zoomora-nav next\" id=\"zoomoraNextBtn\">\n <i class=\"zoomorai-arrow-right\"></i>\n </button>\n \n <div class=\"zoomora-caption\" id=\"zoomoraCaption\"></div>\n <div class=\"zoomora-thumbnails\" id=\"zoomoraThumbs\"></div>\n </div>\n </div>\n `;\n\n document.body.insertAdjacentHTML('beforeend', zoomoraHTML);\n\n // Cache DOM elements\n this.zoomora = document.getElementById('zoomoraLightbox');\n this.header = document.getElementById('zoomoraHeader');\n this.content = document.getElementById('zoomoraContent');\n this.slidesContainer = document.getElementById('zoomoraSlidesContainer');\n this.counter = document.getElementById('zoomoraCounter');\n this.thumbs = document.getElementById('zoomoraThumbs');\n this.loading = document.getElementById('zoomoraLoading');\n this.caption = document.getElementById('zoomoraCaption');\n this.prevBtn = document.getElementById('zoomoraPrevBtn');\n this.nextBtn = document.getElementById('zoomoraNextBtn');\n\n // Verify all elements were created\n if (!this.zoomora || !this.content || !this.counter || !this.thumbs || !this.loading || !this.caption) {\n throw new Error('Failed to create required DOM elements');\n }\n }\n\n /**\n * Bind event listeners\n */\n bindEvents() {\n // Document click handler for opening lightbox\n this.addEventListener(document, 'click', this.boundMethods.handleDocumentClick);\n\n // Control button handlers\n this.addEventListener(document.getElementById('zoomoraCloseBtn'), 'click', () => this.close());\n this.addEventListener(document.getElementById('zoomoraPrevBtn'), 'click', () => this.prev());\n this.addEventListener(document.getElementById('zoomoraNextBtn'), 'click', () => this.next());\n this.addEventListener(document.getElementById('zoomoraZoomBtn'), 'click', () => this.toggleZoom());\n this.addEventListener(document.getElementById('zoomoraFullscreenBtn'), 'click', () => this.toggleFullscreen());\n this.addEventListener(document.getElementById('zoomoraCollapseBtn'), 'click', () => this.exitFullscreen());\n this.addEventListener(document.getElementById('zoomoraThumbnailBtn'), 'click', () => this.toggleThumbnails());\n\n // Fullscreen change events\n this.addEventListener(document, 'fullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'webkitfullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'mozfullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'MSFullscreenChange', this.boundMethods.handleFullscreenChange);\n\n // Keyboard navigation\n this.addEventListener(document, 'keydown', this.boundMethods.handleKeydown);\n\n // Lightbox click to close\n this.addEventListener(this.zoomora, 'click', this.boundMethods.handleZoomoraClick);\n\n // Content click for zoom toggle\n this.addEventListener(this.content, 'click', this.boundMethods.handleContentClick);\n\n // Mouse drag events\n this.addEventListener(this.content, 'mousedown', this.boundMethods.handleMouseDown);\n this.addEventListener(this.content, 'mousemove', this.boundMethods.handleMouseMove);\n this.addEventListener(this.content, 'mouseup', this.boundMethods.handleMouseUp);\n this.addEventListener(this.content, 'mouseleave', this.boundMethods.handleMouseUp);\n\n // Touch events\n this.addEventListener(this.content, 'touchstart', this.boundMethods.handleTouchStart, {passive: false});\n this.addEventListener(this.content, 'touchmove', this.boundMethods.handleTouchMove, {passive: false});\n this.addEventListener(this.content, 'touchend', this.boundMethods.handleTouchEnd);\n\n // Add auto-hide toggle button handler\n this.addEventListener(document.getElementById('zoomoraAutoHideBtn'), 'click', () => this.toggleAutoHide());\n\n // Add mouse/touch activity listeners for auto-hide\n this.addEventListener(this.zoomora, 'mousemove', () => this.handleUserActivity());\n this.addEventListener(this.zoomora, 'touchstart', () => this.handleUserActivity());\n this.addEventListener(this.zoomora, 'keydown', () => this.handleUserActivity());\n }\n\n /**\n * Add event listener with cleanup tracking\n * @param {Element} element - DOM element\n * @param {string} event - Event type\n * @param {Function} handler - Event handler\n * @param {Object} options - Event options\n */\n addEventListener(element, event, handler, options = {}) {\n if (!element) return;\n\n element.addEventListener(event, handler, options);\n\n // Track for cleanup\n const key = `${element.constructor.name}_${event}`;\n if (!this.eventListeners.has(key)) {\n this.eventListeners.set(key, []);\n }\n this.eventListeners.get(key).push({element, event, handler, options});\n }\n\n /**\n * Handle document click events\n * @param {Event} e - Click event\n */\n handleDocumentClick(e) {\n const target = e.target.closest(this.options.selector);\n if (target) {\n e.preventDefault();\n this.open(target);\n }\n }\n\n /**\n * Handle keyboard events\n * @param {KeyboardEvent} e - Keyboard event\n */\n handleKeydown(e) {\n if (!this.zoomora.classList.contains('active')) return;\n\n switch (e.key) {\n case 'Escape':\n if (this.isFullscreen) {\n this.exitFullscreen();\n } else {\n this.close();\n }\n break;\n case 'ArrowLeft':\n this.prev();\n break;\n case 'ArrowRight':\n this.next();\n break;\n case 'z':\n case 'Z':\n this.toggleZoom();\n break;\n case 'f':\n case 'F':\n this.toggleFullscreen();\n break;\n case 't':\n case 'T':\n this.toggleThumbnails();\n break;\n }\n }\n\n /**\n * Handle fullscreen change events\n */\n handleFullscreenChange() {\n const isInFullscreen = document.fullscreenElement ||\n document.webkitFullscreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement;\n\n if (!isInFullscreen && this.isFullscreen) {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }\n }\n\n /**\n * Handle zoomora container clicks\n * @param {Event} e - Click event\n */\n handleZoomoraClick(e) {\n if (e.target === this.zoomora) {\n this.close();\n }\n }\n\n /**\n * Handle content clicks\n * @param {Event} e - Click event\n */\n handleContentClick(e) {\n const media = e.target.closest('.zoomora-media');\n if (media && !media.classList.contains('no-zoom') && !this.isDragging) {\n this.toggleZoom();\n }\n }\n\n /**\n * Handle mouse down events\n * @param {MouseEvent} e - Mouse event\n */\n handleMouseDown(e) {\n this.startDrag(e);\n }\n\n /**\n * Handle mouse move events\n * @param {MouseEvent} e - Mouse event\n */\n handleMouseMove(e) {\n this.drag(e);\n }\n\n /**\n * Handle mouse up events\n */\n handleMouseUp() {\n this.endDrag();\n }\n\n /**\n * Handle touch start events\n * @param {TouchEvent} e - Touch event\n */\n handleTouchStart(e) {\n this.startDrag(e);\n }\n\n /**\n * Handle touch move events\n * @param {TouchEvent} e - Touch event\n */\n handleTouchMove(e) {\n this.drag(e);\n }\n\n /**\n * Handle touch end events\n */\n handleTouchEnd() {\n this.endDrag();\n }\n\n /**\n * Get image source from element\n * @param {Element} item - DOM element\n * @returns {string} - Image source URL\n */\n getImageSource(item) {\n const src = item.dataset.src || item.src || item.getAttribute('src');\n const type = item.dataset.type || 'image';\n\n // Handle YouTube URLs for video types\n if (type === 'video' && src) {\n return this.convertToEmbedUrl(src);\n }\n\n return src;\n }\n\n /**\n * Convert YouTube URLs to embed format\n * @param url\n * @returns {*|string}\n */\n convertToEmbedUrl(url) {\n // If already an embed URL, return as is\n if (url.includes('youtube.com/embed/')) {\n return url;\n }\n\n // Handle different YouTube URL formats\n let videoId = null;\n let startTime = null;\n\n // Extract video ID and start time from different YouTube URL formats\n if (url.includes('youtube.com/watch')) {\n const urlParams = new URLSearchParams(url.split('?')[1]);\n videoId = urlParams.get('v');\n const t = urlParams.get('t');\n if (t) {\n // Convert time format (e.g., \"111s\" to seconds)\n startTime = t.replace('s', '');\n }\n } else if (url.includes('youtu.be/')) {\n const parts = url.split('/');\n const videoAndParams = parts[parts.length - 1];\n if (videoAndParams.includes('?')) {\n videoId = videoAndParams.split('?')[0];\n const urlParams = new URLSearchParams(videoAndParams.split('?')[1]);\n const t = urlParams.get('t');\n if (t) startTime = t.replace('s', '');\n } else {\n videoId = videoAndParams;\n }\n }\n\n if (videoId) {\n let embedUrl = `https://www.youtube.com/embed/${videoId}`;\n const params = new URLSearchParams();\n\n if (startTime) {\n params.append('start', startTime);\n }\n\n // Add other useful parameters\n params.append('rel', '0'); // Don't show related videos\n params.append('modestbranding', '1'); // Modest branding\n\n // Option: Add autoplay for YouTube videos (uncomment if desired)\n // params.append('autoplay', '1');\n\n if (params.toString()) {\n embedUrl += '?' + params.toString();\n }\n\n return embedUrl;\n }\n\n // If not a YouTube URL or couldn't parse, return original\n return url;\n }\n\n /**\n * Get thumbnail source from element\n * @param {Element} item - DOM element\n * @returns {string} - Thumbnail source URL\n */\n getThumbnailSource(item) {\n const type = item.dataset.type || 'image';\n\n // For video items, always use the img.src as thumbnail (poster image)\n if (type === 'video') {\n return item.src || item.getAttribute('src');\n }\n\n // For regular images, use data-src or fallback to src\n return item.dataset.src || item.src || item.getAttribute('src');\n }\n\n /**\n * Get group identifier from element\n * @param {Element} element - DOM element\n * @returns {string} - Group identifier\n */\n getGroup(element) {\n if (this.options.useHref) {\n return element.dataset.lightbox || element.dataset.gallery || 'default';\n }\n return element.dataset.zoomora || 'default';\n }\n\n /**\n * Open lightbox with specified element\n * @param {Element} element - DOM element to open\n */\n open(element) {\n if (!element) return;\n\n const group = this.getGroup(element);\n let groupSelector;\n\n if (this.options.useHref) {\n if (element.dataset.lightbox) {\n groupSelector = `[data-lightbox=\"${group}\"]`;\n } else if (element.dataset.gallery) {\n groupSelector = `[data-gallery=\"${group}\"]`;\n } else {\n groupSelector = this.options.selector;\n }\n } else {\n groupSelector = `[data-zoomora=\"${group}\"]`;\n }\n\n this.items = Array.from(document.querySelectorAll(groupSelector));\n this.currentIndex = Math.max(0, this.items.indexOf(element));\n\n // Reset states\n this.isZoomed = false;\n this.isFullscreen = false;\n this.thumbnailsVisible = true;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n\n this.zoomora.classList.add('active');\n document.body.style.overflow = 'hidden';\n\n this.loadContent();\n this.updateThumbnails();\n this.updateCounter();\n this.updateNavigation();\n this.updateCaption();\n this.updateButtons();\n\n // Initialize auto-hide if enabled\n if (this.autoHideEnabled) {\n this.startAutoHideTimer();\n } else {\n this.showControls();\n }\n\n // Trigger callback\n if (typeof this.options.onOpen === 'function') {\n this.options.onOpen(element, this.currentIndex);\n }\n }\n\n /**\n * Close lightbox\n */\n close() {\n if (this.isFullscreen) {\n this.exitFullscreen();\n }\n\n this.zoomora.classList.remove('active');\n document.body.style.overflow = '';\n this.isZoomed = false;\n this.isFullscreen = false;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n\n const media = this.content.querySelector('.zoomora-media');\n if (media) {\n media.classList.remove('zoomed');\n media.style.transform = '';\n media.style.cursor = '';\n }\n\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n\n // Clean up auto-hide\n this.stopAutoHideTimer();\n this.showControls();\n\n // Trigger callback\n if (typeof this.options.onClose === 'function') {\n this.options.onClose(this.currentIndex);\n }\n }\n\n /**\n * Navigate to previous item\n */\n prev() {\n if (this.currentIndex > 0) {\n this.currentIndex--;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n\n // Trigger callback\n if (typeof this.options.onPrev === 'function') {\n this.options.onPrev(this.currentIndex);\n }\n }\n }\n\n /**\n * Navigate to next item\n */\n next() {\n if (this.currentIndex < this.items.length - 1) {\n this.currentIndex++;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n\n // Trigger callback\n if (typeof this.options.onNext === 'function') {\n this.options.onNext(this.currentIndex);\n }\n }\n }\n\n /**\n * Load content for current item\n */\n loadContent() {\n if (!this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const src = this.getImageSource(item);\n const type = item.dataset.type || 'image';\n\n if (!src) {\n console.error('Zoomora: No source found for item');\n return;\n }\n\n // Show loading spinner\n this.loading.style.display = 'block';\n\n // Clear content but keep the loading reference intact\n // Don't replace innerHTML, just clear the slides\n if (this.slidesContainer) {\n this.slidesContainer.innerHTML = '';\n }\n\n // Add slight delay for smooth transition\n setTimeout(() => {\n this.renderContent(src, type, item);\n }, 100);\n }\n\n /**\n * Render content based on type\n * @param {string} src - Source URL\n * @param {string} type - Content type\n * @param {Element} item - Original item element\n */\n renderContent(src, type, item) {\n const slideContainer = document.createElement('div');\n slideContainer.className = 'zoomora-slide-container';\n\n // Create slide wrapper\n const slide = document.createElement('div');\n slide.className = `zoomora-slide ${this.options.transition === 'slide' ? 'slide-effect' : 'fade-effect'}`;\n slide.style.opacity = '0';\n slide.style.transform = this.options.transition === 'slide' ? 'translateX(100%)' : 'scale(0.8)';\n\n let mediaElement;\n\n try {\n switch (type) {\n case 'video':\n if (src.endsWith('.mp4') || src.endsWith('.webm') || src.endsWith('.ogg')) {\n const videoContainer = document.createElement('div');\n videoContainer.className = 'zoomora-video-container';\n\n mediaElement = document.createElement('video');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-video';\n mediaElement.setAttribute('preload', 'metadata');\n\n const posterSrc = item.src || item.getAttribute('src');\n if (posterSrc) {\n mediaElement.setAttribute('poster', posterSrc);\n }\n\n const playButton = document.createElement('div');\n playButton.className = 'zoomora-play-button';\n playButton.innerHTML = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M8 5v14l11-7z\"/></svg>`;\n\n playButton.addEventListener('click', () => {\n mediaElement.play();\n playButton.style.display = 'none';\n mediaElement.setAttribute('controls', '');\n });\n\n mediaElement.addEventListener('ended', () => {\n playButton.style.display = 'flex';\n });\n\n videoContainer.appendChild(mediaElement);\n videoContainer.appendChild(playButton);\n slideContainer.appendChild(videoContainer);\n } else {\n mediaElement = document.createElement('iframe');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-video';\n mediaElement.setAttribute('allowfullscreen', '');\n mediaElement.setAttribute('frameborder', '0');\n slideContainer.appendChild(mediaElement);\n }\n break;\n\n case 'iframe':\n mediaElement = document.createElement('iframe');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-iframe';\n mediaElement.setAttribute('frameborder', '0');\n slideContainer.appendChild(mediaElement);\n break;\n\n default:\n mediaElement = document.createElement('img');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-media';\n mediaElement.alt = item.alt || item.title || '';\n\n mediaElement.onload = () => {\n this.loading.style.display = 'none';\n this.checkZoomability(mediaElement);\n this.animateSlideIn(slide);\n };\n\n mediaElement.onerror = () => {\n this.loading.style.display = 'none';\n console.error('Zoomora: Failed to load image:', src);\n this.animateSlideIn(slide);\n };\n\n slideContainer.appendChild(mediaElement);\n }\n\n slide.appendChild(slideContainer);\n\n // Clear existing slides and add new one\n this.slidesContainer.innerHTML = '';\n this.slidesContainer.appendChild(slide);\n\n if (type !== 'image') {\n this.loading.style.display = 'none';\n this.animateSlideIn(slide);\n }\n\n } catch (error) {\n console.error('Zoomora: Error rendering content:', error);\n this.loading.style.display = 'none';\n }\n }\n\n // Animation helper\n animateSlideIn(slide) {\n // Force reflow\n slide.offsetHeight;\n\n // Add active class and animate\n slide.classList.add('active');\n\n if (this.options.transition === 'slide') {\n slide.style.transition = `transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`;\n slide.style.transform = 'translateX(0)';\n slide.style.opacity = '1';\n } else {\n slide.style.transition = `transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`;\n slide.style.transform = 'scale(1)';\n slide.style.opacity = '1';\n }\n }\n\n // Toggle auto-hide controls\n toggleAutoHide() {\n this.autoHideEnabled = !this.autoHideEnabled;\n const autoHideBtn = document.getElementById('zoomoraAutoHideBtn');\n\n if (this.autoHideEnabled) {\n autoHideBtn.classList.add('active');\n autoHideBtn.title = 'Disable Auto-Hide Controls';\n this.startAutoHideTimer();\n } else {\n autoHideBtn.classList.remove('active');\n autoHideBtn.title = 'Enable Auto-Hide Controls';\n this.stopAutoHideTimer();\n this.showControls();\n }\n }\n\n // Handle user activity\n handleUserActivity() {\n if (!this.autoHideEnabled) return;\n\n this.showControls();\n this.startAutoHideTimer();\n }\n\n // Start auto-hide timer\n startAutoHideTimer() {\n this.stopAutoHideTimer();\n\n this.autoHideTimeout = setTimeout(() => {\n this.hideControls();\n }, this.options.autoHideDelay);\n }\n\n // Stop auto-hide timer\n stopAutoHideTimer() {\n if (this.autoHideTimeout) {\n clearTimeout(this.autoHideTimeout);\n this.autoHideTimeout = null;\n }\n }\n\n // Show controls\n showControls() {\n if (this.isControlsVisible) return;\n\n this.isControlsVisible = true;\n this.zoomora.classList.remove('controls-hidden');\n\n // Animate controls back in\n if (this.header) {\n this.header.style.transform = 'translateY(0)';\n this.header.style.opacity = '1';\n }\n\n if (this.caption) {\n this.caption.style.transform = 'translateX(-50%) translateY(0)';\n this.caption.style.opacity = '1';\n }\n\n if (this.thumbs) {\n this.thumbs.style.transform = 'translateX(-50%) translateY(0)';\n this.thumbs.style.opacity = '1';\n }\n\n if (this.prevBtn) {\n this.prevBtn.style.transform = 'translateX(0)';\n this.prevBtn.style.opacity = '1';\n }\n\n if (this.nextBtn) {\n this.nextBtn.style.transform = 'translateX(0)';\n this.nextBtn.style.opacity = '1';\n }\n }\n\n // Hide controls\n hideControls() {\n if (!this.isControlsVisible) return;\n\n this.isControlsVisible = false;\n this.zoomora.classList.add('controls-hidden');\n\n // Animate controls out\n if (this.header) {\n this.header.style.transform = 'translateY(-100%)';\n this.header.style.opacity = '0';\n }\n\n if (this.caption) {\n this.caption.style.transform = 'translateX(-50%) translateY(100%)';\n this.caption.style.opacity = '0';\n }\n\n if (this.thumbs) {\n this.thumbs.style.transform = 'translateX(-50%) translateY(100%)';\n this.thumbs.style.opacity = '0';\n }\n\n if (this.prevBtn) {\n this.prevBtn.style.transform = 'translateX(-100%)';\n this.prevBtn.style.opacity = '0';\n }\n\n if (this.nextBtn) {\n this.nextBtn.style.transform = 'translateX(100%)';\n this.nextBtn.style.opacity = '0';\n }\n }\n\n /**\n * Check if image can be zoomed\n * @param {HTMLImageElement} img - Image element\n */\n checkZoomability(img) {\n if (!img || !img.naturalWidth || !img.naturalHeight) return;\n\n const imgRect = img.getBoundingClientRect();\n const renderedWidth = imgRect.width;\n const renderedHeight = imgRect.height;\n const naturalWidth = img.naturalWidth;\n const naturalHeight = img.naturalHeight;\n\n const isScaledDown = naturalWidth > renderedWidth || naturalHeight > renderedHeight;\n const zoomRatioX = naturalWidth / renderedWidth;\n const zoomRatioY = naturalHeight / renderedHeight;\n const maxZoomRatio = Math.max(zoomRatioX, zoomRatioY);\n\n // Store zoom info\n img.dataset.zoomRatio = maxZoomRatio;\n img.dataset.naturalWidth = naturalWidth;\n img.dataset.naturalHeight = naturalHeight;\n img.dataset.renderedWidth = renderedWidth;\n img.dataset.renderedHeight = renderedHeight;\n\n // Enable zoom if significantly scaled down\n if (isScaledDown && maxZoomRatio > 1.1) {\n img.classList.remove('no-zoom');\n } else {\n img.classList.add('no-zoom');\n }\n }\n\n /**\n * Update counter display\n */\n updateCounter() {\n if (this.options.showCounter && this.counter) {\n this.counter.textContent = `${this.currentIndex + 1} / ${this.items.length}`;\n }\n }\n\n /**\n * Update caption display\n */\n updateCaption() {\n if (!this.caption || !this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const caption = item.dataset.caption || item.title || '';\n\n if (caption) {\n this.caption.textContent = caption;\n this.caption.style.transform = 'translateX(-50%) translateY(0)';\n this.caption.style.opacity = '1';\n this.caption.style.pointerEvents = 'auto';\n this.caption.style.transition = 'opacity 0.3s ease, transform 0.3s ease';\n } else {\n this.caption.style.transform = 'translateX(-50%) translateY(100%)';\n this.caption.style.opacity = '0';\n this.caption.style.pointerEvents = 'none';\n this.caption.style.transition = 'opacity 0.3s ease, transform 0.3s ease';\n }\n }\n\n /**\n * Update thumbnails display\n */\n updateThumbnails() {\n if (!this.options.showThumbnails || !this.thumbs) return;\n\n if (this.items.length === 1) {\n this.caption.classList.add('single-item-thumbnail');\n this.thumbs.style.display = 'none';\n return;\n }\n\n this.caption.classList.remove('single-item-thumbnail');\n\n this.thumbs.style.display = 'flex';\n this.thumbs.innerHTML = '';\n\n this.items.forEach((item, index) => {\n const thumb = document.createElement('div');\n thumb.className = 'zoomora-thumb';\n if (index === this.currentIndex) thumb.classList.add('active');\n\n const img = document.createElement('img');\n const thumbSrc = this.getThumbnailSource(item);\n\n if (thumbSrc) {\n img.src = thumbSrc;\n img.alt = item.alt || item.title || '';\n img.onerror = () => {\n thumb.style.display = 'none';\n };\n }\n\n thumb.appendChild(img);\n\n thumb.addEventListener('click', () => {\n this.currentIndex = index;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n });\n\n this.thumbs.appendChild(thumb);\n });\n }\n\n /**\n * Update navigation buttons\n */\n updateNavigation() {\n const prevBtn = document.getElementById('zoomoraPrevBtn');\n const nextBtn = document.getElementById('zoomoraNextBtn');\n\n if (prevBtn) {\n prevBtn.style.display = this.currentIndex > 0 ? 'flex' : 'none';\n }\n if (nextBtn) {\n nextBtn.style.display = this.currentIndex < this.items.length - 1 ? 'flex' : 'none';\n }\n }\n\n /**\n * Update control buttons\n */\n updateButtons() {\n const fullscreenBtn = document.getElementById('zoomoraFullscreenBtn');\n const collapseBtn = document.getElementById('zoomoraCollapseBtn');\n\n if (fullscreenBtn && collapseBtn) {\n if (this.isFullscreen) {\n fullscreenBtn.style.display = 'none';\n collapseBtn.style.display = 'flex';\n } else {\n fullscreenBtn.style.display = 'flex';\n collapseBtn.style.display = 'none';\n }\n }\n }\n\n /**\n * Toggle zoom state\n */\n toggleZoom() {\n const media = this.content.querySelector('.zoomora-media');\n if (!media || media.tagName !== 'IMG' || media.classList.contains('no-zoom')) return;\n\n this.isZoomed = !this.isZoomed;\n media.classList.toggle('zoomed', this.isZoomed);\n\n if (this.isZoomed) {\n const zoomRatio = parseFloat(media.dataset.zoomRatio) || 2;\n let zoomScale = Math.min(zoomRatio, this.options.maxZoomScale);\n\n if (zoomRatio > 2.5) {\n zoomScale = Math.min(zoomRatio * 0.7, 2.5);\n }\n\n media.style.transform = `scale(${zoomScale})`;\n media.style.cursor = 'grab';\n media.dataset.currentZoomScale = zoomScale;\n this.currentScale = zoomScale;\n } else {\n media.style.transform = '';\n media.style.cursor = '';\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n }\n }\n\n /**\n * Toggle fullscreen mode\n */\n toggleFullscreen() {\n if (!this.isFullscreen) {\n this.enterFullscreen();\n } else {\n this.exitFullscreen();\n }\n }\n\n /**\n * Enter fullscreen mode\n */\n enterFullscreen() {\n const element = this.zoomora;\n const requestFullscreen = element.requestFullscreen ||\n element.webkitRequestFullscreen ||\n element.mozRequestFullScreen ||\n element.msRequestFullscreen;\n\n if (requestFullscreen) {\n requestFullscreen.call(element).then(() => {\n this.isFullscreen = true;\n this.zoomora.classList.add('fullscreen');\n this.updateButtons();\n }).catch(err => {\n console.warn('Zoomora: Could not enter fullscreen:', err);\n this.fallbackFullscreen();\n });\n } else {\n this.fallbackFullscreen();\n }\n }\n\n /**\n * Exit fullscreen mode\n */\n exitFullscreen() {\n const isInFullscreen = document.fullscreenElement ||\n document.webkitFullscreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement;\n\n if (isInFullscreen) {\n const exitFullscreen = document.exitFullscreen ||\n document.webkitExitFullscreen ||\n document.mozCancelFullScreen ||\n document.msExitFullscreen;\n\n if (exitFullscreen) {\n exitFullscreen.call(document).then(() => {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }).catch(err => {\n console.warn('Zoomora: Could not exit fullscreen:', err);\n this.fallbackExitFullscreen();\n });\n } else {\n this.fallbackExitFullscreen();\n }\n } else {\n this.fallbackExitFullscreen();\n }\n }\n\n /**\n * Fallback fullscreen using CSS\n */\n fallbackFullscreen() {\n this.isFullscreen = true;\n this.zoomora.classList.add('fullscreen');\n this.updateButtons();\n }\n\n /**\n * Exit CSS fullscreen\n */\n fallbackExitFullscreen() {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }\n\n /**\n * Toggle thumbnails visibility\n */\n toggleThumbnails() {\n if (this.items.length === 1) return;\n\n this.thumbnailsVisible = !this.thumbnailsVisible;\n if (this.thumbs) {\n this.thumbs.classList.toggle('thumbs-hidden', !this.thumbnailsVisible);\n\n if (!this.caption || !this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const caption = item.dataset.caption || item.title || '';\n\n if (caption && this.thumbs.classList.contains('thumbs-hidden')) {\n this.caption.style.bottom = '20px';\n this.caption.style.transition = 'bottom 0.3s ease, transform 0.3s ease';\n } else {\n this.caption.style.bottom = '120px';\n }\n }\n }\n\n /**\n * Start drag operation\n * @param {Event} e - Mouse or touch event\n */\n startDrag(e) {\n const media = this.content.querySelector('.zoomora-media');\n if (!media || !this.isZoomed) return;\n\n this.isDragging = true;\n media.style.cursor = 'grabbing';\n\n this.startX = e.clientX || (e.touches && e.touches[0].clientX) || 0;\n this.startY = e.clientY || (e.touches && e.touches[0].clientY) || 0;\n\n // Parse current transform\n const transform = media.style.transform;\n const scaleMatch = transform.match(/scale\\(([^)]+)\\)/);\n const translateMatch = transform.match(/translate\\(([^,]+),\\s*([^)]+)\\)/);\n\n this.currentScale = scaleMatch ? parseFloat(scaleMatch[1]) : 1;\n this.currentX = translateMatch ? parseFloat(translateMatch[1]) : 0;\n this.currentY = translateMatch ? parseFloat(translateMatch[2]) : 0;\n\n e.preventDefault();\n }\n\n /**\n * Handle drag movement\n * @param {Event} e - Mouse or touch event\n */\n drag(e) {\n if (!this.isDragging) return;\n\n e.preventDefault();\n const clientX = e.clientX || (e.touches && e.touches[0].clientX) || 0;\n const clientY = e.clientY || (e.touches && e.touches[0].clientY) || 0;\n\n const deltaX = clientX - this.startX;\n const deltaY = clientY - this.startY;\n\n const newX = this.currentX + deltaX;\n const newY = this.currentY + deltaY;\n\n const media = this.content.querySelector('.zoomora-media');\n if (!media) return;\n\n const mediaRect = media.getBoundingClientRect();\n const scale = this.currentScale;\n const maxX = (mediaRect.width * (scale - 1)) / 2;\n const maxY = (mediaRect.height * (scale - 1)) / 2;\n\n const constrainedX = Math.max(-maxX, Math.min(maxX, newX));\n const constrainedY = Math.max(-maxY, Math.min(maxY, newY));\n\n media.style.transform = `scale(${scale}) translate(${constrainedX}px, ${constrainedY}px)`;\n }\n\n /**\n * End drag operation\n */\n endDrag() {\n if (!this.isDragging) return;\n\n this.isDragging = false;\n const media = this.content.querySelector('.zoomora-media');\n if (media && this.isZoomed) {\n media.style.cursor = 'grab';\n }\n }\n\n /**\n * Go to specific item by index\n * @param {number} index - Item index\n */\n goTo(index) {\n if (index < 0 || index >= this.items.length) return;\n\n this.currentIndex = index;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n }\n\n /**\n * Get current item index\n * @returns {number} - Current index\n */\n getCurrentIndex() {\n return this.currentIndex;\n }\n\n /**\n * Get total number of items\n * @returns {number} - Total items\n */\n getTotalItems() {\n return this.items.length;\n }\n\n /**\n * Check if lightbox is open\n * @returns {boolean} - True if open\n */\n isOpen() {\n return this.zoomora && this.zoomora.classList.contains('active');\n }\n\n /**\n * Update options\n * @param {Object} newOptions - New options to merge\n */\n updateOptions(newOptions) {\n this.options = {...this.options, ...newOptions};\n }\n\n /**\n * Refresh the lightbox (re-scan for items)\n */\n refresh() {\n if (this.isOpen()) {\n const currentItem = this.items[this.currentIndex];\n if (currentItem) {\n this.open(currentItem);\n }\n }\n }\n\n /**\n * Destroy the lightbox instance\n */\n destroy() {\n if (!this.isInitialized) return;\n\n // Close if open\n if (this.isOpen()) {\n this.close();\n }\n\n // Clean up auto-hide\n this.stopAutoHideTimer();\n\n // Remove all event listeners\n this.eventListeners.forEach((listeners, key) => {\n listeners.forEach(({element, event, handler, options}) => {\n if (element && element.removeEventListener) {\n element.removeEventListener(event, handler, options);\n }\n });\n });\n this.eventListeners.clear();\n\n // Remove DOM elements\n if (this.zoomora && this.zoomora.parentNode) {\n this.zoomora.parentNode.removeChild(this.zoomora);\n }\n\n // Reset properties\n this.isInitialized = false;\n this.items = [];\n this.currentIndex = 0;\n this.zoomora = null;\n this.content = null;\n this.counter = null;\n this.thumbs = null;\n this.loading = null;\n this.caption = null;\n }\n }\n\n // Export the class\n return Zoomora;\n}));"],"names":["this"],"mappings":"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"}
1
+ {"version":3,"file":"zoomora.umd.js","sources":["../src/zoomora.js"],"sourcesContent":["/*!\n * Zoomora Lightbox Plugin v1.1.0\n * A modern, responsive lightbox plugin with zoom, fullscreen, and gallery features\n *\n * Copyright (c) 2025 Faruk Ahmed (FrontTheme)\n * Licensed under MIT License\n */\n\n// Import styles\nimport './styles/zoomora.scss';\n\n(function (global, factory) {\n 'use strict';\n\n if (typeof module === 'object' && typeof module.exports === 'object') {\n // CommonJS/Node.js\n module.exports = factory();\n } else if (typeof define === 'function' && define.amd) {\n // AMD\n define(factory);\n } else {\n // Browser globals\n global.Zoomora = factory();\n }\n}(typeof window !== 'undefined' ? window : this, function () {\n 'use strict';\n\n /**\n * Zoomora Lightbox Plugin\n * @class\n */\n class Zoomora {\n /**\n * Default configuration options\n * @type {Object}\n */\n static get defaults() {\n return {\n selector: '[data-zoomora]',\n showCounter: true,\n showThumbnails: true,\n showFullscreen: true,\n showZoom: true,\n transition: 'fade', // 'fade' or 'slide'\n useHref: false, // Use href instead of data-src\n maxZoomScale: 3, // Maximum zoom scale\n zoomStep: 0.1, // Zoom step for scroll wheel\n animationDuration: 300, // Animation duration in ms\n onOpen: null, // Callback when lightbox opens\n onClose: null, // Callback when lightbox closes\n onNext: null, // Callback when navigating to next item\n onPrev: null, // Callback when navigating to previous item\n\n // Auto-hide controls\n showAutoHideToggle: true, // Show auto-hide toggle button\n autoHideDelay: 3000, // Delay in ms before hiding controls\n autoHideEnabled: false, // Default state of auto-hide\n };\n }\n\n /**\n * Constructor\n * @param {Object} options - Configuration options\n */\n constructor(options = {}) {\n this.options = {...Zoomora.defaults, ...options};\n this.currentIndex = 0;\n this.items = [];\n this.isZoomed = false;\n this.isFullscreen = false;\n this.isDragging = false;\n this.thumbnailsVisible = true;\n this.startX = 0;\n this.startY = 0;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n this.isInitialized = false;\n this.eventListeners = new Map();\n\n // Auto-hide controls\n this.autoHideEnabled = false;\n this.autoHideTimeout = null;\n this.autoHideDelay = 3000;\n this.isControlsVisible = true;\n this.idleTimer = null;\n\n this.lastDragTime = 0;\n\n // Bound methods for event listeners\n this.boundMethods = {\n handleDocumentClick: this.handleDocumentClick.bind(this),\n handleKeydown: this.handleKeydown.bind(this),\n handleFullscreenChange: this.handleFullscreenChange.bind(this),\n handleZoomoraClick: this.handleZoomoraClick.bind(this),\n handleContentClick: this.handleContentClick.bind(this),\n handleMouseDown: this.handleMouseDown.bind(this),\n handleMouseMove: this.handleMouseMove.bind(this),\n handleMouseUp: this.handleMouseUp.bind(this),\n handleTouchStart: this.handleTouchStart.bind(this),\n handleTouchMove: this.handleTouchMove.bind(this),\n handleTouchEnd: this.handleTouchEnd.bind(this),\n };\n\n this.init();\n }\n\n /**\n * Initialize the plugin\n */\n init() {\n if (this.isInitialized) {\n console.warn('Zoomora: Plugin already initialized');\n return;\n }\n\n try {\n this.createLightbox();\n this.bindEvents();\n\n this.isInitialized = true;\n } catch (error) {\n console.error('Zoomora: Initialization failed', error);\n }\n }\n\n /**\n * Static method to bind to anchor tags with href\n * @param {string} selector - CSS selector\n * @param {Object} options - Configuration options\n * @returns {Zoomora} - New Zoomora instance\n */\n static bind(selector, options = {}) {\n const enhancedOptions = {\n ...options,\n selector: selector,\n useHref: true\n };\n return new Zoomora(enhancedOptions);\n }\n\n /**\n * Create lightbox HTML structure\n */\n createLightbox() {\n // Check if lightbox already exists\n if (document.getElementById('zoomoraLightbox')) {\n console.warn('Zoomora: Lightbox already exists in DOM');\n return;\n }\n\n // Build auto-hide button conditionally\n const autoHideButtonHTML = this.options.showAutoHideToggle ? `\n <button class=\"zoomora-btn\" id=\"zoomoraAutoHideBtn\" title=\"Toggle Auto-Hide Controls\">\n <i class=\"zoomorai-controls-off\"></i>\n </button>\n ` : '';\n\n const zoomoraHTML = `\n <div class=\"zoomora\" id=\"zoomoraLightbox\">\n <div class=\"zoomora-container\">\n <div class=\"zoomora-header\" id=\"zoomoraHeader\">\n <div class=\"zoomora-counter\" id=\"zoomoraCounter\">1 / 1</div>\n <div class=\"zoomora-controls\">\n <button class=\"zoomora-btn\" id=\"zoomoraThumbnailBtn\" title=\"Toggle Thumbnails\">\n <i class=\"zoomorai-thumbnails\"></i>\n </button>\n ${autoHideButtonHTML}\n <button class=\"zoomora-btn\" id=\"zoomoraZoomBtn\" title=\"Zoom\">\n <i class=\"zoomorai-zoom\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraFullscreenBtn\" title=\"Fullscreen\">\n <i class=\"zoomorai-expand\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraCollapseBtn\" title=\"Exit Fullscreen\" style=\"display: none;\">\n <i class=\"zoomorai-collapse\"></i>\n </button>\n <button class=\"zoomora-btn\" id=\"zoomoraCloseBtn\" title=\"Close\">\n <i class=\"zoomorai-close\"></i>\n </button>\n </div>\n </div>\n \n <div class=\"zoomora-content\" id=\"zoomoraContent\">\n <div class=\"zoomora-loading\" id=\"zoomoraLoading\"></div>\n <div class=\"zoomora-slides-container\" id=\"zoomoraSlidesContainer\"></div>\n </div>\n \n <button class=\"zoomora-nav prev\" id=\"zoomoraPrevBtn\">\n <i class=\"zoomorai-arrow-left\"></i>\n </button>\n <button class=\"zoomora-nav next\" id=\"zoomoraNextBtn\">\n <i class=\"zoomorai-arrow-right\"></i>\n </button>\n \n <div class=\"zoomora-caption\" id=\"zoomoraCaption\"></div>\n <div class=\"zoomora-thumbnails\" id=\"zoomoraThumbs\"></div>\n </div>\n </div>\n `;\n\n document.body.insertAdjacentHTML('beforeend', zoomoraHTML);\n\n // Cache DOM elements\n this.zoomora = document.getElementById('zoomoraLightbox');\n this.header = document.getElementById('zoomoraHeader');\n this.content = document.getElementById('zoomoraContent');\n this.slidesContainer = document.getElementById('zoomoraSlidesContainer');\n this.counter = document.getElementById('zoomoraCounter');\n this.thumbs = document.getElementById('zoomoraThumbs');\n this.loading = document.getElementById('zoomoraLoading');\n this.caption = document.getElementById('zoomoraCaption');\n this.prevBtn = document.getElementById('zoomoraPrevBtn');\n this.nextBtn = document.getElementById('zoomoraNextBtn');\n\n // Verify all elements were created\n if (!this.zoomora || !this.content || !this.counter || !this.thumbs || !this.loading || !this.caption) {\n throw new Error('Failed to create required DOM elements');\n }\n }\n\n /**\n * Bind event listeners\n */\n bindEvents() {\n // Document click handler for opening lightbox\n this.addEventListener(document, 'click', this.boundMethods.handleDocumentClick);\n\n // Control button handlers\n this.addEventListener(document.getElementById('zoomoraCloseBtn'), 'click', () => this.close());\n this.addEventListener(document.getElementById('zoomoraPrevBtn'), 'click', () => this.prev());\n this.addEventListener(document.getElementById('zoomoraNextBtn'), 'click', () => this.next());\n this.addEventListener(document.getElementById('zoomoraZoomBtn'), 'click', () => this.toggleZoom());\n this.addEventListener(document.getElementById('zoomoraFullscreenBtn'), 'click', () => this.toggleFullscreen());\n this.addEventListener(document.getElementById('zoomoraCollapseBtn'), 'click', () => this.exitFullscreen());\n this.addEventListener(document.getElementById('zoomoraThumbnailBtn'), 'click', () => this.toggleThumbnails());\n\n // Fullscreen change events\n this.addEventListener(document, 'fullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'webkitfullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'mozfullscreenchange', this.boundMethods.handleFullscreenChange);\n this.addEventListener(document, 'MSFullscreenChange', this.boundMethods.handleFullscreenChange);\n\n // Keyboard navigation\n this.addEventListener(document, 'keydown', this.boundMethods.handleKeydown);\n\n // Lightbox click to close\n this.addEventListener(this.zoomora, 'click', this.boundMethods.handleZoomoraClick);\n\n // Content click for zoom toggle\n this.addEventListener(this.content, 'click', this.boundMethods.handleContentClick);\n\n // Mouse drag events\n this.addEventListener(this.content, 'mousedown', this.boundMethods.handleMouseDown);\n this.addEventListener(this.content, 'mousemove', this.boundMethods.handleMouseMove);\n this.addEventListener(this.content, 'mouseup', this.boundMethods.handleMouseUp);\n this.addEventListener(this.content, 'mouseleave', this.boundMethods.handleMouseUp);\n\n // Touch events\n this.addEventListener(this.content, 'touchstart', this.boundMethods.handleTouchStart, {passive: false});\n this.addEventListener(this.content, 'touchmove', this.boundMethods.handleTouchMove, {passive: false});\n this.addEventListener(this.content, 'touchend', this.boundMethods.handleTouchEnd);\n\n // Add auto-hide toggle button handler (only if enabled)\n if (this.options.showAutoHideToggle) {\n this.addEventListener(document.getElementById('zoomoraAutoHideBtn'), 'click', () => this.toggleAutoHide());\n\n // Add mouse/touch activity listeners for auto-hide\n this.addEventListener(this.zoomora, 'mousemove', () => this.handleUserActivity());\n this.addEventListener(this.zoomora, 'touchstart', () => this.handleUserActivity());\n this.addEventListener(this.zoomora, 'keydown', () => this.handleUserActivity());\n }\n }\n\n /**\n * Add event listener with cleanup tracking\n * @param {Element} element - DOM element\n * @param {string} event - Event type\n * @param {Function} handler - Event handler\n * @param {Object} options - Event options\n */\n addEventListener(element, event, handler, options = {}) {\n if (!element) return;\n\n element.addEventListener(event, handler, options);\n\n // Track for cleanup\n const key = `${element.constructor.name}_${event}`;\n if (!this.eventListeners.has(key)) {\n this.eventListeners.set(key, []);\n }\n this.eventListeners.get(key).push({element, event, handler, options});\n }\n\n /**\n * Handle document click events\n * @param {Event} e - Click event\n */\n handleDocumentClick(e) {\n const target = e.target.closest(this.options.selector);\n if (target) {\n e.preventDefault();\n this.open(target);\n }\n }\n\n /**\n * Handle keyboard events\n * @param {KeyboardEvent} e - Keyboard event\n */\n handleKeydown(e) {\n if (!this.zoomora.classList.contains('active')) return;\n\n switch (e.key) {\n case 'Escape':\n if (this.isFullscreen) {\n this.exitFullscreen();\n } else {\n this.close();\n }\n break;\n case 'ArrowLeft':\n this.prev();\n break;\n case 'ArrowRight':\n this.next();\n break;\n case 'z':\n case 'Z':\n this.toggleZoom();\n break;\n case 'f':\n case 'F':\n this.toggleFullscreen();\n break;\n case 't':\n case 'T':\n this.toggleThumbnails();\n break;\n }\n }\n\n /**\n * Handle fullscreen change events\n */\n handleFullscreenChange() {\n const isInFullscreen = document.fullscreenElement ||\n document.webkitFullscreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement;\n\n if (!isInFullscreen && this.isFullscreen) {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }\n }\n\n /**\n * Handle zoomora container clicks\n * @param {Event} e - Click event\n */\n handleZoomoraClick(e) {\n if (e.target === this.zoomora) {\n this.close();\n }\n }\n\n /**\n * Handle content clicks\n * @param {Event} e - Click event\n */\n handleContentClick(e) {\n // Ignore click if we just finished dragging (within 200ms)\n if (Date.now() - this.lastDragTime < 200) {\n return;\n }\n\n const media = e.target.closest('.zoomora-media');\n if (media && !media.classList.contains('no-zoom')) {\n this.toggleZoom();\n }\n }\n\n /**\n * Handle mouse down events\n * @param {MouseEvent} e - Mouse event\n */\n handleMouseDown(e) {\n this.startDrag(e);\n }\n\n /**\n * Handle mouse move events\n * @param {MouseEvent} e - Mouse event\n */\n handleMouseMove(e) {\n this.drag(e);\n }\n\n /**\n * Handle mouse up events\n */\n handleMouseUp() {\n this.endDrag();\n }\n\n /**\n * Handle touch start events\n * @param {TouchEvent} e - Touch event\n */\n handleTouchStart(e) {\n this.startDrag(e);\n }\n\n /**\n * Handle touch move events\n * @param {TouchEvent} e - Touch event\n */\n handleTouchMove(e) {\n this.drag(e);\n }\n\n /**\n * Handle touch end events\n */\n handleTouchEnd() {\n this.endDrag();\n }\n\n /**\n * Get image source from element\n * @param {Element} item - DOM element\n * @returns {string} - Image source URL\n */\n getImageSource(item) {\n const src = item.dataset.src || item.src || item.getAttribute('src');\n const type = item.dataset.type || 'image';\n\n // Handle YouTube URLs for video types\n if (type === 'video' && src) {\n return this.convertToEmbedUrl(src);\n }\n\n return src;\n }\n\n /**\n * Convert YouTube URLs to embed format\n * @param url\n * @returns {*|string}\n */\n convertToEmbedUrl(url) {\n // If already an embed URL, return as is\n if (url.includes('youtube.com/embed/')) {\n return url;\n }\n\n // Handle different YouTube URL formats\n let videoId = null;\n let startTime = null;\n\n // Extract video ID and start time from different YouTube URL formats\n if (url.includes('youtube.com/watch')) {\n const urlParams = new URLSearchParams(url.split('?')[1]);\n videoId = urlParams.get('v');\n const t = urlParams.get('t');\n if (t) {\n // Convert time format (e.g., \"111s\" to seconds)\n startTime = t.replace('s', '');\n }\n } else if (url.includes('youtu.be/')) {\n const parts = url.split('/');\n const videoAndParams = parts[parts.length - 1];\n if (videoAndParams.includes('?')) {\n videoId = videoAndParams.split('?')[0];\n const urlParams = new URLSearchParams(videoAndParams.split('?')[1]);\n const t = urlParams.get('t');\n if (t) startTime = t.replace('s', '');\n } else {\n videoId = videoAndParams;\n }\n }\n\n if (videoId) {\n let embedUrl = `https://www.youtube.com/embed/${videoId}`;\n const params = new URLSearchParams();\n\n if (startTime) {\n params.append('start', startTime);\n }\n\n // Add other useful parameters\n params.append('rel', '0'); // Don't show related videos\n params.append('modestbranding', '1'); // Modest branding\n\n // Option: Add autoplay for YouTube videos (uncomment if desired)\n // params.append('autoplay', '1');\n\n if (params.toString()) {\n embedUrl += '?' + params.toString();\n }\n\n return embedUrl;\n }\n\n // If not a YouTube URL or couldn't parse, return original\n return url;\n }\n\n /**\n * Get thumbnail source from element\n * @param {Element} item - DOM element\n * @returns {string} - Thumbnail source URL\n */\n getThumbnailSource(item) {\n const type = item.dataset.type || 'image';\n\n // For video items, always use the img.src as thumbnail (poster image)\n if (type === 'video') {\n return item.src || item.getAttribute('src');\n }\n\n // For regular images, use data-src or fallback to src\n return item.dataset.src || item.src || item.getAttribute('src');\n }\n\n /**\n * Get group identifier from element\n * @param {Element} element - DOM element\n * @returns {string} - Group identifier\n */\n getGroup(element) {\n if (this.options.useHref) {\n return element.dataset.lightbox || element.dataset.gallery || 'default';\n }\n return element.dataset.zoomora || 'default';\n }\n\n /**\n * Open lightbox with specified element\n * @param {Element} element - DOM element to open\n */\n open(element) {\n if (!element) return;\n\n const group = this.getGroup(element);\n let groupSelector;\n\n if (this.options.useHref) {\n if (element.dataset.lightbox) {\n groupSelector = `[data-lightbox=\"${group}\"]`;\n } else if (element.dataset.gallery) {\n groupSelector = `[data-gallery=\"${group}\"]`;\n } else {\n groupSelector = this.options.selector;\n }\n } else {\n groupSelector = `[data-zoomora=\"${group}\"]`;\n }\n\n this.items = Array.from(document.querySelectorAll(groupSelector));\n this.currentIndex = Math.max(0, this.items.indexOf(element));\n\n // Reset states\n this.isZoomed = false;\n this.isFullscreen = false;\n this.thumbnailsVisible = true;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n\n this.zoomora.classList.add('active');\n document.body.style.overflow = 'hidden';\n\n this.loadContent();\n this.updateThumbnails();\n this.updateCounter();\n this.updateNavigation();\n this.updateCaption();\n this.updateButtons();\n\n // Initialize auto-hide if enabled\n if (this.autoHideEnabled) {\n this.startAutoHideTimer();\n } else {\n this.showControls();\n }\n\n // Trigger callback\n if (typeof this.options.onOpen === 'function') {\n this.options.onOpen(element, this.currentIndex);\n }\n }\n\n /**\n * Close lightbox\n */\n close() {\n if (this.isFullscreen) {\n this.exitFullscreen();\n }\n\n this.zoomora.classList.remove('active');\n document.body.style.overflow = '';\n this.isZoomed = false;\n this.isFullscreen = false;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n\n const media = this.content.querySelector('.zoomora-media');\n if (media) {\n media.classList.remove('zoomed');\n media.style.transform = '';\n media.style.cursor = '';\n }\n\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n\n // Clean up auto-hide\n this.stopAutoHideTimer();\n this.showControls();\n\n // Trigger callback\n if (typeof this.options.onClose === 'function') {\n this.options.onClose(this.currentIndex);\n }\n }\n\n /**\n * Navigate to previous item\n */\n prev() {\n if (this.currentIndex > 0) {\n this.currentIndex--;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n\n // Trigger callback\n if (typeof this.options.onPrev === 'function') {\n this.options.onPrev(this.currentIndex);\n }\n }\n }\n\n /**\n * Navigate to next item\n */\n next() {\n if (this.currentIndex < this.items.length - 1) {\n this.currentIndex++;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n\n // Trigger callback\n if (typeof this.options.onNext === 'function') {\n this.options.onNext(this.currentIndex);\n }\n }\n }\n\n /**\n * Load content for current item\n */\n loadContent() {\n if (!this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const src = this.getImageSource(item);\n const type = item.dataset.type || 'image';\n\n if (!src) {\n console.error('Zoomora: No source found for item');\n return;\n }\n\n // Reset zoom state\n this.isZoomed = false;\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n\n // Show loading spinner\n this.loading.style.display = 'block';\n\n if (this.slidesContainer) {\n this.slidesContainer.innerHTML = '';\n }\n\n setTimeout(() => {\n this.renderContent(src, type, item);\n }, 100);\n }\n\n /**\n * Render content based on type\n * @param {string} src - Source URL\n * @param {string} type - Content type\n * @param {Element} item - Original item element\n */\n renderContent(src, type, item) {\n const slideContainer = document.createElement('div');\n slideContainer.className = 'zoomora-slide-container';\n\n // Create slide wrapper\n const slide = document.createElement('div');\n slide.className = `zoomora-slide ${this.options.transition === 'slide' ? 'slide-effect' : 'fade-effect'}`;\n slide.style.opacity = '0';\n slide.style.transform = this.options.transition === 'slide' ? 'translateX(100%)' : 'scale(0.8)';\n\n let mediaElement;\n\n try {\n switch (type) {\n case 'video':\n if (src.endsWith('.mp4') || src.endsWith('.webm') || src.endsWith('.ogg')) {\n const videoContainer = document.createElement('div');\n videoContainer.className = 'zoomora-video-container';\n\n mediaElement = document.createElement('video');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-video';\n mediaElement.setAttribute('preload', 'metadata');\n\n const posterSrc = item.src || item.getAttribute('src');\n if (posterSrc) {\n mediaElement.setAttribute('poster', posterSrc);\n }\n\n const playButton = document.createElement('div');\n playButton.className = 'zoomora-play-button';\n playButton.innerHTML = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M8 5v14l11-7z\"/></svg>`;\n\n playButton.addEventListener('click', () => {\n mediaElement.play();\n playButton.style.display = 'none';\n mediaElement.setAttribute('controls', '');\n });\n\n mediaElement.addEventListener('ended', () => {\n playButton.style.display = 'flex';\n });\n\n videoContainer.appendChild(mediaElement);\n videoContainer.appendChild(playButton);\n slideContainer.appendChild(videoContainer);\n } else {\n mediaElement = document.createElement('iframe');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-video';\n mediaElement.setAttribute('allowfullscreen', '');\n mediaElement.setAttribute('frameborder', '0');\n slideContainer.appendChild(mediaElement);\n }\n break;\n\n case 'iframe':\n mediaElement = document.createElement('iframe');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-iframe';\n mediaElement.setAttribute('frameborder', '0');\n slideContainer.appendChild(mediaElement);\n break;\n\n default:\n mediaElement = document.createElement('img');\n mediaElement.src = src;\n mediaElement.className = 'zoomora-media';\n mediaElement.alt = item.alt || item.title || '';\n\n mediaElement.onload = () => {\n this.loading.style.display = 'none';\n this.checkZoomability(mediaElement);\n this.animateSlideIn(slide);\n };\n\n mediaElement.onerror = () => {\n this.loading.style.display = 'none';\n console.error('Zoomora: Failed to load image:', src);\n this.animateSlideIn(slide);\n };\n\n slideContainer.appendChild(mediaElement);\n }\n\n slide.appendChild(slideContainer);\n\n // Clear existing slides and add new one\n this.slidesContainer.innerHTML = '';\n this.slidesContainer.appendChild(slide);\n\n if (type !== 'image') {\n this.loading.style.display = 'none';\n this.animateSlideIn(slide);\n }\n\n } catch (error) {\n console.error('Zoomora: Error rendering content:', error);\n this.loading.style.display = 'none';\n }\n }\n\n // Animation helper\n animateSlideIn(slide) {\n // Force reflow\n slide.offsetHeight;\n\n // Add active class and animate\n slide.classList.add('active');\n\n if (this.options.transition === 'slide') {\n slide.style.transition = `transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`;\n slide.style.transform = 'translateX(0)';\n slide.style.opacity = '1';\n } else {\n slide.style.transition = `transform ${this.options.animationDuration}ms ease, opacity ${this.options.animationDuration}ms ease`;\n slide.style.transform = 'scale(1)';\n slide.style.opacity = '1';\n }\n }\n\n // Toggle auto-hide controls\n toggleAutoHide() {\n this.autoHideEnabled = !this.autoHideEnabled;\n const autoHideBtn = document.getElementById('zoomoraAutoHideBtn');\n\n if (this.autoHideEnabled) {\n autoHideBtn.classList.add('active');\n autoHideBtn.title = 'Disable Auto-Hide Controls';\n this.startAutoHideTimer();\n } else {\n autoHideBtn.classList.remove('active');\n autoHideBtn.title = 'Enable Auto-Hide Controls';\n this.stopAutoHideTimer();\n this.showControls();\n }\n }\n\n // Handle user activity\n handleUserActivity() {\n if (!this.autoHideEnabled) return;\n\n this.showControls();\n this.startAutoHideTimer();\n }\n\n // Start auto-hide timer\n startAutoHideTimer() {\n this.stopAutoHideTimer();\n\n this.autoHideTimeout = setTimeout(() => {\n this.hideControls();\n }, this.options.autoHideDelay);\n }\n\n // Stop auto-hide timer\n stopAutoHideTimer() {\n if (this.autoHideTimeout) {\n clearTimeout(this.autoHideTimeout);\n this.autoHideTimeout = null;\n }\n }\n\n // Show controls\n showControls() {\n if (this.isControlsVisible) return;\n\n this.isControlsVisible = true;\n this.zoomora.classList.remove('controls-hidden');\n\n // Animate controls back in\n if (this.header) {\n this.header.style.transform = 'translateY(0)';\n this.header.style.opacity = '1';\n }\n\n if (this.caption) {\n this.caption.style.transform = 'translateX(-50%) translateY(0)';\n this.caption.style.opacity = '1';\n }\n\n if (this.thumbs) {\n this.thumbs.style.transform = 'translateX(-50%) translateY(0)';\n this.thumbs.style.opacity = '1';\n }\n\n if (this.prevBtn) {\n this.prevBtn.style.transform = 'translateX(0)';\n this.prevBtn.style.opacity = '1';\n }\n\n if (this.nextBtn) {\n this.nextBtn.style.transform = 'translateX(0)';\n this.nextBtn.style.opacity = '1';\n }\n }\n\n // Hide controls\n hideControls() {\n if (!this.isControlsVisible) return;\n\n this.isControlsVisible = false;\n this.zoomora.classList.add('controls-hidden');\n\n // Animate controls out\n if (this.header) {\n this.header.style.transform = 'translateY(-100%)';\n this.header.style.opacity = '0';\n }\n\n if (this.caption) {\n this.caption.style.transform = 'translateX(-50%) translateY(100%)';\n this.caption.style.opacity = '0';\n }\n\n if (this.thumbs) {\n this.thumbs.style.transform = 'translateX(-50%) translateY(100%)';\n this.thumbs.style.opacity = '0';\n }\n\n if (this.prevBtn) {\n this.prevBtn.style.transform = 'translateX(-100%)';\n this.prevBtn.style.opacity = '0';\n }\n\n if (this.nextBtn) {\n this.nextBtn.style.transform = 'translateX(100%)';\n this.nextBtn.style.opacity = '0';\n }\n }\n\n /**\n * Check if image can be zoomed\n * @param {HTMLImageElement} img - Image element\n */\n checkZoomability(img) {\n if (!img || !img.naturalWidth || !img.naturalHeight) return;\n\n const imgRect = img.getBoundingClientRect();\n const renderedWidth = imgRect.width;\n const renderedHeight = imgRect.height;\n const naturalWidth = img.naturalWidth;\n const naturalHeight = img.naturalHeight;\n\n const isScaledDown = naturalWidth > renderedWidth || naturalHeight > renderedHeight;\n const zoomRatioX = naturalWidth / renderedWidth;\n const zoomRatioY = naturalHeight / renderedHeight;\n const maxZoomRatio = Math.max(zoomRatioX, zoomRatioY);\n\n // Store zoom info\n img.dataset.zoomRatio = maxZoomRatio;\n img.dataset.naturalWidth = naturalWidth;\n img.dataset.naturalHeight = naturalHeight;\n img.dataset.renderedWidth = renderedWidth;\n img.dataset.renderedHeight = renderedHeight;\n\n // Enable zoom if significantly scaled down\n if (isScaledDown && maxZoomRatio > 1.1) {\n img.classList.remove('no-zoom');\n } else {\n img.classList.add('no-zoom');\n }\n }\n\n /**\n * Calculate zoom levels for an image\n * @param {HTMLImageElement} img - Image element\n * @returns {Object} Zoom configuration\n */\n /**\n * Calculate zoom levels for an image\n * @param {HTMLImageElement} img - Image element\n * @returns {Object} Zoom configuration\n */\n calculateZoomLevels(img) {\n if (!img || !img.naturalWidth || !img.naturalHeight) {\n return {canZoom: false, levels: [], currentLevel: 0};\n }\n\n // Get CONTAINER size (not current displayed image size)\n const container = this.content.getBoundingClientRect();\n const containerWidth = container.width;\n const containerHeight = container.height;\n\n const naturalWidth = img.naturalWidth;\n const naturalHeight = img.naturalHeight;\n\n // Calculate what the ORIGINAL fit-to-screen scale would be\n const scaleToFitWidth = containerWidth / naturalWidth;\n const scaleToFitHeight = containerHeight / naturalHeight;\n const fitScale = Math.min(scaleToFitWidth, scaleToFitHeight);\n\n // If image naturally fits or is smaller than container, can't zoom\n if (fitScale >= 0.95) {\n return {canZoom: false, levels: [], currentLevel: 0};\n }\n\n // Calculate zoom levels based on FIT scale (not current scale)\n const levels = [1]; // Start with fit-to-screen\n\n // Add progressive levels: 1.5x, 2x, 3x\n if (fitScale * 1.5 <= 1) levels.push(1.5);\n if (fitScale * 2 <= 1) levels.push(2);\n if (fitScale * 3 <= 1) levels.push(3);\n\n // Add actual size (100%) as final level\n const actualSizeScale = 1 / fitScale;\n if (actualSizeScale > levels[levels.length - 1]) {\n levels.push(actualSizeScale);\n }\n\n return {\n canZoom: levels.length > 1,\n levels: levels,\n currentLevel: 0,\n baseScale: fitScale,\n naturalWidth: naturalWidth,\n naturalHeight: naturalHeight\n };\n }\n\n /**\n * Update counter display\n */\n updateCounter() {\n if (this.options.showCounter && this.counter) {\n this.counter.textContent = `${this.currentIndex + 1} / ${this.items.length}`;\n }\n }\n\n /**\n * Update caption display\n */\n updateCaption() {\n if (!this.caption || !this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const caption = item.dataset.caption || item.title || '';\n\n if (caption) {\n this.caption.textContent = caption;\n this.caption.style.transform = 'translateX(-50%) translateY(0)';\n this.caption.style.opacity = '1';\n this.caption.style.pointerEvents = 'auto';\n this.caption.style.transition = 'opacity 0.3s ease, transform 0.3s ease';\n } else {\n this.caption.style.transform = 'translateX(-50%) translateY(100%)';\n this.caption.style.opacity = '0';\n this.caption.style.pointerEvents = 'none';\n this.caption.style.transition = 'opacity 0.3s ease, transform 0.3s ease';\n }\n }\n\n /**\n * Update thumbnails display\n */\n updateThumbnails() {\n if (!this.options.showThumbnails || !this.thumbs) return;\n\n if (this.items.length === 1) {\n this.caption.classList.add('single-item-thumbnail');\n this.thumbs.style.display = 'none';\n return;\n }\n\n this.caption.classList.remove('single-item-thumbnail');\n\n this.thumbs.style.display = 'flex';\n this.thumbs.innerHTML = '';\n\n this.items.forEach((item, index) => {\n const thumb = document.createElement('div');\n thumb.className = 'zoomora-thumb';\n if (index === this.currentIndex) thumb.classList.add('active');\n\n const img = document.createElement('img');\n const thumbSrc = this.getThumbnailSource(item);\n\n if (thumbSrc) {\n img.src = thumbSrc;\n img.alt = item.alt || item.title || '';\n img.onerror = () => {\n thumb.style.display = 'none';\n };\n }\n\n thumb.appendChild(img);\n\n thumb.addEventListener('click', () => {\n this.currentIndex = index;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n });\n\n this.thumbs.appendChild(thumb);\n });\n }\n\n /**\n * Update navigation buttons\n */\n updateNavigation() {\n const prevBtn = document.getElementById('zoomoraPrevBtn');\n const nextBtn = document.getElementById('zoomoraNextBtn');\n\n if (prevBtn) {\n prevBtn.style.display = this.currentIndex > 0 ? 'flex' : 'none';\n }\n if (nextBtn) {\n nextBtn.style.display = this.currentIndex < this.items.length - 1 ? 'flex' : 'none';\n }\n }\n\n /**\n * Update control buttons\n */\n updateButtons() {\n const fullscreenBtn = document.getElementById('zoomoraFullscreenBtn');\n const collapseBtn = document.getElementById('zoomoraCollapseBtn');\n\n if (fullscreenBtn && collapseBtn) {\n if (this.isFullscreen) {\n fullscreenBtn.style.display = 'none';\n collapseBtn.style.display = 'flex';\n } else {\n fullscreenBtn.style.display = 'flex';\n collapseBtn.style.display = 'none';\n }\n }\n }\n\n /**\n * Toggle zoom state\n */\n toggleZoom() {\n const media = this.content.querySelector('.zoomora-media');\n if (!media || media.tagName !== 'IMG') return;\n\n // Calculate zoom levels\n const zoomConfig = this.calculateZoomLevels(media);\n\n if (!zoomConfig.canZoom) {\n console.log('Image cannot be zoomed (already at full size or larger)');\n return;\n }\n\n // Get or initialize current zoom level\n if (!media.dataset.zoomLevel) {\n media.dataset.zoomLevel = '0';\n }\n\n let currentLevel = parseInt(media.dataset.zoomLevel) || 0;\n\n // Cycle to next level\n currentLevel++;\n if (currentLevel >= zoomConfig.levels.length) {\n // Reset to fit-to-screen\n currentLevel = 0;\n }\n\n const targetScale = zoomConfig.levels[currentLevel];\n media.dataset.zoomLevel = currentLevel.toString();\n\n if (currentLevel === 0) {\n // Back to fit-to-screen\n this.isZoomed = false;\n this.isDragging = false;\n media.classList.remove('dragging');\n media.style.transform = '';\n media.style.cursor = 'pointer';\n media.classList.remove('zoomed');\n this.currentX = 0;\n this.currentY = 0;\n this.currentScale = 1;\n } else {\n // Zoom in - reset position to center\n this.isZoomed = true;\n this.currentScale = targetScale;\n this.currentX = 0; // Always reset to center on zoom change\n this.currentY = 0;\n\n media.style.transform = `translate(0px, 0px) scale(${targetScale})`;\n media.style.cursor = 'grab';\n media.classList.add('zoomed');\n\n console.log(`Zoomed to level ${currentLevel}/${zoomConfig.levels.length - 1} (${(targetScale * 100).toFixed(0)}%)`);\n }\n }\n\n /**\n * Update image transform based on current state\n * @param {HTMLElement} media - Media element\n */\n updateImageTransform(media) {\n if (!media) return;\n\n if (this.currentScale === 1) {\n media.style.transform = '';\n } else {\n // IMPORTANT: translate in scaled space, so divide by scale\n const translateX = this.currentX / this.currentScale;\n const translateY = this.currentY / this.currentScale;\n media.style.transform = `scale(${this.currentScale}) translate(${translateX}px, ${translateY}px)`;\n }\n }\n\n /**\n * Toggle fullscreen mode\n */\n toggleFullscreen() {\n if (!this.isFullscreen) {\n this.enterFullscreen();\n } else {\n this.exitFullscreen();\n }\n }\n\n /**\n * Enter fullscreen mode\n */\n enterFullscreen() {\n const element = this.zoomora;\n const requestFullscreen = element.requestFullscreen ||\n element.webkitRequestFullscreen ||\n element.mozRequestFullScreen ||\n element.msRequestFullscreen;\n\n if (requestFullscreen) {\n requestFullscreen.call(element).then(() => {\n this.isFullscreen = true;\n this.zoomora.classList.add('fullscreen');\n this.updateButtons();\n }).catch(err => {\n console.warn('Zoomora: Could not enter fullscreen:', err);\n this.fallbackFullscreen();\n });\n } else {\n this.fallbackFullscreen();\n }\n }\n\n /**\n * Exit fullscreen mode\n */\n exitFullscreen() {\n const isInFullscreen = document.fullscreenElement ||\n document.webkitFullscreenElement ||\n document.mozFullScreenElement ||\n document.msFullscreenElement;\n\n if (isInFullscreen) {\n const exitFullscreen = document.exitFullscreen ||\n document.webkitExitFullscreen ||\n document.mozCancelFullScreen ||\n document.msExitFullscreen;\n\n if (exitFullscreen) {\n exitFullscreen.call(document).then(() => {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }).catch(err => {\n console.warn('Zoomora: Could not exit fullscreen:', err);\n this.fallbackExitFullscreen();\n });\n } else {\n this.fallbackExitFullscreen();\n }\n } else {\n this.fallbackExitFullscreen();\n }\n }\n\n /**\n * Fallback fullscreen using CSS\n */\n fallbackFullscreen() {\n this.isFullscreen = true;\n this.zoomora.classList.add('fullscreen');\n this.updateButtons();\n }\n\n /**\n * Exit CSS fullscreen\n */\n fallbackExitFullscreen() {\n this.isFullscreen = false;\n this.zoomora.classList.remove('fullscreen');\n this.updateButtons();\n }\n\n /**\n * Toggle thumbnails visibility\n */\n toggleThumbnails() {\n if (this.items.length === 1) return;\n\n this.thumbnailsVisible = !this.thumbnailsVisible;\n if (this.thumbs) {\n this.thumbs.classList.toggle('thumbs-hidden', !this.thumbnailsVisible);\n\n if (!this.caption || !this.items[this.currentIndex]) return;\n\n const item = this.items[this.currentIndex];\n const caption = item.dataset.caption || item.title || '';\n\n if (caption && this.thumbs.classList.contains('thumbs-hidden')) {\n this.caption.style.bottom = '20px';\n this.caption.style.transition = 'bottom 0.3s ease, transform 0.3s ease';\n } else {\n this.caption.style.bottom = '120px';\n }\n }\n }\n\n /**\n * Start drag operation\n * @param {Event} e - Mouse or touch event\n */\n startDrag(e) {\n const media = this.content.querySelector('.zoomora-media');\n if (!media || !this.isZoomed) return;\n\n this.isDragging = true;\n media.classList.add('dragging');\n media.style.cursor = 'grabbing';\n\n this.startX = e.clientX || (e.touches && e.touches[0].clientX) || 0;\n this.startY = e.clientY || (e.touches && e.touches[0].clientY) || 0;\n\n // Read current position from transform\n const transform = window.getComputedStyle(media).transform;\n if (transform && transform !== 'none') {\n const matrix = new DOMMatrix(transform);\n this.currentX = matrix.m41;\n this.currentY = matrix.m42;\n } else {\n this.currentX = 0;\n this.currentY = 0;\n }\n\n e.preventDefault();\n }\n\n /**\n * Handle drag movement\n * @param {Event} e - Mouse or touch event\n */\n drag(e) {\n if (!this.isDragging) return;\n e.preventDefault();\n\n const media = this.content.querySelector('.zoomora-media');\n if (!media) return;\n\n const clientX = e.clientX || (e.touches && e.touches[0].clientX) || 0;\n const clientY = e.clientY || (e.touches && e.touches[0].clientY) || 0;\n\n const deltaX = clientX - this.startX;\n const deltaY = clientY - this.startY;\n\n let newX = this.currentX + deltaX;\n let newY = this.currentY + deltaY;\n\n // Calculate boundaries for BOTH width AND height\n const container = this.content.getBoundingClientRect();\n const mediaRect = media.getBoundingClientRect();\n\n // How much the scaled image overflows the container\n const overflowX = Math.max(0, (mediaRect.width - container.width) / 2);\n const overflowY = Math.max(0, (mediaRect.height - container.height) / 2);\n\n // Constrain drag to overflow boundaries\n if (overflowX > 0) {\n newX = Math.max(-overflowX, Math.min(overflowX, newX));\n } else {\n newX = 0; // Center horizontally if no overflow\n }\n\n if (overflowY > 0) {\n newY = Math.max(-overflowY, Math.min(overflowY, newY));\n } else {\n newY = 0; // Center vertically if no overflow\n }\n\n // Apply transform\n media.style.transform = `translate(${newX}px, ${newY}px) scale(${this.currentScale})`;\n\n // Update for next frame\n this.startX = clientX;\n this.startY = clientY;\n this.currentX = newX;\n this.currentY = newY;\n }\n\n /**\n * End drag operation\n */\n endDrag() {\n if (!this.isDragging) return;\n\n this.isDragging = false;\n this.lastDragTime = Date.now();\n\n const media = this.content.querySelector('.zoomora-media');\n if (media) {\n media.classList.remove('dragging');\n if (this.isZoomed) {\n media.style.cursor = 'grab';\n }\n }\n }\n\n /**\n * Go to specific item by index\n * @param {number} index - Item index\n */\n goTo(index) {\n if (index < 0 || index >= this.items.length) return;\n\n this.currentIndex = index;\n this.loadContent();\n this.updateCounter();\n this.updateThumbnails();\n this.updateNavigation();\n this.updateCaption();\n }\n\n /**\n * Get current item index\n * @returns {number} - Current index\n */\n getCurrentIndex() {\n return this.currentIndex;\n }\n\n /**\n * Get total number of items\n * @returns {number} - Total items\n */\n getTotalItems() {\n return this.items.length;\n }\n\n /**\n * Check if lightbox is open\n * @returns {boolean} - True if open\n */\n isOpen() {\n return this.zoomora && this.zoomora.classList.contains('active');\n }\n\n /**\n * Update options\n * @param {Object} newOptions - New options to merge\n */\n updateOptions(newOptions) {\n this.options = {...this.options, ...newOptions};\n }\n\n /**\n * Refresh the lightbox (re-scan for items)\n */\n refresh() {\n if (this.isOpen()) {\n const currentItem = this.items[this.currentIndex];\n if (currentItem) {\n this.open(currentItem);\n }\n }\n }\n\n /**\n * Destroy the lightbox instance\n */\n destroy() {\n if (!this.isInitialized) return;\n\n // Close if open\n if (this.isOpen()) {\n this.close();\n }\n\n // Clean up auto-hide\n this.stopAutoHideTimer();\n\n // Remove all event listeners\n this.eventListeners.forEach((listeners, key) => {\n listeners.forEach(({element, event, handler, options}) => {\n if (element && element.removeEventListener) {\n element.removeEventListener(event, handler, options);\n }\n });\n });\n this.eventListeners.clear();\n\n // Remove DOM elements\n if (this.zoomora && this.zoomora.parentNode) {\n this.zoomora.parentNode.removeChild(this.zoomora);\n }\n\n // Reset properties\n this.isInitialized = false;\n this.items = [];\n this.currentIndex = 0;\n this.zoomora = null;\n this.content = null;\n this.counter = null;\n this.thumbs = null;\n this.loading = null;\n this.caption = null;\n }\n }\n\n // Export the class\n return Zoomora;\n}));"],"names":["this"],"mappings":"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"}