diff options
| author | eltrac <hi@eltr.ac> | 2026-02-10 11:49:54 +0800 |
|---|---|---|
| committer | eltrac <hi@eltr.ac> | 2026-02-10 11:49:54 +0800 |
| commit | f0f473184c362520cc12bd9a1cc149d0ced9b19c (patch) | |
| tree | 020598dc3886608283238b9cc7a4db3c4530315f /dist | |
| parent | bf36eb7314302d5d1e104b4e812db8098b08c7d6 (diff) | |
chore(build): build latest version
Diffstat (limited to 'dist')
| -rw-r--r-- | dist/libra.min.js | 2 | ||||
| -rw-r--r-- | dist/libra.min.js.map | 2 |
2 files changed, 2 insertions, 2 deletions
diff --git a/dist/libra.min.js b/dist/libra.min.js index a5dbf7b..720dfcd 100644 --- a/dist/libra.min.js +++ b/dist/libra.min.js @@ -1,2 +1,2 @@ -let t={selector:"[data-libra]",margin:50,offset:{x:0,y:0},transitionDuration:200,imageCursor:"zoom-in"};class e{constructor(){let e=document.createElement("div");return e.id="libra-overlay",e.classList.add("libra-overlay","libra-hidden"),e.style.transitionDuration=t.transitionDuration+"ms",this.element=e,document.body.appendChild(e),this}show(){this.element.classList.remove("libra-hidden"),this.element.classList.add("libra-visible")}hide(){this.element.classList.remove("libra-visible"),this.element.classList.add("libra-hidden")}}class i{static calculateFinalState(e){let i={},s=t.margin,n=e.naturalWidth,o=e.naturalHeight,l=n/o,r=window.innerWidth-2*s,a=window.innerHeight-2*s;return i.width=n>r?r:n,i.height=n>r?r/l:o,i.height>a&&(i.height=a,i.width=a*l),i.top=(a-i.height)/2+window.scrollY+s+t.offset.y,i.left=(r-i.width)/2+window.scrollX+s+t.offset.x,i}static transformMatrix(t,e,i){let s=i.width/e.width,n=i.height/e.height,o=e.left+e.width/2,l=e.top+e.height/2,r=i.left+i.width/2,a=i.top+i.height/2;t.style.transform=`matrix(${s}, 0, 0, ${n}, ${r-o}, ${a-l})`}static resetTransformMatrix(t){t.style.transform="matrix(1, 0, 0, 1, 0, 0)"}}class s{isOpen=!1;constructor(t){return this.original=t,this.fetchOriginalPosition(),this.create(t),this}create(e){let i=document.createElement("img");i.src=e.src,i.id=`libra-shadow-${e.id}`,i.classList.add("libra-shadow"),i.style.transitionDuration=t.transitionDuration+"ms",this.element=i,this.positionShadow(),this.placeItself()}fetchOriginalPosition(){let e=this.original.getBoundingClientRect();this.originalPosition={top:e.top+window.scrollY+t.offset.y,left:e.left+window.scrollX+t.offset.x,width:e.width,height:e.height}}positionShadow(){this.element.style.top=this.originalPosition.top+"px",this.element.style.left=this.originalPosition.left+"px",this.element.style.width=this.originalPosition.width+"px",this.element.style.height=this.originalPosition.height+"px"}open(){this.isOpen=!0,this.element.classList.add("open"),this.fetchOriginalPosition(),this.positionShadow(),this.original.style.visibility="hidden",document.body.contains(this.element)||this.placeItself();let t=()=>i.transformMatrix(this.element,this.originalPosition,i.calculateFinalState(this.element));0===this.element.naturalWidth||0===this.element.naturalHeight?this.element.addEventListener("load",t,{once:!0}):t()}close(){this.isOpen=!1,this.element.classList.remove("open"),i.resetTransformMatrix(this.element),setTimeout(()=>{this.original.style.visibility="visible",this.destroyItself()},t.transitionDuration)}placeItself(){document.body.appendChild(this.element)}destroyItself(){document.body.contains(this.element)&&document.body.removeChild(this.element)}}class n{currentImage=null;shadows={};constructor(e){!function t(e,i){for(let s in i)"object"!=typeof i[s]||null===i[s]||Array.isArray(i[s])?e[s]=i[s]:(e[s]||(e[s]={}),t(e[s],i[s]));return e}(t,e),this.initOverlay(),this.initImages(),this.initControls()}initOverlay(){this.overlay=new e,this.overlay.element.addEventListener("click",()=>{this.closeCurrent()})}initImages(){this.images=document.querySelectorAll(t.selector),this.images.forEach(e=>{"IMG"===e.tagName&&(e.id=crypto.randomUUID(),e.style.cursor=t.imageCursor,e.addEventListener("click",()=>this.open(e)))})}initControls(){document.addEventListener("keydown",t=>{("Escape"===t.key||" "===t.key)&&this.closeCurrent()}),document.body.addEventListener("wheel",t=>this.closeCurrent()),document.body.addEventListener("touchmove",t=>this.closeCurrent())}open(t){this.currentImage=t;let e=this.shadows[t.id]||new s(t);this.shadows[t.id]||(this.shadows[t.id]=e),e.open(),this.overlay.show()}close(t){this.currentImage=null,this.shadows[t.id]&&(this.shadows[t.id].close(),this.overlay.hide())}closeCurrent(){this.currentImage&&this.close(this.currentImage)}}export{n as default}; +let t={selector:"[data-libra]",margin:50,zeroMarginBreakpoint:768,offset:{x:0,y:0},transitionDuration:200,imageCursor:"zoom-in"};class e{constructor(){let e=document.createElement("div");return e.id="libra-overlay",e.classList.add("libra-overlay","libra-hidden"),e.style.transitionDuration=t.transitionDuration+"ms",this.element=e,document.body.appendChild(e),this}show(){this.element.classList.remove("libra-hidden"),this.element.classList.add("libra-visible")}hide(){this.element.classList.remove("libra-visible"),this.element.classList.add("libra-hidden")}}class i{static calculateFinalState(e){let i={},s=t.margin;window.innerWidth<=t.zeroMarginBreakpoint&&(s=0);let n=e.naturalWidth,o=e.naturalHeight,l=n/o,r=window.innerWidth-2*s,a=window.innerHeight-2*s;return i.width=n>r?r:n,i.height=n>r?r/l:o,i.height>a&&(i.height=a,i.width=a*l),i.top=(a-i.height)/2+window.scrollY+s+t.offset.y,i.left=(r-i.width)/2+window.scrollX+s+t.offset.x,i}static transformMatrix(t,e,i){let s=i.width/e.width,n=i.height/e.height,o=e.left+e.width/2,l=e.top+e.height/2,r=i.left+i.width/2,a=i.top+i.height/2;t.style.transform=`matrix(${s}, 0, 0, ${n}, ${r-o}, ${a-l})`}static resetTransformMatrix(t){t.style.transform="matrix(1, 0, 0, 1, 0, 0)"}}class s{isOpen=!1;constructor(t){return this.original=t,this.fetchOriginalPosition(),this.create(t),this}create(e){let i=document.createElement("img");i.src=e.src,i.id=`libra-shadow-${e.id}`,i.classList.add("libra-shadow"),i.style.transitionDuration=t.transitionDuration+"ms",this.element=i,this.positionShadow(),this.placeItself()}fetchOriginalPosition(){let e=this.original.getBoundingClientRect();this.originalPosition={top:e.top+window.scrollY+t.offset.y,left:e.left+window.scrollX+t.offset.x,width:e.width,height:e.height}}positionShadow(){this.element.style.top=this.originalPosition.top+"px",this.element.style.left=this.originalPosition.left+"px",this.element.style.width=this.originalPosition.width+"px",this.element.style.height=this.originalPosition.height+"px"}open(){this.isOpen=!0,this.element.classList.add("open"),this.fetchOriginalPosition(),this.positionShadow(),this.original.style.visibility="hidden",document.body.contains(this.element)||this.placeItself();let t=()=>i.transformMatrix(this.element,this.originalPosition,i.calculateFinalState(this.element));0===this.element.naturalWidth||0===this.element.naturalHeight?this.element.addEventListener("load",t,{once:!0}):t()}close(){this.isOpen=!1,this.element.classList.remove("open"),i.resetTransformMatrix(this.element),setTimeout(()=>{this.original.style.visibility="visible",this.destroyItself()},t.transitionDuration)}placeItself(){document.body.appendChild(this.element)}destroyItself(){document.body.contains(this.element)&&document.body.removeChild(this.element)}}class n{currentImage=null;shadows={};constructor(e){!function t(e,i){for(let s in i)"object"!=typeof i[s]||null===i[s]||Array.isArray(i[s])?e[s]=i[s]:(e[s]||(e[s]={}),t(e[s],i[s]));return e}(t,e),this.initOverlay(),this.initImages(),this.initControls()}initOverlay(){this.overlay=new e,this.overlay.element.addEventListener("click",()=>{this.closeCurrent()})}initImages(){this.images=document.querySelectorAll(t.selector),this.images.forEach(e=>{"IMG"===e.tagName&&(e.id=crypto.randomUUID(),e.style.cursor=t.imageCursor,e.addEventListener("click",()=>this.open(e)))})}initControls(){document.addEventListener("keydown",t=>{("Escape"===t.key||" "===t.key)&&this.closeCurrent()}),document.body.addEventListener("wheel",t=>this.closeCurrent()),document.body.addEventListener("touchmove",t=>this.closeCurrent())}open(t){this.currentImage=t;let e=this.shadows[t.id]||new s(t);this.shadows[t.id]||(this.shadows[t.id]=e),e.open(),this.overlay.show()}close(t){this.currentImage=null,this.shadows[t.id]&&(this.shadows[t.id].close(),this.overlay.hide())}closeCurrent(){this.currentImage&&this.close(this.currentImage)}}export{n as default}; //# sourceMappingURL=libra.min.js.map diff --git a/dist/libra.min.js.map b/dist/libra.min.js.map index 3bb87bb..236ae15 100644 --- a/dist/libra.min.js.map +++ b/dist/libra.min.js.map @@ -1 +1 @@ -{"mappings":"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","sources":["<anon>","src/lightbox.js","src/overlay.js","src/config.js","src/shadow.js","src/animation.js"],"sourcesContent":["const $0c04c0cc2b6985d8$var$config = {\n selector: '[data-libra]',\n margin: 50,\n offset: {\n x: 0,\n y: 0\n },\n transitionDuration: 200,\n imageCursor: 'zoom-in'\n};\nfunction $0c04c0cc2b6985d8$var$deepMerge(target, source) {\n for(const key in source)if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {\n if (!target[key]) target[key] = {};\n $0c04c0cc2b6985d8$var$deepMerge(target[key], source[key]);\n } else target[key] = source[key];\n return target;\n}\nfunction $0c04c0cc2b6985d8$export$940a7873bb071df8(newConfig) {\n $0c04c0cc2b6985d8$var$deepMerge($0c04c0cc2b6985d8$var$config, newConfig);\n}\nvar $0c04c0cc2b6985d8$export$2e2bcd8739ae039 = $0c04c0cc2b6985d8$var$config;\n\n\nclass $e49d13fc7942bae1$export$2e2bcd8739ae039 {\n constructor(){\n const overlay = document.createElement('div');\n overlay.id = 'libra-overlay';\n overlay.classList.add('libra-overlay', 'libra-hidden');\n // Set transition duration from config\n overlay.style.transitionDuration = (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).transitionDuration + 'ms';\n this.element = overlay;\n document.body.appendChild(overlay);\n return this;\n }\n show() {\n this.element.classList.remove('libra-hidden');\n this.element.classList.add('libra-visible');\n }\n hide() {\n this.element.classList.remove('libra-visible');\n this.element.classList.add('libra-hidden');\n }\n}\n\n\n\nclass $6e8e6c64a3263339$export$2e2bcd8739ae039 {\n static calculateFinalState(element) {\n let finals = {};\n const margin = (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).margin;\n const nw = element.naturalWidth;\n const nh = element.naturalHeight;\n const ratio = nw / nh;\n const ww = window.innerWidth - 2 * margin;\n const wh = window.innerHeight - 2 * margin;\n // size image based on width first\n finals.width = nw > ww ? ww : nw;\n finals.height = nw > ww ? ww / ratio : nh;\n // if height is too big, adjust based on height\n if (finals.height > wh) {\n finals.height = wh;\n finals.width = wh * ratio;\n }\n finals.top = (wh - finals.height) / 2 + window.scrollY + margin + (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).offset.y;\n finals.left = (ww - finals.width) / 2 + window.scrollX + margin + (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).offset.x;\n return finals;\n }\n static transformMatrix(element, starts, finals) {\n // Calculate scaling factors based on width and height interpolation\n const scaleX = finals.width / starts.width;\n const scaleY = finals.height / starts.height;\n // Calculate the center of the starting and final positions\n const startCenterX = starts.left + starts.width / 2;\n const startCenterY = starts.top + starts.height / 2;\n const finalCenterX = finals.left + finals.width / 2;\n const finalCenterY = finals.top + finals.height / 2;\n const translateX = finalCenterX - startCenterX;\n const translateY = finalCenterY - startCenterY;\n // Apply the transform with matrix (scale + translate)\n element.style.transform = `matrix(${scaleX}, 0, 0, ${scaleY}, ${translateX}, ${translateY})`;\n }\n static resetTransformMatrix(element) {\n element.style.transform = `matrix(1, 0, 0, 1, 0, 0)`;\n }\n}\n\n\n\nclass $2f427fc7e1c3703f$export$2e2bcd8739ae039 {\n isOpen = false;\n /**\n * ============\n * Constructors\n * ============\n */ constructor(image){\n this.original = image;\n this.fetchOriginalPosition();\n this.create(image);\n return this;\n }\n create(image) {\n // create shadow image\n const shadow = document.createElement('img');\n shadow.src = image.src;\n shadow.id = `libra-shadow-${image.id}`;\n shadow.classList.add('libra-shadow');\n shadow.style.transitionDuration = (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).transitionDuration + 'ms';\n this.element = shadow;\n // set positioning and place shadow element\n this.positionShadow();\n this.placeItself();\n }\n fetchOriginalPosition() {\n const rect = this.original.getBoundingClientRect();\n this.originalPosition = {\n top: rect.top + window.scrollY + (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).offset.y,\n left: rect.left + window.scrollX + (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).offset.x,\n width: rect.width,\n height: rect.height\n };\n }\n positionShadow() {\n this.element.style.top = this.originalPosition.top + 'px';\n this.element.style.left = this.originalPosition.left + 'px';\n this.element.style.width = this.originalPosition.width + 'px';\n this.element.style.height = this.originalPosition.height + 'px';\n }\n /**\n * ============\n * Actions\n * ============\n */ open() {\n this.isOpen = true;\n this.element.classList.add('open');\n // Update original position before animation in case viewport changed\n this.fetchOriginalPosition();\n this.positionShadow();\n this.original.style.visibility = 'hidden';\n if (!document.body.contains(this.element)) this.placeItself();\n // play animation\n const animate = ()=>(0, $6e8e6c64a3263339$export$2e2bcd8739ae039).transformMatrix(this.element, this.originalPosition, (0, $6e8e6c64a3263339$export$2e2bcd8739ae039).calculateFinalState(this.element));\n if (this.element.naturalWidth === 0 || this.element.naturalHeight === 0) // Wait for image to load before animating\n this.element.addEventListener('load', animate, {\n once: true\n });\n else // animate directly if loaded\n animate();\n }\n close() {\n this.isOpen = false;\n this.element.classList.remove('open');\n (0, $6e8e6c64a3263339$export$2e2bcd8739ae039).resetTransformMatrix(this.element);\n // Wait for animation to complete before showing original and destroying shadow\n setTimeout(()=>{\n this.original.style.visibility = 'visible';\n this.destroyItself();\n }, (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).transitionDuration);\n }\n placeItself() {\n document.body.appendChild(this.element);\n }\n destroyItself() {\n if (!document.body.contains(this.element)) return;\n document.body.removeChild(this.element);\n }\n}\n\n\n\nclass $e220af4964903f87$export$2e2bcd8739ae039 {\n currentImage = null;\n shadows = {};\n /**\n * ============\n * Initializers\n * ============\n */ constructor(config){\n (0, $0c04c0cc2b6985d8$export$940a7873bb071df8)(config);\n this.initOverlay();\n this.initImages();\n this.initControls();\n }\n initOverlay() {\n this.overlay = new (0, $e49d13fc7942bae1$export$2e2bcd8739ae039)();\n this.overlay.element.addEventListener('click', ()=>{\n this.closeCurrent();\n });\n }\n initImages() {\n this.images = document.querySelectorAll((0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).selector);\n this.images.forEach((image)=>{\n if (image.tagName !== 'IMG') return;\n image.id = crypto.randomUUID(); // generate unique id for each image\n image.style.cursor = (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).imageCursor;\n image.addEventListener('click', ()=>this.open(image)); // click image to open lightbox\n });\n }\n initControls() {\n // keyboard shortcuts\n document.addEventListener('keydown', (e)=>{\n if (e.key === 'Escape' || e.key === ' ') this.closeCurrent();\n });\n // scroll to dismiss\n document.body.addEventListener('wheel', (e)=>this.closeCurrent());\n document.body.addEventListener('touchmove', (e)=>this.closeCurrent());\n }\n /**\n * ============\n * Actions\n * ============\n */ // open lightbox = open shadow + show overlay\n open(image) {\n this.currentImage = image;\n const shadow = this.shadows[image.id] || new (0, $2f427fc7e1c3703f$export$2e2bcd8739ae039)(image);\n if (!this.shadows[image.id]) this.shadows[image.id] = shadow;\n shadow.open();\n this.overlay.show();\n }\n // close lightbox = remove shadow + hide overlay\n close(image) {\n this.currentImage = null;\n if (!this.shadows[image.id]) return;\n this.shadows[image.id].close();\n this.overlay.hide();\n }\n closeCurrent() {\n if (!this.currentImage) return;\n this.close(this.currentImage);\n }\n}\n\n\nexport {$e220af4964903f87$export$2e2bcd8739ae039 as default};\n//# sourceMappingURL=libra.min.js.map\n","import Overlay from './overlay';\nimport Shadow from './shadow';\nimport config from './config';\nimport { setConfig } from './config';\n\nexport default class LightBox {\n currentImage = null;\n shadows = {};\n\n /**\n * ============\n * Initializers\n * ============\n */\n\n constructor(config) {\n setConfig(config);\n\n this.initOverlay();\n this.initImages();\n this.initControls();\n }\n\n initOverlay() {\n this.overlay = new Overlay();\n this.overlay.element.addEventListener('click', () => {\n this.closeCurrent();\n });\n }\n\n initImages() {\n this.images = document.querySelectorAll(config.selector);\n this.images.forEach(image => {\n if (image.tagName !== 'IMG') return;\n image.id = crypto.randomUUID(); // generate unique id for each image\n image.style.cursor = config.imageCursor;\n image.addEventListener('click', () => this.open(image)); // click image to open lightbox\n });\n }\n\n initControls() {\n // keyboard shortcuts\n document.addEventListener('keydown', e => {\n if (e.key === 'Escape' || e.key === ' ')\n this.closeCurrent();\n });\n // scroll to dismiss\n document.body.addEventListener('wheel', e => this.closeCurrent());\n document.body.addEventListener('touchmove', e => this.closeCurrent());\n }\n\n /**\n * ============\n * Actions\n * ============\n */\n\n // open lightbox = open shadow + show overlay\n open(image) {\n this.currentImage = image;\n\n const shadow = this.shadows[image.id] || new Shadow(image);\n if (!this.shadows[image.id]) {\n this.shadows[image.id] = shadow;\n }\n\n shadow.open();\n this.overlay.show();\n }\n\n // close lightbox = remove shadow + hide overlay\n close(image) {\n this.currentImage = null;\n\n if (!this.shadows[image.id]) return;\n this.shadows[image.id].close();\n\n this.overlay.hide();\n }\n\n closeCurrent() {\n if (!this.currentImage) return;\n this.close(this.currentImage);\n }\n}\n","import config from './config';\n\nexport default class Overlay {\n constructor() {\n const overlay = document.createElement('div');\n overlay.id = 'libra-overlay';\n overlay.classList.add('libra-overlay', 'libra-hidden');\n\n // Set transition duration from config\n overlay.style.transitionDuration = config.transitionDuration + 'ms';\n\n this.element = overlay;\n document.body.appendChild(overlay);\n\n return this;\n }\n\n show() {\n this.element.classList.remove('libra-hidden');\n this.element.classList.add('libra-visible');\n }\n\n hide() {\n this.element.classList.remove('libra-visible');\n this.element.classList.add('libra-hidden');\n }\n}\n","const config = {\n selector: '[data-libra]',\n margin: 50,\n offset: { x: 0, y: 0 },\n transitionDuration: 200, // milliseconds\n imageCursor: 'zoom-in',\n};\n\nfunction deepMerge(target, source) {\n for (const key in source) {\n if (\n typeof source[key] === 'object' &&\n source[key] !== null &&\n !Array.isArray(source[key])\n ) {\n if (!target[key]) target[key] = {};\n deepMerge(target[key], source[key]);\n } else {\n target[key] = source[key];\n }\n }\n return target;\n}\n\nexport function setConfig(newConfig) {\n deepMerge(config, newConfig);\n}\n\nexport default config;\n","import Animation from './animation.js'\nimport config from './config'\n\nexport default class Shadow {\n isOpen = false;\n\n /**\n * ============\n * Constructors\n * ============\n */\n\n constructor(image) {\n this.original = image;\n this.fetchOriginalPosition();\n this.create(image);\n\n return this;\n }\n\n create(image) {\n // create shadow image\n const shadow = document.createElement('img');\n shadow.src = image.src;\n shadow.id = `libra-shadow-${image.id}`;\n shadow.classList.add('libra-shadow');\n shadow.style.transitionDuration = config.transitionDuration + 'ms';\n\n this.element = shadow;\n\n // set positioning and place shadow element\n this.positionShadow();\n this.placeItself();\n }\n\n fetchOriginalPosition() {\n const rect = this.original.getBoundingClientRect();\n this.originalPosition = {\n top: rect.top + window.scrollY + config.offset.y,\n left: rect.left + window.scrollX + config.offset.x,\n width: rect.width,\n height: rect.height,\n };\n }\n\n positionShadow() {\n this.element.style.top = this.originalPosition.top + 'px';\n this.element.style.left = this.originalPosition.left + 'px';\n this.element.style.width = this.originalPosition.width + 'px';\n this.element.style.height = this.originalPosition.height + 'px';\n }\n\n /**\n * ============\n * Actions\n * ============\n */\n\n open() {\n this.isOpen = true;\n this.element.classList.add('open');\n\n // Update original position before animation in case viewport changed\n this.fetchOriginalPosition();\n this.positionShadow();\n\n this.original.style.visibility = 'hidden';\n if (!document.body.contains(this.element)) this.placeItself();\n\n // play animation\n const animate = () =>\n Animation.transformMatrix(\n this.element,\n this.originalPosition,\n Animation.calculateFinalState(this.element),\n );\n\n if (this.element.naturalWidth === 0 || this.element.naturalHeight === 0) {\n // Wait for image to load before animating\n this.element.addEventListener('load', animate, { once: true });\n } else {\n // animate directly if loaded\n animate();\n }\n }\n\n close() {\n this.isOpen = false;\n this.element.classList.remove('open');\n\n Animation.resetTransformMatrix(this.element);\n // Wait for animation to complete before showing original and destroying shadow\n setTimeout(() => {\n this.original.style.visibility = 'visible';\n this.destroyItself();\n }, config.transitionDuration);\n }\n\n placeItself() {\n document.body.appendChild(this.element);\n }\n\n destroyItself() {\n if (!document.body.contains(this.element)) return;\n document.body.removeChild(this.element);\n }\n}\n","import config from './config';\n\nexport default class Animation {\n static calculateFinalState(element) {\n let finals = {}\n\n const margin = config.margin;\n const nw = element.naturalWidth;\n const nh = element.naturalHeight;\n const ratio = nw / nh;\n const ww = window.innerWidth - 2*margin;\n const wh = window.innerHeight - 2*margin;\n\n // size image based on width first\n finals.width = (nw > ww) ? ww : nw;\n finals.height = (nw > ww) ? ww / ratio : nh;\n\n // if height is too big, adjust based on height\n if (finals.height > wh) {\n finals.height = wh;\n finals.width = wh * ratio;\n }\n\n finals.top = (wh - finals.height) / 2 + window.scrollY + margin + config.offset.y;\n finals.left = (ww - finals.width) / 2 + window.scrollX + margin + config.offset.x;\n\n return finals;\n }\n\n static transformMatrix(element, starts, finals) {\n // Calculate scaling factors based on width and height interpolation\n const scaleX = finals.width / starts.width;\n const scaleY = finals.height / starts.height;\n\n // Calculate the center of the starting and final positions\n const startCenterX = starts.left + starts.width / 2;\n const startCenterY = starts.top + starts.height / 2;\n const finalCenterX = finals.left + finals.width / 2;\n const finalCenterY = finals.top + finals.height / 2;\n\n const translateX = finalCenterX - startCenterX;\n const translateY = finalCenterY - startCenterY;\n\n // Apply the transform with matrix (scale + translate)\n element.style.transform = `matrix(${scaleX}, 0, 0, ${scaleY}, ${translateX}, ${translateY})`;\n }\n\n static resetTransformMatrix(element) {\n element.style.transform = `matrix(1, 0, 0, 1, 0, 0)`;\n }\n}\n"],"names":["$0c04c0cc2b6985d8$var$config","selector","margin","offset","x","y","transitionDuration","imageCursor","$e49d13fc7942bae1$export$2e2bcd8739ae039","overlay","document","createElement","id","classList","add","style","element","body","appendChild","show","remove","hide","$6e8e6c64a3263339$export$2e2bcd8739ae039","calculateFinalState","finals","nw","naturalWidth","nh","naturalHeight","ratio","ww","window","innerWidth","wh","innerHeight","width","height","top","scrollY","left","scrollX","transformMatrix","starts","scaleX","scaleY","startCenterX","startCenterY","finalCenterX","finalCenterY","transform","resetTransformMatrix","$2f427fc7e1c3703f$export$2e2bcd8739ae039","isOpen","image","original","fetchOriginalPosition","create","shadow","src","positionShadow","placeItself","rect","getBoundingClientRect","originalPosition","open","visibility","contains","animate","addEventListener","once","close","setTimeout","destroyItself","removeChild","$e220af4964903f87$export$2e2bcd8739ae039","currentImage","shadows","config","$0c04c0cc2b6985d8$var$deepMerge","target","source","key","Array","isArray","initOverlay","initImages","initControls","closeCurrent","images","querySelectorAll","forEach","tagName","crypto","randomUUID","cursor","e","default"],"version":3,"file":"libra.min.js.map"}
\ No newline at end of file +{"mappings":"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","sources":["<anon>","src/lightbox.js","src/overlay.js","src/config.js","src/shadow.js","src/animation.js"],"sourcesContent":["const $0c04c0cc2b6985d8$var$config = {\n // selects images that load libra.js\n selector: '[data-libra]',\n // margin between viewport and zoomed image\n // in px\n margin: 50,\n // in small screens, it's best to not use margins\n // otherwise, the zoomed image gets even smaller\n // define on screen smaller than what size, margin is set to 0\n zeroMarginBreakpoint: 768,\n // shifts the zoomed image if needed\n offset: {\n x: 0,\n y: 0\n },\n transitionDuration: 200,\n imageCursor: 'zoom-in'\n};\nfunction $0c04c0cc2b6985d8$var$deepMerge(target, source) {\n for(const key in source)if (typeof source[key] === 'object' && source[key] !== null && !Array.isArray(source[key])) {\n if (!target[key]) target[key] = {};\n $0c04c0cc2b6985d8$var$deepMerge(target[key], source[key]);\n } else target[key] = source[key];\n return target;\n}\nfunction $0c04c0cc2b6985d8$export$940a7873bb071df8(newConfig) {\n $0c04c0cc2b6985d8$var$deepMerge($0c04c0cc2b6985d8$var$config, newConfig);\n}\nvar $0c04c0cc2b6985d8$export$2e2bcd8739ae039 = $0c04c0cc2b6985d8$var$config;\n\n\nclass $e49d13fc7942bae1$export$2e2bcd8739ae039 {\n constructor(){\n const overlay = document.createElement('div');\n overlay.id = 'libra-overlay';\n overlay.classList.add('libra-overlay', 'libra-hidden');\n // Set transition duration from config\n overlay.style.transitionDuration = (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).transitionDuration + 'ms';\n this.element = overlay;\n document.body.appendChild(overlay);\n return this;\n }\n show() {\n this.element.classList.remove('libra-hidden');\n this.element.classList.add('libra-visible');\n }\n hide() {\n this.element.classList.remove('libra-visible');\n this.element.classList.add('libra-hidden');\n }\n}\n\n\n\nclass $6e8e6c64a3263339$export$2e2bcd8739ae039 {\n static calculateFinalState(element) {\n let finals = {};\n let margin = (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).margin;\n if (window.innerWidth <= (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).zeroMarginBreakpoint) margin = 0;\n const nw = element.naturalWidth;\n const nh = element.naturalHeight;\n const ratio = nw / nh;\n const ww = window.innerWidth - 2 * margin;\n const wh = window.innerHeight - 2 * margin;\n // size image based on width first\n finals.width = nw > ww ? ww : nw;\n finals.height = nw > ww ? ww / ratio : nh;\n // if height is too big, adjust based on height\n if (finals.height > wh) {\n finals.height = wh;\n finals.width = wh * ratio;\n }\n finals.top = (wh - finals.height) / 2 + window.scrollY + margin + (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).offset.y;\n finals.left = (ww - finals.width) / 2 + window.scrollX + margin + (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).offset.x;\n return finals;\n }\n static transformMatrix(element, starts, finals) {\n // Calculate scaling factors based on width and height interpolation\n const scaleX = finals.width / starts.width;\n const scaleY = finals.height / starts.height;\n // Calculate the center of the starting and final positions\n const startCenterX = starts.left + starts.width / 2;\n const startCenterY = starts.top + starts.height / 2;\n const finalCenterX = finals.left + finals.width / 2;\n const finalCenterY = finals.top + finals.height / 2;\n const translateX = finalCenterX - startCenterX;\n const translateY = finalCenterY - startCenterY;\n // Apply the transform with matrix (scale + translate)\n element.style.transform = `matrix(${scaleX}, 0, 0, ${scaleY}, ${translateX}, ${translateY})`;\n }\n static resetTransformMatrix(element) {\n element.style.transform = `matrix(1, 0, 0, 1, 0, 0)`;\n }\n}\n\n\n\nclass $2f427fc7e1c3703f$export$2e2bcd8739ae039 {\n isOpen = false;\n /**\n * ============\n * Constructors\n * ============\n */ constructor(image){\n this.original = image;\n this.fetchOriginalPosition();\n this.create(image);\n return this;\n }\n create(image) {\n // create shadow image\n const shadow = document.createElement('img');\n shadow.src = image.src;\n shadow.id = `libra-shadow-${image.id}`;\n shadow.classList.add('libra-shadow');\n shadow.style.transitionDuration = (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).transitionDuration + 'ms';\n this.element = shadow;\n // set positioning and place shadow element\n this.positionShadow();\n this.placeItself();\n }\n fetchOriginalPosition() {\n const rect = this.original.getBoundingClientRect();\n this.originalPosition = {\n top: rect.top + window.scrollY + (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).offset.y,\n left: rect.left + window.scrollX + (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).offset.x,\n width: rect.width,\n height: rect.height\n };\n }\n positionShadow() {\n this.element.style.top = this.originalPosition.top + 'px';\n this.element.style.left = this.originalPosition.left + 'px';\n this.element.style.width = this.originalPosition.width + 'px';\n this.element.style.height = this.originalPosition.height + 'px';\n }\n /**\n * ============\n * Actions\n * ============\n */ open() {\n this.isOpen = true;\n this.element.classList.add('open');\n // Update original position before animation in case viewport changed\n this.fetchOriginalPosition();\n this.positionShadow();\n this.original.style.visibility = 'hidden';\n if (!document.body.contains(this.element)) this.placeItself();\n // play animation\n const animate = ()=>(0, $6e8e6c64a3263339$export$2e2bcd8739ae039).transformMatrix(this.element, this.originalPosition, (0, $6e8e6c64a3263339$export$2e2bcd8739ae039).calculateFinalState(this.element));\n if (this.element.naturalWidth === 0 || this.element.naturalHeight === 0) // Wait for image to load before animating\n this.element.addEventListener('load', animate, {\n once: true\n });\n else // animate directly if loaded\n animate();\n }\n close() {\n this.isOpen = false;\n this.element.classList.remove('open');\n (0, $6e8e6c64a3263339$export$2e2bcd8739ae039).resetTransformMatrix(this.element);\n // Wait for animation to complete before showing original and destroying shadow\n setTimeout(()=>{\n this.original.style.visibility = 'visible';\n this.destroyItself();\n }, (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).transitionDuration);\n }\n placeItself() {\n document.body.appendChild(this.element);\n }\n destroyItself() {\n if (!document.body.contains(this.element)) return;\n document.body.removeChild(this.element);\n }\n}\n\n\n\nclass $e220af4964903f87$export$2e2bcd8739ae039 {\n currentImage = null;\n shadows = {};\n /**\n * ============\n * Initializers\n * ============\n */ constructor(config){\n (0, $0c04c0cc2b6985d8$export$940a7873bb071df8)(config);\n this.initOverlay();\n this.initImages();\n this.initControls();\n }\n initOverlay() {\n this.overlay = new (0, $e49d13fc7942bae1$export$2e2bcd8739ae039)();\n this.overlay.element.addEventListener('click', ()=>{\n this.closeCurrent();\n });\n }\n initImages() {\n this.images = document.querySelectorAll((0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).selector);\n this.images.forEach((image)=>{\n if (image.tagName !== 'IMG') return;\n image.id = crypto.randomUUID(); // generate unique id for each image\n image.style.cursor = (0, $0c04c0cc2b6985d8$export$2e2bcd8739ae039).imageCursor;\n image.addEventListener('click', ()=>this.open(image)); // click image to open lightbox\n });\n }\n initControls() {\n // keyboard shortcuts\n document.addEventListener('keydown', (e)=>{\n if (e.key === 'Escape' || e.key === ' ') this.closeCurrent();\n });\n // scroll to dismiss\n document.body.addEventListener('wheel', (e)=>this.closeCurrent());\n document.body.addEventListener('touchmove', (e)=>this.closeCurrent());\n }\n /**\n * ============\n * Actions\n * ============\n */ // open lightbox = open shadow + show overlay\n open(image) {\n this.currentImage = image;\n const shadow = this.shadows[image.id] || new (0, $2f427fc7e1c3703f$export$2e2bcd8739ae039)(image);\n if (!this.shadows[image.id]) this.shadows[image.id] = shadow;\n shadow.open();\n this.overlay.show();\n }\n // close lightbox = remove shadow + hide overlay\n close(image) {\n this.currentImage = null;\n if (!this.shadows[image.id]) return;\n this.shadows[image.id].close();\n this.overlay.hide();\n }\n closeCurrent() {\n if (!this.currentImage) return;\n this.close(this.currentImage);\n }\n}\n\n\nexport {$e220af4964903f87$export$2e2bcd8739ae039 as default};\n//# sourceMappingURL=libra.min.js.map\n","import Overlay from './overlay';\nimport Shadow from './shadow';\nimport config from './config';\nimport { setConfig } from './config';\n\nexport default class LightBox {\n currentImage = null;\n shadows = {};\n\n /**\n * ============\n * Initializers\n * ============\n */\n\n constructor(config) {\n setConfig(config);\n\n this.initOverlay();\n this.initImages();\n this.initControls();\n }\n\n initOverlay() {\n this.overlay = new Overlay();\n this.overlay.element.addEventListener('click', () => {\n this.closeCurrent();\n });\n }\n\n initImages() {\n this.images = document.querySelectorAll(config.selector);\n this.images.forEach(image => {\n if (image.tagName !== 'IMG') return;\n image.id = crypto.randomUUID(); // generate unique id for each image\n image.style.cursor = config.imageCursor;\n image.addEventListener('click', () => this.open(image)); // click image to open lightbox\n });\n }\n\n initControls() {\n // keyboard shortcuts\n document.addEventListener('keydown', e => {\n if (e.key === 'Escape' || e.key === ' ')\n this.closeCurrent();\n });\n // scroll to dismiss\n document.body.addEventListener('wheel', e => this.closeCurrent());\n document.body.addEventListener('touchmove', e => this.closeCurrent());\n }\n\n /**\n * ============\n * Actions\n * ============\n */\n\n // open lightbox = open shadow + show overlay\n open(image) {\n this.currentImage = image;\n\n const shadow = this.shadows[image.id] || new Shadow(image);\n if (!this.shadows[image.id]) {\n this.shadows[image.id] = shadow;\n }\n\n shadow.open();\n this.overlay.show();\n }\n\n // close lightbox = remove shadow + hide overlay\n close(image) {\n this.currentImage = null;\n\n if (!this.shadows[image.id]) return;\n this.shadows[image.id].close();\n\n this.overlay.hide();\n }\n\n closeCurrent() {\n if (!this.currentImage) return;\n this.close(this.currentImage);\n }\n}\n","import config from './config';\n\nexport default class Overlay {\n constructor() {\n const overlay = document.createElement('div');\n overlay.id = 'libra-overlay';\n overlay.classList.add('libra-overlay', 'libra-hidden');\n\n // Set transition duration from config\n overlay.style.transitionDuration = config.transitionDuration + 'ms';\n\n this.element = overlay;\n document.body.appendChild(overlay);\n\n return this;\n }\n\n show() {\n this.element.classList.remove('libra-hidden');\n this.element.classList.add('libra-visible');\n }\n\n hide() {\n this.element.classList.remove('libra-visible');\n this.element.classList.add('libra-hidden');\n }\n}\n","const config = {\n // selects images that load libra.js\n selector: '[data-libra]',\n\n // margin between viewport and zoomed image\n // in px\n margin: 50,\n\n // in small screens, it's best to not use margins\n // otherwise, the zoomed image gets even smaller\n // define on screen smaller than what size, margin is set to 0\n zeroMarginBreakpoint: 768,\n\n // shifts the zoomed image if needed\n offset: { x: 0, y: 0 },\n\n transitionDuration: 200, // milliseconds\n imageCursor: 'zoom-in',\n};\n\nfunction deepMerge(target, source) {\n for (const key in source) {\n if (\n typeof source[key] === 'object' &&\n source[key] !== null &&\n !Array.isArray(source[key])\n ) {\n if (!target[key]) target[key] = {};\n deepMerge(target[key], source[key]);\n } else {\n target[key] = source[key];\n }\n }\n return target;\n}\n\nexport function setConfig(newConfig) {\n deepMerge(config, newConfig);\n}\n\nexport default config;\n","import Animation from './animation.js'\nimport config from './config'\n\nexport default class Shadow {\n isOpen = false;\n\n /**\n * ============\n * Constructors\n * ============\n */\n\n constructor(image) {\n this.original = image;\n this.fetchOriginalPosition();\n this.create(image);\n\n return this;\n }\n\n create(image) {\n // create shadow image\n const shadow = document.createElement('img');\n shadow.src = image.src;\n shadow.id = `libra-shadow-${image.id}`;\n shadow.classList.add('libra-shadow');\n shadow.style.transitionDuration = config.transitionDuration + 'ms';\n\n this.element = shadow;\n\n // set positioning and place shadow element\n this.positionShadow();\n this.placeItself();\n }\n\n fetchOriginalPosition() {\n const rect = this.original.getBoundingClientRect();\n this.originalPosition = {\n top: rect.top + window.scrollY + config.offset.y,\n left: rect.left + window.scrollX + config.offset.x,\n width: rect.width,\n height: rect.height,\n };\n }\n\n positionShadow() {\n this.element.style.top = this.originalPosition.top + 'px';\n this.element.style.left = this.originalPosition.left + 'px';\n this.element.style.width = this.originalPosition.width + 'px';\n this.element.style.height = this.originalPosition.height + 'px';\n }\n\n /**\n * ============\n * Actions\n * ============\n */\n\n open() {\n this.isOpen = true;\n this.element.classList.add('open');\n\n // Update original position before animation in case viewport changed\n this.fetchOriginalPosition();\n this.positionShadow();\n\n this.original.style.visibility = 'hidden';\n if (!document.body.contains(this.element)) this.placeItself();\n\n // play animation\n const animate = () =>\n Animation.transformMatrix(\n this.element,\n this.originalPosition,\n Animation.calculateFinalState(this.element),\n );\n\n if (this.element.naturalWidth === 0 || this.element.naturalHeight === 0) {\n // Wait for image to load before animating\n this.element.addEventListener('load', animate, { once: true });\n } else {\n // animate directly if loaded\n animate();\n }\n }\n\n close() {\n this.isOpen = false;\n this.element.classList.remove('open');\n\n Animation.resetTransformMatrix(this.element);\n // Wait for animation to complete before showing original and destroying shadow\n setTimeout(() => {\n this.original.style.visibility = 'visible';\n this.destroyItself();\n }, config.transitionDuration);\n }\n\n placeItself() {\n document.body.appendChild(this.element);\n }\n\n destroyItself() {\n if (!document.body.contains(this.element)) return;\n document.body.removeChild(this.element);\n }\n}\n","import config from './config';\n\nexport default class Animation {\n static calculateFinalState(element) {\n let finals = {}\n\n let margin = config.margin;\n if (window.innerWidth <= config.zeroMarginBreakpoint) {\n margin = 0\n }\n\n const nw = element.naturalWidth;\n const nh = element.naturalHeight;\n const ratio = nw / nh;\n const ww = window.innerWidth - 2*margin;\n const wh = window.innerHeight - 2*margin;\n\n // size image based on width first\n finals.width = (nw > ww) ? ww : nw;\n finals.height = (nw > ww) ? ww / ratio : nh;\n\n // if height is too big, adjust based on height\n if (finals.height > wh) {\n finals.height = wh;\n finals.width = wh * ratio;\n }\n\n finals.top = (wh - finals.height) / 2 + window.scrollY + margin + config.offset.y;\n finals.left = (ww - finals.width) / 2 + window.scrollX + margin + config.offset.x;\n\n return finals;\n }\n\n static transformMatrix(element, starts, finals) {\n // Calculate scaling factors based on width and height interpolation\n const scaleX = finals.width / starts.width;\n const scaleY = finals.height / starts.height;\n\n // Calculate the center of the starting and final positions\n const startCenterX = starts.left + starts.width / 2;\n const startCenterY = starts.top + starts.height / 2;\n const finalCenterX = finals.left + finals.width / 2;\n const finalCenterY = finals.top + finals.height / 2;\n\n const translateX = finalCenterX - startCenterX;\n const translateY = finalCenterY - startCenterY;\n\n // Apply the transform with matrix (scale + translate)\n element.style.transform = `matrix(${scaleX}, 0, 0, ${scaleY}, ${translateX}, ${translateY})`;\n }\n\n static resetTransformMatrix(element) {\n element.style.transform = `matrix(1, 0, 0, 1, 0, 0)`;\n }\n}\n"],"names":["$0c04c0cc2b6985d8$var$config","selector","margin","zeroMarginBreakpoint","offset","x","y","transitionDuration","imageCursor","$e49d13fc7942bae1$export$2e2bcd8739ae039","overlay","document","createElement","id","classList","add","style","element","body","appendChild","show","remove","hide","$6e8e6c64a3263339$export$2e2bcd8739ae039","calculateFinalState","finals","window","innerWidth","nw","naturalWidth","nh","naturalHeight","ratio","ww","wh","innerHeight","width","height","top","scrollY","left","scrollX","transformMatrix","starts","scaleX","scaleY","startCenterX","startCenterY","finalCenterX","finalCenterY","transform","resetTransformMatrix","$2f427fc7e1c3703f$export$2e2bcd8739ae039","isOpen","image","original","fetchOriginalPosition","create","shadow","src","positionShadow","placeItself","rect","getBoundingClientRect","originalPosition","open","visibility","contains","animate","addEventListener","once","close","setTimeout","destroyItself","removeChild","$e220af4964903f87$export$2e2bcd8739ae039","currentImage","shadows","config","$0c04c0cc2b6985d8$var$deepMerge","target","source","key","Array","isArray","initOverlay","initImages","initControls","closeCurrent","images","querySelectorAll","forEach","tagName","crypto","randomUUID","cursor","e","default"],"version":3,"file":"libra.min.js.map"}
\ No newline at end of file |
