@taprootio/espalier 4.14.1 → 4.15.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.
@@ -15,6 +15,18 @@ import "../button/esp-button.js";
15
15
  * A subtle caret at the bottom of the screen reveals a drawer
16
16
  * overlay containing the image caption and a `comments` slot.
17
17
  *
18
+ * Both halves of that panel are optional. `hide-comments` drops the
19
+ * comment count and the `comments` slot; `hide-caption` drops the
20
+ * image caption. With only the caption left, the bar shows it on one
21
+ * line and slides up only when the line is actually clipped — a
22
+ * caption that already fits has no caret and no tab stop. With both
23
+ * hidden there is no bar, though navigation dots remain for a
24
+ * multi-image gallery.
25
+ *
26
+ * ```html
27
+ * <esp-lightbox for=".gallery" hide-comments></esp-lightbox>
28
+ * ```
29
+ *
18
30
  * ```html
19
31
  * <div class="gallery">
20
32
  * <esp-image caption="A mountain lake" original-width="1200" original-height="800" low-res="https://picsum.photos/id/29/300/200">
@@ -65,6 +77,18 @@ export declare class EspalierLightbox extends EspalierElementBase {
65
77
  * @type {number}
66
78
  */
67
79
  commentCount: number;
80
+ /**
81
+ * Remove the comment affordance: no comment count, no caret driven by it,
82
+ * and no `comments` slot. The caption can still open a drawer when it is too
83
+ * long for one line.
84
+ * @type {boolean}
85
+ */
86
+ hideComments: boolean;
87
+ /**
88
+ * Remove the image caption from the bar and the drawer.
89
+ * @type {boolean}
90
+ */
91
+ hideCaption: boolean;
68
92
  /** Open the lightbox at the given image index. */
69
93
  open(index: number): void;
70
94
  /** Close the lightbox. */
@@ -1,4 +1,4 @@
1
- var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnPropertyDescriptor(e,t):i,n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(l,e,t,i);else for(var r=l.length-1;r>=0;r--)(n=l[r])&&(s=(a<3?n(s):a>3?n(e,t,s):n(e,t))||s);return a>3&&s&&Object.defineProperty(e,t,s),s},d;import{css as C,html as h,nothing as m}from"lit";import{customElement as D,property as y,state as _}from"lit/decorators.js";import{classMap as f}from"lit/directives/class-map.js";import{keyed as k}from"lit/directives/keyed.js";import{styleMap as b}from"lit/directives/style-map.js";import{cancelSVG as O}from"../shared/svgs/cancel.js";import{commentSVG as $}from"../shared/svgs/comment.js";import{leftArrow as S}from"../shared/svgs/left-arrow.js";import{rightArrow as z}from"../shared/svgs/right-arrow.js";import{validImageDimensions as g}from"../image/image-dimensions.js";import{EspalierElementBase as x}from"../shared/esp-element-base.js";import{ESP_EVENTS as R}from"../shared/events.js";import{OverlayController as M}from"../shared/overlay-controller.js";import{RafThrottle as v}from"../shared/raf-throttle.js";import"../image/esp-image.js";import"../image/esp-image-option.js";import"../button/esp-button.js";function L(l,e){if(!l)return e;const t=Math.min(e.width/l.width,e.height/l.height);return!Number.isFinite(t)||t<=0?e:{width:Math.min(e.width,l.width*t),height:Math.min(e.height,l.height*t)}}let o=d=class extends x{constructor(){super(...arguments),this.isOpen=!1,this.currentIndex=0,this.drawerOpen=!1,this._images=[],this._clickHandlers=new Map,this._clickSetupFrame=new v(()=>this._runClickSetup()),this._imageMeasureFrame=new v(()=>this._runImageMeasurement()),this._galleryObserver=null,this._galleryRefreshFrame=new v(()=>this._runGalleryRefresh()),this._galleryRefreshInvalidatesDimensions=!1,this._observedGallery=null,this._imageContainerObserver=null,this._observedImageContainer=null,this._observedRenderedImage=null,this._loadedIntrinsicDimensions=null,this._imageDimensions=null,this._overlay=new M({host:this,getFocusTrapContainer:()=>this.shadowRoot?.querySelector(".lightbox")??null}),this._touchStartX=0,this._touchStartY=0,this._touchDeltaX=0,this._touchDeltaY=0,this._swiping=!1,this._swipingVertical=!1,this.for="",this.commentCount=0,this._scheduleImageMeasurement=()=>{this.isOpen&&this._imageMeasureFrame.schedule()},this._handleViewportChange=()=>{this._prepareImageDimensions(),this._scheduleImageMeasurement()},this._handleRenderedImageLoad=()=>{const e=this._observedRenderedImage;if(!e)return;const t=g(e.naturalWidth,e.naturalHeight);t&&(this._loadedIntrinsicDimensions=t,this._prepareImageDimensions())}}get _commentLabel(){return this.commentCount<=0?"No comments. Add yours!":this.commentCount===1?"1 comment":`${this.commentCount} comments`}open(e){if(this._collectImages(),this._images.length===0)return;const t=Number.isFinite(e)?Math.trunc(e):0,i=Math.max(0,Math.min(t,this._images.length-1));if(this.isOpen){i===this.currentIndex?(this._prepareImageDimensions(),this._scheduleImageMeasurement()):this._goTo(i);return}this.currentIndex=i,this._loadedIntrinsicDimensions=null,this._prepareImageDimensions(),this.isOpen=!0,this.drawerOpen=!1,this._startImageSizing(),this._overlay.open(),this._emitChanged(),this.updateComplete.then(()=>{this.isOpen&&this._overlay.moveFocusInto()})}close(){this.isOpen&&(this.isOpen=!1,this.drawerOpen=!1,this._stopImageSizing(),this._overlay.close())}_viewportDimensions(){const e=document.documentElement.clientWidth||window.innerWidth,t=document.documentElement.clientHeight||window.innerHeight;return g(e,t)??{width:1,height:1}}_availableImageDimensions(){const e=this.shadowRoot?.querySelector(".image-container");if(e){const t=e.getBoundingClientRect(),i=g(t.width,t.height);if(i)return i}return this._viewportDimensions()}_sourceIntrinsicDimensions(e){if(!e)return null;const t=g(e.originalWidth,e.originalHeight);if(t)return t;const i=Array.from(e.children).find(n=>n.tagName==="PICTURE"||n.tagName==="IMG"),s=(i?.tagName==="IMG"?i:i?.querySelector("img"))??e.shadowRoot?.querySelector("img");return s?g(s.naturalWidth,s.naturalHeight)??g(Number(s.getAttribute("width")),Number(s.getAttribute("height"))):null}_prepareImageDimensions(){const e=this._loadedIntrinsicDimensions??this._sourceIntrinsicDimensions(this._images[this.currentIndex]);this._setImageDimensions(L(e,this._availableImageDimensions()))}_setImageDimensions(e){const t=Math.max(1,e.width),i=Math.max(1,e.height);this._imageDimensions&&Math.abs(this._imageDimensions.width-t)<.5&&Math.abs(this._imageDimensions.height-i)<.5||(this._imageDimensions={width:t,height:i})}_responsiveSizes(){return`${Math.max(1,Math.ceil(this._imageDimensions?.width??1))}px`}_runImageMeasurement(){!this.isOpen||!this.isConnected||(this._observeRenderedImage(),this._prepareImageDimensions())}_startImageSizing(){window.addEventListener("resize",this._handleViewportChange),window.addEventListener("orientationchange",this._handleViewportChange),window.visualViewport?.addEventListener("resize",this._handleViewportChange)}_observeImageContainer(){const e=this.shadowRoot?.querySelector(".image-container")??null;e!==this._observedImageContainer&&(this._imageContainerObserver?.disconnect(),this._imageContainerObserver=null,this._observedImageContainer=e,!(!e||typeof ResizeObserver>"u")&&(this._imageContainerObserver=new ResizeObserver(this._scheduleImageMeasurement),this._imageContainerObserver.observe(e)))}_stopImageSizing(){window.removeEventListener("resize",this._handleViewportChange),window.removeEventListener("orientationchange",this._handleViewportChange),window.visualViewport?.removeEventListener("resize",this._handleViewportChange),this._imageContainerObserver?.disconnect(),this._imageContainerObserver=null,this._observedImageContainer=null,this._stopObservingRenderedImage(),this._imageMeasureFrame.cancel()}_observeRenderedImage(){const e=this.shadowRoot?.querySelector(".image-container esp-image"),i=e?.querySelector("img")??null??e?.shadowRoot?.querySelector("img")??null;i!==this._observedRenderedImage&&(this._stopObservingRenderedImage(),this._observedRenderedImage=i,i?.addEventListener("load",this._handleRenderedImageLoad)),i?.complete&&this._handleRenderedImageLoad()}_stopObservingRenderedImage(){this._observedRenderedImage?.removeEventListener("load",this._handleRenderedImageLoad),this._observedRenderedImage=null}_collectImages(){if(!this.for)return this._images=[],null;let e;try{e=document.querySelector(this.for)}catch{return this._images=[],null}return e?(this._images=Array.from(e.querySelectorAll("esp-image")),e):(this._images=[],null)}_attachClickHandlers(e=!1){const t=this._images[this.currentIndex],i=this.currentIndex;this._detachClickHandlers();const a=this._collectImages();if(this._images.forEach((p,I)=>{const w=()=>this.open(I);p.addEventListener("click",w),p.classList.add(d._CLICKABLE_CLASS),this._clickHandlers.set(p,w)}),this._observeGallery(a),!this.isOpen)return;if(this._images.length===0){this.close();return}const s=t?this._images.indexOf(t):-1,n=s>=0?s:Math.min(i,this._images.length-1),r=this._images[n]!==t,u=n!==this.currentIndex;this.currentIndex=n,(r||e)&&(this._loadedIntrinsicDimensions=null),this._prepareImageDimensions(),this.requestUpdate(),(r||u)&&this._emitChanged()}_detachClickHandlers(){for(const[e,t]of this._clickHandlers)e.removeEventListener("click",t),e.classList.remove(d._CLICKABLE_CLASS);this._clickHandlers.clear()}_observeGallery(e){e!==this._observedGallery&&(this._cancelGalleryRefresh(),this._galleryObserver?.disconnect(),this._galleryObserver=null,this._observedGallery=e,!(!e||typeof MutationObserver>"u")&&(this._galleryObserver=new MutationObserver(t=>this._scheduleGalleryRefresh(t)),this._galleryObserver.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["caption","height","local-image","low-res","media","original-height","original-width","src","srcset","type","url","width"]})))}_scheduleGalleryRefresh(e){const t=this._images[this.currentIndex];t&&(this._galleryRefreshInvalidatesDimensions||=e.some(i=>i.type==="attributes"&&i.attributeName==="caption"?!1:i.target===t||t.contains(i.target))),this._galleryRefreshFrame.schedule()}_runGalleryRefresh(){if(!this.isConnected)return;const e=this._galleryRefreshInvalidatesDimensions;this._galleryRefreshInvalidatesDimensions=!1,this._attachClickHandlers(e)}_cancelGalleryRefresh(){this._galleryRefreshFrame.cancel(),this._galleryRefreshInvalidatesDimensions=!1}_stopObservingGallery(){this._cancelGalleryRefresh(),this._galleryObserver?.disconnect(),this._galleryObserver=null,this._observedGallery=null}_goTo(e){const t=this._images.length;if(t===0)return;const i=(e%t+t)%t;i!==this.currentIndex&&(this.currentIndex=i,this._loadedIntrinsicDimensions=null,this._prepareImageDimensions(),this._scheduleImageMeasurement(),this._emitChanged())}_emitChanged(){this.dispatchEvent(new CustomEvent(R.LIGHTBOX_CHANGED,{detail:{index:this.currentIndex},bubbles:!0,composed:!0}))}_prev(){this._goTo(this.currentIndex-1)}_next(){this._goTo(this.currentIndex+1)}_handleKeyDown(e){if(this.isOpen)switch(e.key){case"Escape":e.preventDefault(),this.close();break;case"ArrowLeft":e.preventDefault(),this._prev();break;case"ArrowRight":e.preventDefault(),this._next();break;case"ArrowUp":e.preventDefault(),this.drawerOpen||this._toggleDrawer();break;case"ArrowDown":e.preventDefault(),this.drawerOpen&&this._toggleDrawer();break;case"Tab":this._overlay.trapFocus(e);break}}_handleTouchStart(e){e.touches.length===1&&(this._touchStartX=e.touches[0].clientX,this._touchStartY=e.touches[0].clientY,this._touchDeltaX=0,this._touchDeltaY=0,this._swiping=!1,this._swipingVertical=!1)}_handleTouchMove(e){if(e.touches.length!==1)return;const t=e.touches[0].clientX-this._touchStartX,i=e.touches[0].clientY-this._touchStartY;!this._swiping&&!this._swipingVertical&&(Math.abs(t)>10||Math.abs(i)>10)&&(Math.abs(t)>Math.abs(i)?this._swiping=!0:this._swipingVertical=!0),this._swiping?(e.preventDefault(),this._touchDeltaX=t):this._swipingVertical&&(e.preventDefault(),this._touchDeltaY=i)}_handleTouchEnd(){this._swiping?this._touchDeltaX>50?this._prev():this._touchDeltaX<-50&&this._next():this._swipingVertical&&(this._touchDeltaY<-50&&!this.drawerOpen?this._toggleDrawer():this._touchDeltaY>50&&this.drawerOpen&&this._toggleDrawer()),this._touchDeltaX=0,this._touchDeltaY=0,this._swiping=!1,this._swipingVertical=!1}_handleLightboxClick(e){if(!this.drawerOpen)return;const t=this.shadowRoot?.querySelector(".comment-panel");t&&e.composedPath().includes(t)||(this.drawerOpen=!1)}_handleImageContainerClick(e){if(e.target===e.currentTarget){if(this.drawerOpen){this.drawerOpen=!1;return}this.close()}}_toggleDrawer(){this.drawerOpen=!this.drawerOpen}_handleBarKeyDown(e){(e.key==="Enter"||e.key===" ")&&(e.preventDefault(),this._toggleDrawer())}connectedCallback(){super.connectedCallback(),!this._overlay.isPromoting&&(d._ensureGlobalStyles(),this._clickSetupFrame.schedule())}_runClickSetup(){this.isConnected&&this._attachClickHandlers()}static _ensureGlobalStyles(){if(document.head.querySelector("style[data-esp-lightbox-global-styles]"))return;const e=document.createElement("style");e.dataset.espLightboxGlobalStyles="",e.textContent=`.${d._CLICKABLE_CLASS} { cursor: pointer; }`,document.head.appendChild(e)}updated(e){super.updated(e),e.has("for")&&this._attachClickHandlers(),this.isOpen?(this._observeImageContainer(),this._scheduleImageMeasurement()):this._stopImageSizing()}disconnectedCallback(){if(super.disconnectedCallback(),this._overlay.isPromoting)return;this._clickSetupFrame.cancel();const e=this.isOpen;this._stopImageSizing(),this._stopObservingGallery(),this._detachClickHandlers(),e&&(this.isOpen=!1,this.drawerOpen=!1,this._overlay.close())}_renderCurrentImage(){const e=this._images[this.currentIndex];if(!e)return m;const t=this._responsiveSizes(),i=this._imageDimensions??this._viewportDimensions(),a={width:`${i.width}px`,height:`${i.height}px`};if(e.localImage)return h`
1
+ var d=function(c,e,t,i){var s=arguments.length,r=s<3?e:i===null?i=Object.getOwnPropertyDescriptor(e,t):i,n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(c,e,t,i);else for(var a=c.length-1;a>=0;a--)(n=c[a])&&(r=(s<3?n(r):s>3?n(e,t,r):n(e,t))||r);return s>3&&r&&Object.defineProperty(e,t,r),r},m;import{css as O,html as o,nothing as l}from"lit";import{customElement as D,property as _,state as u}from"lit/decorators.js";import{classMap as b}from"lit/directives/class-map.js";import{keyed as k}from"lit/directives/keyed.js";import{styleMap as v}from"lit/directives/style-map.js";import{cancelSVG as $}from"../shared/svgs/cancel.js";import{commentSVG as S}from"../shared/svgs/comment.js";import{leftArrow as R}from"../shared/svgs/left-arrow.js";import{rightArrow as z}from"../shared/svgs/right-arrow.js";import{validImageDimensions as g}from"../image/image-dimensions.js";import{EspalierElementBase as x}from"../shared/esp-element-base.js";import{ESP_EVENTS as B}from"../shared/events.js";import{OverlayController as M}from"../shared/overlay-controller.js";import{RafThrottle as w}from"../shared/raf-throttle.js";import"../image/esp-image.js";import"../image/esp-image-option.js";import"../button/esp-button.js";function C(c,e){if(!c)return e;const t=Math.min(e.width/c.width,e.height/c.height);return!Number.isFinite(t)||t<=0?e:{width:Math.min(e.width,c.width*t),height:Math.min(e.height,c.height*t)}}let h=m=class extends x{constructor(){super(...arguments),this.isOpen=!1,this.currentIndex=0,this.drawerOpen=!1,this._images=[],this._clickHandlers=new Map,this._clickSetupFrame=new w(()=>this._runClickSetup()),this._imageMeasureFrame=new w(()=>this._runImageMeasurement()),this._galleryObserver=null,this._galleryRefreshFrame=new w(()=>this._runGalleryRefresh()),this._galleryRefreshInvalidatesDimensions=!1,this._observedGallery=null,this._imageContainerObserver=null,this._observedImageContainer=null,this._observedRenderedImage=null,this._loadedIntrinsicDimensions=null,this._prefetched=new Map,this._captionBarObserver=null,this._observedCaptionParts=[null,null],this._commentBarObserver=null,this._observedCommentBar=null,this._captionClipped=!1,this._imageDimensions=null,this._overlay=new M({host:this,getFocusTrapContainer:()=>this.shadowRoot?.querySelector(".lightbox")??null}),this._touchStartX=0,this._touchStartY=0,this._touchDeltaX=0,this._touchDeltaY=0,this._swiping=!1,this._swipingVertical=!1,this.for="",this.commentCount=0,this.hideComments=!1,this.hideCaption=!1,this._scheduleImageMeasurement=()=>{this.isOpen&&this._imageMeasureFrame.schedule()},this._handleViewportChange=()=>{this._prepareImageDimensions(),this._scheduleImageMeasurement()},this._handleRenderedImageLoad=()=>{const e=this._observedRenderedImage;if(!e)return;const t=g(e.naturalWidth,e.naturalHeight);t&&(this._loadedIntrinsicDimensions=t,this._prepareImageDimensions())},this._measureCaptionClipped=()=>{const e=this.shadowRoot?.querySelector(".caption-line"),t=this.shadowRoot?.querySelector(".caption-toggle");let i=!1;if(e&&t){const s=getComputedStyle(t),r=t.clientWidth-(Number.parseFloat(s.paddingLeft)||0)-(Number.parseFloat(s.paddingRight)||0);i=e.scrollWidth-r>1}i!==this._captionClipped&&(this._captionClipped=i),this.drawerOpen&&!this._drawerAvailable&&(this.drawerOpen=!1)},this._syncBarHeight=()=>{const e=this.shadowRoot?.querySelector(".comment-panel"),t=this._observedCommentBar;!e||!t||e.style.setProperty("--_bar-height",`${t.getBoundingClientRect().height}px`)}}get _commentLabel(){return this.commentCount<=0?"No comments. Add yours!":this.commentCount===1?"1 comment":`${this.commentCount} comments`}open(e){if(this._collectImages(),this._images.length===0)return;const t=Number.isFinite(e)?Math.trunc(e):0,i=Math.max(0,Math.min(t,this._images.length-1));if(this.isOpen){i===this.currentIndex?(this._prepareImageDimensions(),this._scheduleImageMeasurement()):this._goTo(i);return}this.currentIndex=i,this._loadedIntrinsicDimensions=null,this._prepareImageDimensions(),this.isOpen=!0,this.drawerOpen=!1,this._startImageSizing(),this._overlay.open(),this._emitChanged(),this.updateComplete.then(()=>{this.isOpen&&this._overlay.moveFocusInto()})}close(){this.isOpen&&(this.isOpen=!1,this.drawerOpen=!1,this._stopImageSizing(),this._overlay.close())}_viewportDimensions(){const e=document.documentElement.clientWidth||window.innerWidth,t=document.documentElement.clientHeight||window.innerHeight;return g(e,t)??{width:1,height:1}}_availableImageDimensions(){const e=this.shadowRoot?.querySelector(".image-container");if(e){const t=e.getBoundingClientRect(),i=g(t.width,t.height);if(i)return i}return this._viewportDimensions()}_sourceIntrinsicDimensions(e){if(!e)return null;const t=g(e.originalWidth,e.originalHeight);if(t)return t;const i=Array.from(e.children).find(n=>n.tagName==="PICTURE"||n.tagName==="IMG"),r=(i?.tagName==="IMG"?i:i?.querySelector("img"))??e.shadowRoot?.querySelector("img");return r?g(r.naturalWidth,r.naturalHeight)??g(Number(r.getAttribute("width")),Number(r.getAttribute("height"))):null}_prepareImageDimensions(){const e=this._loadedIntrinsicDimensions??this._sourceIntrinsicDimensions(this._images[this.currentIndex]);this._setImageDimensions(C(e,this._availableImageDimensions()))}_setImageDimensions(e){const t=Math.max(1,e.width),i=Math.max(1,e.height);this._imageDimensions&&Math.abs(this._imageDimensions.width-t)<.5&&Math.abs(this._imageDimensions.height-i)<.5||(this._imageDimensions={width:t,height:i})}_responsiveSizes(){return`${Math.max(1,Math.ceil(this._imageDimensions?.width??1))}px`}_responsiveSizesFor(e){const t=C(this._sourceIntrinsicDimensions(e),this._availableImageDimensions());return`${Math.max(1,Math.ceil(t.width))}px`}_runImageMeasurement(){!this.isOpen||!this.isConnected||(this._observeRenderedImage(),this._prepareImageDimensions(),this._prefetchNeighbors())}_startImageSizing(){window.addEventListener("resize",this._handleViewportChange),window.addEventListener("orientationchange",this._handleViewportChange),window.visualViewport?.addEventListener("resize",this._handleViewportChange)}_observeImageContainer(){const e=this.shadowRoot?.querySelector(".image-container")??null;e!==this._observedImageContainer&&(this._imageContainerObserver?.disconnect(),this._imageContainerObserver=null,this._observedImageContainer=e,!(!e||typeof ResizeObserver>"u")&&(this._imageContainerObserver=new ResizeObserver(this._scheduleImageMeasurement),this._imageContainerObserver.observe(e)))}_stopImageSizing(){window.removeEventListener("resize",this._handleViewportChange),window.removeEventListener("orientationchange",this._handleViewportChange),window.visualViewport?.removeEventListener("resize",this._handleViewportChange),this._imageContainerObserver?.disconnect(),this._imageContainerObserver=null,this._observedImageContainer=null,this._stopObservingRenderedImage(),this._stopObservingCaptionBar(),this._stopObservingCommentBar(),this._clearPrefetch(),this._imageMeasureFrame.cancel()}_observeRenderedImage(){const e=this.shadowRoot?.querySelector(".image-container esp-image"),i=e?.querySelector("img")??null??e?.shadowRoot?.querySelector("img")??null;i!==this._observedRenderedImage&&(this._stopObservingRenderedImage(),this._observedRenderedImage=i,i?.addEventListener("load",this._handleRenderedImageLoad)),i?.complete&&this._handleRenderedImageLoad()}_stopObservingRenderedImage(){this._observedRenderedImage?.removeEventListener("load",this._handleRenderedImageLoad),this._observedRenderedImage=null}_projectedSource(e){return e?Array.from(e.children).find(t=>t.tagName==="PICTURE"||t.tagName==="IMG")??null:null}_prepareProjectedClone(e,t,i){const s=e.cloneNode(!0);s.querySelectorAll("source").forEach(n=>n.setAttribute("sizes",t));const r=s.tagName==="IMG"?s:s.querySelector("img");return r?(r.hasAttribute("srcset")&&r.setAttribute("sizes",t),r.setAttribute("loading","eager"),r.setAttribute("fetchpriority",i),r.setAttribute("decoding","async"),s):null}_projectedSignature(e){const t=[e.tagName];for(const s of e.querySelectorAll("source"))t.push(s.getAttribute("type"),s.getAttribute("media"),s.getAttribute("srcset"));const i=e.tagName==="IMG"?e:e.querySelector("img");return t.push(i?.getAttribute("src")??null,i?.getAttribute("srcset")??null,i?.getAttribute("crossorigin")??null,i?.getAttribute("referrerpolicy")??null),JSON.stringify(t)}_warmPlan(e){if(e.localImage)return null;const t=this._projectedSource(e);if(!t)return null;const i=this._responsiveSizesFor(e);return{projected:t,sizes:i,key:`${i}|${this._projectedSignature(t)}`}}_prefetchNeighbors(){const e=this.shadowRoot?.querySelector(".preload");if(!e)return;const t=this._images.length;if(!this.isOpen||t===0){this._clearPrefetch();return}const i=this._images[this.currentIndex],s=new Set,r=m._PREFETCH_RADIUS;for(let n=-r;n<=r;n++){if(n===0)continue;const a=((this.currentIndex+n)%t+t)%t,p=this._images[a];p&&p!==i&&s.add(p)}for(const[n,a]of this._prefetched)s.has(n)&&a.key===this._warmPlan(n)?.key||(a.node.remove(),this._prefetched.delete(n));for(const n of s){if(this._prefetched.has(n))continue;const a=this._warmPlan(n);if(!a)continue;const p=this._prepareProjectedClone(a.projected,a.sizes,"low");p&&(this._prefetched.set(n,{node:p,key:a.key}),e.appendChild(p))}}_clearPrefetch(){for(const e of this._prefetched.values())e.node.remove();this._prefetched.clear()}_collectImages(){if(!this.for)return this._images=[],null;let e;try{e=document.querySelector(this.for)}catch{return this._images=[],null}return e?(this._images=Array.from(e.querySelectorAll("esp-image")),e):(this._images=[],null)}_attachClickHandlers(e=!1){const t=this._images[this.currentIndex],i=this.currentIndex;this._detachClickHandlers();const s=this._collectImages();if(this._images.forEach((f,I)=>{const y=()=>this.open(I);f.addEventListener("click",y),f.classList.add(m._CLICKABLE_CLASS),this._clickHandlers.set(f,y)}),this._observeGallery(s),!this.isOpen)return;if(this._images.length===0){this.close();return}const r=t?this._images.indexOf(t):-1,n=r>=0?r:Math.min(i,this._images.length-1),a=this._images[n]!==t,p=n!==this.currentIndex;this.currentIndex=n,(a||e)&&(this._loadedIntrinsicDimensions=null),this._prepareImageDimensions(),this.requestUpdate(),(a||p)&&this._emitChanged()}_detachClickHandlers(){for(const[e,t]of this._clickHandlers)e.removeEventListener("click",t),e.classList.remove(m._CLICKABLE_CLASS);this._clickHandlers.clear()}_observeGallery(e){e!==this._observedGallery&&(this._cancelGalleryRefresh(),this._galleryObserver?.disconnect(),this._galleryObserver=null,this._observedGallery=e,!(!e||typeof MutationObserver>"u")&&(this._galleryObserver=new MutationObserver(t=>this._scheduleGalleryRefresh(t)),this._galleryObserver.observe(e,{childList:!0,subtree:!0,attributes:!0,attributeFilter:["caption","crossorigin","height","local-image","low-res","media","original-height","original-width","referrerpolicy","src","srcset","type","url","width"]})))}_scheduleGalleryRefresh(e){const t=this._images[this.currentIndex];t&&(this._galleryRefreshInvalidatesDimensions||=e.some(i=>i.type==="attributes"&&i.attributeName==="caption"?!1:i.target===t||t.contains(i.target))),this._galleryRefreshFrame.schedule()}_runGalleryRefresh(){if(!this.isConnected)return;const e=this._galleryRefreshInvalidatesDimensions;this._galleryRefreshInvalidatesDimensions=!1,this._attachClickHandlers(e)}_cancelGalleryRefresh(){this._galleryRefreshFrame.cancel(),this._galleryRefreshInvalidatesDimensions=!1}_stopObservingGallery(){this._cancelGalleryRefresh(),this._galleryObserver?.disconnect(),this._galleryObserver=null,this._observedGallery=null}_goTo(e){const t=this._images.length;if(t===0)return;const i=(e%t+t)%t;i!==this.currentIndex&&(this.currentIndex=i,this._loadedIntrinsicDimensions=null,this._prepareImageDimensions(),this._scheduleImageMeasurement(),this._emitChanged())}_emitChanged(){this.dispatchEvent(new CustomEvent(B.LIGHTBOX_CHANGED,{detail:{index:this.currentIndex},bubbles:!0,composed:!0}))}_prev(){this._goTo(this.currentIndex-1)}_next(){this._goTo(this.currentIndex+1)}_handleKeyDown(e){if(this.isOpen)switch(e.key){case"Escape":e.preventDefault(),this.close();break;case"ArrowLeft":e.preventDefault(),this._prev();break;case"ArrowRight":e.preventDefault(),this._next();break;case"ArrowUp":e.preventDefault(),this.drawerOpen||this._toggleDrawer();break;case"ArrowDown":e.preventDefault(),this.drawerOpen&&this._toggleDrawer();break;case"Tab":this._overlay.trapFocus(e);break}}_handleTouchStart(e){e.touches.length===1&&(this._touchStartX=e.touches[0].clientX,this._touchStartY=e.touches[0].clientY,this._touchDeltaX=0,this._touchDeltaY=0,this._swiping=!1,this._swipingVertical=!1)}_handleTouchMove(e){if(e.touches.length!==1)return;const t=e.touches[0].clientX-this._touchStartX,i=e.touches[0].clientY-this._touchStartY;!this._swiping&&!this._swipingVertical&&(Math.abs(t)>10||Math.abs(i)>10)&&(Math.abs(t)>Math.abs(i)?this._swiping=!0:this._swipingVertical=!0),this._swiping?(e.preventDefault(),this._touchDeltaX=t):this._swipingVertical&&(e.preventDefault(),this._touchDeltaY=i)}_handleTouchEnd(){this._swiping?this._touchDeltaX>50?this._prev():this._touchDeltaX<-50&&this._next():this._swipingVertical&&(this._touchDeltaY<-50&&!this.drawerOpen?this._toggleDrawer():this._touchDeltaY>50&&this.drawerOpen&&this._toggleDrawer()),this._touchDeltaX=0,this._touchDeltaY=0,this._swiping=!1,this._swipingVertical=!1}_handleLightboxClick(e){if(!this.drawerOpen)return;const t=this.shadowRoot?.querySelector(".comment-panel");t&&e.composedPath().includes(t)||(this.drawerOpen=!1)}_handleImageContainerClick(e){if(e.target===e.currentTarget){if(this.drawerOpen){this.drawerOpen=!1;return}this.close()}}get _visibleCaption(){return this.hideCaption?"":this._images[this.currentIndex]?.caption??""}get _showsCaptionBar(){return this.hideComments&&this._visibleCaption!==""}get _drawerAvailable(){return this.hideComments?this._showsCaptionBar&&this._captionClipped:!0}get _showsBar(){return!this.hideComments||this._showsCaptionBar}_toggleDrawer(){this._drawerAvailable&&(this.drawerOpen=!this.drawerOpen)}_handleBarKeyDown(e){(e.key==="Enter"||e.key===" ")&&(e.preventDefault(),this._toggleDrawer())}_observeCaptionBar(){const e=this.shadowRoot?.querySelector(".caption-toggle")??null,t=this.shadowRoot?.querySelector(".caption-line")??null,[i,s]=this._observedCaptionParts;if(e===i&&t===s){this._measureCaptionClipped();return}if(this._captionBarObserver?.disconnect(),this._captionBarObserver=null,this._observedCaptionParts=[e,t],!e||!t){this._captionClipped&&(this._captionClipped=!1);return}typeof ResizeObserver<"u"&&(this._captionBarObserver=new ResizeObserver(this._measureCaptionClipped),this._captionBarObserver.observe(e),this._captionBarObserver.observe(t)),this._measureCaptionClipped()}_stopObservingCaptionBar(){this._captionBarObserver?.disconnect(),this._captionBarObserver=null,this._observedCaptionParts=[null,null]}_observeCommentBar(){const e=this.shadowRoot?.querySelector(".comment-bar")??null;e!==this._observedCommentBar&&(this._commentBarObserver?.disconnect(),this._commentBarObserver=null,this._observedCommentBar=e,e&&typeof ResizeObserver<"u"&&(this._commentBarObserver=new ResizeObserver(this._syncBarHeight),this._commentBarObserver.observe(e))),this._syncBarHeight()}_stopObservingCommentBar(){this._commentBarObserver?.disconnect(),this._commentBarObserver=null,this._observedCommentBar=null}connectedCallback(){super.connectedCallback(),!this._overlay.isPromoting&&(m._ensureGlobalStyles(),this._clickSetupFrame.schedule())}_runClickSetup(){this.isConnected&&this._attachClickHandlers()}static _ensureGlobalStyles(){if(document.head.querySelector("style[data-esp-lightbox-global-styles]"))return;const e=document.createElement("style");e.dataset.espLightboxGlobalStyles="",e.textContent=`.${m._CLICKABLE_CLASS} { cursor: pointer; }`,document.head.appendChild(e)}updated(e){super.updated(e),e.has("for")&&this._attachClickHandlers(),this.isOpen?(this._observeImageContainer(),this._observeCaptionBar(),this._observeCommentBar(),this._scheduleImageMeasurement()):this._stopImageSizing()}disconnectedCallback(){if(super.disconnectedCallback(),this._overlay.isPromoting)return;this._clickSetupFrame.cancel();const e=this.isOpen;this._stopImageSizing(),this._stopObservingGallery(),this._detachClickHandlers(),e&&(this.isOpen=!1,this.drawerOpen=!1,this._overlay.close())}_renderCurrentImage(){const e=this._images[this.currentIndex];if(!e)return l;const t=this._responsiveSizes(),i=this._imageDimensions??this._viewportDimensions(),s={width:`${i.width}px`,height:`${i.height}px`};if(e.localImage)return o`
2
2
  <esp-image
3
3
  class="lightbox-image"
4
4
  original-width=${e.originalWidth}
@@ -6,20 +6,20 @@ var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnP
6
6
  caption=${e.caption}
7
7
  .localImage=${e.localImage}
8
8
  .sizes=${t}
9
- style=${b(a)}
9
+ style=${v(s)}
10
10
  ></esp-image>
11
- `;const s=Array.from(e.children).find(r=>r.tagName==="PICTURE"||r.tagName==="IMG");if(s){const r=s.cloneNode(!0);r.querySelectorAll("source").forEach(p=>p.setAttribute("sizes",t));const u=r.tagName==="IMG"?r:r.querySelector("img");return u?.hasAttribute("srcset")&&u.setAttribute("sizes",t),h`
11
+ `;const r=this._projectedSource(e);if(r){const a=this._prepareProjectedClone(r,t,"high");return o`
12
12
  <esp-image
13
13
  class="lightbox-image"
14
14
  original-width=${e.originalWidth}
15
15
  original-height=${e.originalHeight}
16
16
  caption=${e.caption}
17
17
  .sizes=${t}
18
- style=${b(a)}
18
+ style=${v(s)}
19
19
  >
20
- ${r}
20
+ ${a}
21
21
  </esp-image>
22
- `}const n=Array.from(e.querySelectorAll("esp-image-option"));return h`
22
+ `}const n=Array.from(e.querySelectorAll("esp-image-option"));return o`
23
23
  <esp-image
24
24
  class="lightbox-image"
25
25
  original-width=${e.originalWidth}
@@ -27,17 +27,46 @@ var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnP
27
27
  low-res=${e.imageUrl}
28
28
  caption=${e.caption}
29
29
  .sizes=${t}
30
- style=${b(a)}
30
+ style=${v(s)}
31
31
  >
32
- ${n.map(r=>h`
32
+ ${n.map(a=>o`
33
33
  <esp-image-option
34
- width=${r.width}
35
- url=${r.imageUrl}
36
- type=${r.type||m}
34
+ width=${a.width}
35
+ url=${a.imageUrl}
36
+ type=${a.type||l}
37
37
  ></esp-image-option>
38
38
  `)}
39
39
  </esp-image>
40
- `}render(){if(!this.isOpen)return m;const e=this._images[this.currentIndex],t=e?.caption??"",i=this._images.length;return h`
40
+ `}_renderBarToggle(){if(!this._showsBar)return l;const e=this._drawerAvailable,t=e?o`<span class=${b({"comment-bar-caret":!0,open:this.drawerOpen})}>
41
+ ${A}
42
+ </span>`:l;return this._showsCaptionBar?o`
43
+ <div
44
+ class=${b({"comment-bar-toggle":!0,"caption-toggle":!0})}
45
+ role=${e?"button":l}
46
+ tabindex=${e?"0":l}
47
+ aria-expanded=${e?this.drawerOpen?"true":"false":l}
48
+ aria-controls=${e?"drawer-body":l}
49
+ @click=${this._toggleDrawer}
50
+ @keydown=${this._handleBarKeyDown}
51
+ >
52
+ <span class="caption-line">${this._visibleCaption}</span>
53
+ ${t}
54
+ </div>
55
+ `:o`
56
+ <div
57
+ class="comment-bar-toggle"
58
+ role="button"
59
+ tabindex="0"
60
+ aria-expanded=${this.drawerOpen?"true":"false"}
61
+ aria-controls="drawer-body"
62
+ @click=${this._toggleDrawer}
63
+ @keydown=${this._handleBarKeyDown}
64
+ >
65
+ <span class="comment-bar-icon">${S}</span>
66
+ <span class="comment-bar-label">${this._commentLabel}</span>
67
+ ${t}
68
+ </div>
69
+ `}render(){if(!this.isOpen)return l;const e=this._images[this.currentIndex],t=this._visibleCaption,i=this._images.length;return o`
41
70
  <div
42
71
  class="lightbox"
43
72
  role="dialog"
@@ -61,10 +90,10 @@ var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnP
61
90
  label="Close lightbox"
62
91
  @esp-clicked=${this.close}
63
92
  >
64
- ${O}
93
+ ${$}
65
94
  </esp-button>
66
95
 
67
- ${i>1?h`
96
+ ${i>1?o`
68
97
  <esp-button
69
98
  class="prev-btn"
70
99
  icon-only
@@ -72,7 +101,7 @@ var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnP
72
101
  label="Previous image"
73
102
  @esp-clicked=${this._prev}
74
103
  >
75
- ${S}
104
+ ${R}
76
105
  </esp-button>
77
106
  <esp-button
78
107
  class="next-btn"
@@ -83,52 +112,47 @@ var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnP
83
112
  >
84
113
  ${z}
85
114
  </esp-button>
86
- `:m}
115
+ `:l}
87
116
 
88
117
 
89
118
  <div class="image-container" @click=${this._handleImageContainerClick}>
90
119
  ${k(e,this._renderCurrentImage())}
91
120
  </div>
92
121
 
93
- <div class=${f({"comment-panel":!0,open:this.drawerOpen})}>
94
- <div class="comment-bar">
95
- ${i>1?h`
96
-
97
- <nav class="dots" aria-label="Image navigation">
98
- ${this._images.map((a,s)=>h`
99
- <button
100
- type="button"
101
- class=${f({dot:!0,active:s===this.currentIndex})}
102
- aria-label="Image ${s+1} of ${i}"
103
- aria-current=${s===this.currentIndex?"true":"false"}
104
- @click=${()=>this._goTo(s)}
105
- ></button>
106
- `)}
107
- </nav>
108
- `:m}
109
- <div
110
- class="comment-bar-toggle"
111
- role="button"
112
- tabindex="0"
113
- aria-expanded=${this.drawerOpen?"true":"false"}
114
- aria-controls="drawer-body"
115
- @click=${this._toggleDrawer}
116
- @keydown=${this._handleBarKeyDown}
117
- >
118
- <span class="comment-bar-icon">${$}</span>
119
- <span class="comment-bar-label">${this._commentLabel}</span>
120
- <span class=${f({"comment-bar-caret":!0,open:this.drawerOpen})}>
121
- ${E}
122
- </span>
123
- </div>
124
- </div>
125
- <div class="drawer-body" id="drawer-body">
126
- ${t?h`<div class="caption">${t}</div>`:m}
127
- <slot name="comments"></slot>
128
- </div>
122
+
123
+ <div class="preload" aria-hidden="true" inert></div>
124
+
125
+ ${this._showsBar||i>1?this._renderCommentPanel(t,i):l}
126
+ </div>
127
+ `}_renderCommentPanel(e,t){return o`
128
+ <div
129
+ class=${b({"comment-panel":!0,open:this.drawerOpen,"has-bar":this._showsBar,"caption-only":this._showsCaptionBar})}
130
+ >
131
+ <div class="comment-bar">
132
+ ${t>1?o`
133
+
134
+ <nav class="dots" aria-label="Image navigation">
135
+ ${this._images.map((i,s)=>o`
136
+ <button
137
+ type="button"
138
+ class=${b({dot:!0,active:s===this.currentIndex})}
139
+ aria-label="Image ${s+1} of ${t}"
140
+ aria-current=${s===this.currentIndex?"true":"false"}
141
+ @click=${()=>this._goTo(s)}
142
+ ></button>
143
+ `)}
144
+ </nav>
145
+ `:l}
146
+ ${this._renderBarToggle()}
129
147
  </div>
148
+ ${this._drawerAvailable?o`
149
+ <div class="drawer-body" id="drawer-body">
150
+ ${e?o`<div class="caption">${e}</div>`:l}
151
+ ${this.hideComments?l:o`<slot name="comments"></slot>`}
152
+ </div>
153
+ `:l}
130
154
  </div>
131
- `}};o._CLICKABLE_CLASS="esp-lightbox-clickable",o.styles=[...x.styles,C`
155
+ `}};h._PREFETCH_RADIUS=1,h._CLICKABLE_CLASS="esp-lightbox-clickable",h.styles=[...x.styles,O`
132
156
  :host {
133
157
  display: contents;
134
158
  }
@@ -223,6 +247,19 @@ var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnP
223
247
  }
224
248
 
225
249
 
250
+ .preload {
251
+ position: absolute;
252
+ top: 0;
253
+ left: 0;
254
+ width: 1px;
255
+ height: 1px;
256
+ overflow: hidden;
257
+ opacity: 0;
258
+ pointer-events: none;
259
+ z-index: -1;
260
+ }
261
+
262
+
226
263
 
227
264
  .comment-panel {
228
265
  position: fixed;
@@ -236,10 +273,18 @@ var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnP
236
273
  transform: translateY(calc(100% - var(--_bar-height)));
237
274
  transition: transform 0.3s ease;
238
275
 
239
- --_bar-height: calc(3 * var(--esp-size-small));
276
+
277
+ --_toggle-height: 0px;
278
+ --_dots-height: 0px;
279
+
280
+ --_bar-height: calc(var(--_dots-height) + var(--_toggle-height));
281
+
282
+ &.has-bar {
283
+ --_toggle-height: calc(3 * var(--esp-size-small));
284
+ }
240
285
 
241
286
  &:has(.dots) {
242
- --_bar-height: calc(4.875 * var(--esp-size-small));
287
+ --_dots-height: calc(1.875 * var(--esp-size-small));
243
288
  }
244
289
 
245
290
  &.open {
@@ -326,6 +371,24 @@ var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnP
326
371
  font-weight: 500;
327
372
  }
328
373
 
374
+
375
+ .caption-toggle {
376
+ justify-content: center;
377
+ gap: var(--esp-size-tiny);
378
+ }
379
+
380
+ .caption-line {
381
+ min-width: 0;
382
+ overflow: hidden;
383
+ text-overflow: ellipsis;
384
+ white-space: nowrap;
385
+ font-weight: 500;
386
+ }
387
+
388
+ .caption-only .caption-toggle:not([role="button"]) {
389
+ cursor: default;
390
+ }
391
+
329
392
  .comment-bar-caret {
330
393
  display: flex;
331
394
  width: var(--esp-size-small);
@@ -367,7 +430,7 @@ var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnP
367
430
  display: none;
368
431
  }
369
432
  }
370
- `],c([_()],o.prototype,"isOpen",void 0),c([_()],o.prototype,"currentIndex",void 0),c([_()],o.prototype,"drawerOpen",void 0),c([_()],o.prototype,"_imageDimensions",void 0),c([y({type:String})],o.prototype,"for",void 0),c([y({attribute:"comment-count",type:Number})],o.prototype,"commentCount",void 0),o=d=c([D("esp-lightbox")],o);const E=h` <svg
433
+ `],d([u()],h.prototype,"isOpen",void 0),d([u()],h.prototype,"currentIndex",void 0),d([u()],h.prototype,"drawerOpen",void 0),d([u()],h.prototype,"_captionClipped",void 0),d([u()],h.prototype,"_imageDimensions",void 0),d([_({type:String})],h.prototype,"for",void 0),d([_({attribute:"comment-count",type:Number})],h.prototype,"commentCount",void 0),d([_({attribute:"hide-comments",type:Boolean})],h.prototype,"hideComments",void 0),d([_({attribute:"hide-caption",type:Boolean})],h.prototype,"hideCaption",void 0),h=m=d([D("esp-lightbox")],h);const A=o` <svg
371
434
  xmlns="http://www.w3.org/2000/svg"
372
435
  viewBox="0 0 24 24"
373
436
  fill="none"
@@ -378,4 +441,4 @@ var c=function(l,e,t,i){var a=arguments.length,s=a<3?e:i===null?i=Object.getOwnP
378
441
  >
379
442
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
380
443
  <path d="M6 15l6 -6l6 6" />
381
- </svg>`;export{o as EspalierLightbox};
444
+ </svg>`;export{h as EspalierLightbox};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taprootio/espalier",
3
- "version": "4.14.1",
3
+ "version": "4.15.0",
4
4
  "packageManager": "bun@1.3.12",
5
5
  "description": "Espalier — a themeable, accessible, framework-agnostic, enterprise-grade design system built on web standards and love.",
6
6
  "customElements": "custom-elements.json",