@taprootio/espalier 4.8.0 → 4.9.1

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.
@@ -1,10 +1,18 @@
1
- var i=function(l,e,s,t){var a=arguments.length,r=a<3?e:t===null?t=Object.getOwnPropertyDescriptor(e,s):t,p;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(l,e,s,t);else for(var d=l.length-1;d>=0;d--)(p=l[d])&&(r=(a<3?p(r):a>3?p(e,s,r):p(e,s))||r);return a>3&&r&&Object.defineProperty(e,s,r),r};import{css as g,html as c,nothing as v}from"lit";import{customElement as u,property as n}from"lit/decorators.js";import{classMap as b}from"lit/directives/class-map.js";import{createRef as m,ref as f}from"lit/directives/ref.js";import"../button/esp-button.js";import"../progress/esp-progress.js";import{EspalierElementBase as h}from"../shared/esp-element-base.js";const w="esp-internal-image-preview-remove",y="esp-internal-image-preview-retry";let o=class extends h{constructor(){super(...arguments),this.image=m(),this.url="",this.alt="",this.failed=!1}render(){const e=this.progress!==void 0,s=this.failed&&!e,t=e?this.alt?`Cancel upload and remove ${this.alt}`:"Cancel upload and remove image":this.alt?`Remove ${this.alt}`:"Remove image";return c`<div>
2
- <img ${f(this.image)} src=${this.url} alt=${this.alt} draggable="false" decoding="async" />
1
+ var n=function(a,e,t,r){var i=arguments.length,o=i<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,h;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(a,e,t,r);else for(var p=a.length-1;p>=0;p--)(h=a[p])&&(o=(i<3?h(o):i>3?h(e,t,o):h(e,t))||o);return i>3&&o&&Object.defineProperty(e,t,o),o};import{css as v,html as d,nothing as c}from"lit";import{customElement as g,property as u}from"lit/decorators.js";import{classMap as b}from"lit/directives/class-map.js";import{keyed as f}from"lit/directives/keyed.js";import{createRef as y,ref as w}from"lit/directives/ref.js";import"../button/esp-button.js";import"../progress/esp-progress.js";import{EspalierElementBase as m}from"../shared/esp-element-base.js";import{previewLoadQueue as k}from"./preview-load-queue.js";const T="esp-internal-image-preview-remove",R="esp-internal-image-preview-retry",L=2,E=250,I=6e4;function l(a){const e=a.trim().toLowerCase();return e.length>0&&!e.startsWith("blob:")&&!e.startsWith("data:")}let s=class extends m{constructor(){super(...arguments),this.image=y(),this.url="",this.alt="",this.failed=!1,this.sourceToken=0,this.admittedUrl="",this.remoteImageLoaded=!1,this.imageLoadFailed=!1,this.automaticRetryCount=0,this.remotePreviewVisible=!1,this.visibilityObserver=null,this.queuedLoadCancel=null,this.loadSlotRelease=null,this.retryTimer=null,this.loadTimeoutTimer=null,this.activeSourceToken=null}connectedCallback(){super.connectedCallback(),this.startCurrentPreview()}disconnectedCallback(){this.stopVisibilityObserver(),this.cancelRemoteWork(),this.remoteImageLoaded=!1,this.admittedUrl="",this.sourceToken+=1,this.remotePreviewVisible=!1,super.disconnectedCallback()}willUpdate(e){super.willUpdate(e),e.has("url")&&(this.stopVisibilityObserver(),this.cancelRemoteWork(),this.sourceToken+=1,this.admittedUrl="",this.remoteImageLoaded=!1,this.imageLoadFailed=!1,this.automaticRetryCount=0,this.remotePreviewVisible=!1)}updated(e){super.updated(e),e.has("url")&&this.startCurrentPreview()}startCurrentPreview(){if(!(!this.isConnected||!l(this.url))){if(typeof IntersectionObserver>"u"){this.remotePreviewVisible=!0,this.requestRemoteLoad();return}this.visibilityObserver??=new IntersectionObserver((e,t)=>{if(t!==this.visibilityObserver)return;const r=e.find(i=>i.target===this);!r||!this.isConnected||!l(this.url)||(this.remotePreviewVisible=r.isIntersecting,r.isIntersecting?this.requestRemoteLoad():!this.loadSlotRelease&&!this.remoteImageLoaded&&this.cancelQueuedLoad())},{threshold:0}),this.visibilityObserver.observe(this)}}stopVisibilityObserver(){this.visibilityObserver?.disconnect(),this.visibilityObserver=null}requestRemoteLoad(){if(!this.isConnected||!l(this.url)||!this.remotePreviewVisible||this.imageLoadFailed||this.remoteImageLoaded||this.loadSlotRelease||this.queuedLoadCancel||this.retryTimer)return;let e=!1;const t=k.request(r=>{if(e=!0,this.queuedLoadCancel=null,!this.isConnected||!l(this.url)||!this.remotePreviewVisible||this.imageLoadFailed||this.remoteImageLoaded){r();return}this.loadSlotRelease=r;const i=++this.sourceToken;this.activeSourceToken=i,this.admittedUrl=this.url,this.loadTimeoutTimer=setTimeout(()=>this.handleImageFailure(i),I),this.requestUpdate()});e||(this.queuedLoadCancel=t)}handleImageLoad(e,t){this.isActiveImageEvent(e,t)&&(this.completeActiveLoad(),this.remoteImageLoaded=!0,this.stopVisibilityObserver())}handleImageError(e,t){this.isActiveImageEvent(e,t)&&this.handleImageFailure(t)}isActiveImageEvent(e,t){return e.currentTarget instanceof HTMLImageElement&&e.currentTarget.getAttribute("src")===this.url&&t===this.activeSourceToken&&t===this.sourceToken&&this.loadSlotRelease!==null}handleImageFailure(e){if(e!==this.activeSourceToken||e!==this.sourceToken||!this.loadSlotRelease)return;if(this.abandonActiveLoad(),this.automaticRetryCount>=L){this.imageLoadFailed=!0,this.requestUpdate();return}this.automaticRetryCount+=1;const t=.75+Math.random()*.5,r=Math.round(E*2**(this.automaticRetryCount-1)*t),i=this.sourceToken;this.retryTimer=setTimeout(()=>{this.retryTimer=null,i===this.sourceToken&&this.requestRemoteLoad()},r)}completeActiveLoad(){this.releaseActiveLoad()}abandonActiveLoad(){if(!this.loadSlotRelease)return;const e=this.shadowRoot?.querySelector("img");e?.getAttribute("src")===this.admittedUrl&&e.removeAttribute("src"),this.admittedUrl="",this.sourceToken+=1,this.releaseActiveLoad(),this.isConnected&&this.requestUpdate()}releaseActiveLoad(){this.loadTimeoutTimer!==null&&(clearTimeout(this.loadTimeoutTimer),this.loadTimeoutTimer=null),this.activeSourceToken=null;const e=this.loadSlotRelease;this.loadSlotRelease=null,e?.()}cancelQueuedLoad(){const e=this.queuedLoadCancel;this.queuedLoadCancel=null,e?.()}cancelRemoteWork(){this.retryTimer!==null&&(clearTimeout(this.retryTimer),this.retryTimer=null),this.cancelQueuedLoad(),this.abandonActiveLoad()}retryImage(){l(this.url)&&(this.cancelRemoteWork(),this.sourceToken+=1,this.admittedUrl="",this.remoteImageLoaded=!1,this.imageLoadFailed=!1,this.automaticRetryCount=0,this.remotePreviewVisible=!0,this.requestRemoteLoad())}renderImage(){const t=l(this.url)?this.admittedUrl:this.url,r=this.sourceToken;return f(`${t}:${r}`,d`<img
2
+ ${w(this.image)}
3
+ src=${t||c}
4
+ alt=${this.alt}
5
+ draggable="false"
6
+ decoding="async"
7
+ @load=${i=>this.handleImageLoad(i,r)}
8
+ @error=${i=>this.handleImageError(i,r)}
9
+ />`)}render(){const e=this.progress!==void 0,t=this.failed&&!e,r=this.imageLoadFailed&&!e&&!t,i=e?this.alt?`Cancel upload and remove ${this.alt}`:"Cancel upload and remove image":this.alt?`Remove ${this.alt}`:"Remove image";return d`<div>
10
+ ${this.renderImage()}
3
11
  <button
4
12
  type="button"
5
- aria-label=${t}
13
+ aria-label=${i}
6
14
  class=${b({uploading:e})}
7
- @click=${()=>{this.dispatchEvent(new CustomEvent(w,{detail:this,bubbles:!0,composed:!0}))}}
15
+ @click=${()=>{this.dispatchEvent(new CustomEvent(T,{detail:this,bubbles:!0,composed:!0}))}}
8
16
  >
9
17
  <svg
10
18
  xmlns="http://www.w3.org/2000/svg"
@@ -20,7 +28,7 @@ var i=function(l,e,s,t){var a=arguments.length,r=a<3?e:t===null?t=Object.getOwnP
20
28
  <path d="M6 6l12 12" />
21
29
  </svg>
22
30
  </button>
23
- ${e?c`
31
+ ${e?d`
24
32
  <div class="upload-overlay">
25
33
  <esp-progress
26
34
  mode="circle"
@@ -30,8 +38,8 @@ var i=function(l,e,s,t){var a=arguments.length,r=a<3?e:t===null?t=Object.getOwnP
30
38
  label="Upload progress"
31
39
  ></esp-progress>
32
40
  </div>
33
- `:v}
34
- ${s?c`
41
+ `:c}
42
+ ${t?d`
35
43
  <div class="upload-overlay failed">
36
44
  <svg
37
45
  class="alert-icon"
@@ -55,13 +63,43 @@ var i=function(l,e,s,t){var a=arguments.length,r=a<3?e:t===null?t=Object.getOwnP
55
63
  class="retry-btn"
56
64
  collapsed
57
65
  label="Retry upload"
58
- @esp-clicked=${a=>{a.stopPropagation(),this.dispatchEvent(new CustomEvent(y,{detail:this,bubbles:!0,composed:!0}))}}
66
+ @esp-clicked=${o=>{o.stopPropagation(),this.dispatchEvent(new CustomEvent(R,{detail:this,bubbles:!0,composed:!0}))}}
59
67
  >
60
68
  Retry
61
69
  </esp-button>
62
70
  </div>
63
- `:v}
64
- </div>`}};o.styles=[...h.styles,g`
71
+ `:c}
72
+ ${r?d`
73
+ <div class="upload-overlay failed image-load-failed">
74
+ <svg
75
+ class="alert-icon"
76
+ xmlns="http://www.w3.org/2000/svg"
77
+ viewBox="0 0 24 24"
78
+ fill="none"
79
+ stroke="currentColor"
80
+ stroke-width="2"
81
+ stroke-linecap="round"
82
+ stroke-linejoin="round"
83
+ >
84
+ <path stroke="none" d="M0 0h24v24H0z" fill="none" />
85
+ <path d="M12 9v4" />
86
+ <path
87
+ d="M10.363 3.591l-8.106 13.534a1.914 1.914 0 0 0 1.636 2.871h16.214a1.914 1.914 0 0 0 1.636 -2.87l-8.106 -13.536a1.914 1.914 0 0 0 -3.274 0z"
88
+ />
89
+ <path d="M12 16h.01" />
90
+ </svg>
91
+ <span class="error-label">Image failed to load</span>
92
+ <esp-button
93
+ class="image-retry-btn"
94
+ collapsed
95
+ label="Retry image"
96
+ @esp-clicked=${o=>{o.stopPropagation(),this.retryImage()}}
97
+ >
98
+ Retry image
99
+ </esp-button>
100
+ </div>
101
+ `:c}
102
+ </div>`}};s.styles=[...m.styles,v`
65
103
  :host {
66
104
  display: block;
67
105
  box-sizing: border-box;
@@ -164,9 +202,10 @@ var i=function(l,e,s,t){var a=arguments.length,r=a<3?e:t===null?t=Object.getOwnP
164
202
  font-weight: 600;
165
203
  }
166
204
 
167
- .retry-btn {
205
+ .retry-btn,
206
+ .image-retry-btn {
168
207
  --esp-color-action-background: transparent;
169
208
  --esp-color-action-text: var(--esp-image-preview-overlay-text, var(--esp-color-layer-1));
170
209
  --esp-color-border: var(--esp-image-preview-overlay-text, var(--esp-color-layer-1));
171
210
  }
172
- `],i([n()],o.prototype,"url",void 0),i([n()],o.prototype,"alt",void 0),i([n({type:Number})],o.prototype,"progress",void 0),i([n({type:Boolean})],o.prototype,"failed",void 0),o=i([u("esp-image-preview")],o);export{o as EspalierImagePreview};
211
+ `],n([u()],s.prototype,"url",void 0),n([u()],s.prototype,"alt",void 0),n([u({type:Number})],s.prototype,"progress",void 0),n([u({type:Boolean})],s.prototype,"failed",void 0),s=n([g("esp-image-preview")],s);export{s as EspalierImagePreview};
@@ -0,0 +1 @@
1
+ class s{constructor(e){this.limit=e,this.active=0,this.pending=[]}request(e){const i={active:!1,cancelled:!1,released:!1,start:e};return this.pending.push(i),this.drain(),()=>{if(i.cancelled)return;if(i.cancelled=!0,i.active){this.release(i);return}const t=this.pending.indexOf(i);t>=0&&this.pending.splice(t,1)}}drain(){for(;this.active<this.limit&&this.pending.length>0;){const e=this.pending.shift();e.cancelled||(e.active=!0,this.active+=1,e.start(()=>this.release(e)))}}release(e){!e.active||e.released||(e.released=!0,e.active=!1,this.active-=1,this.drain())}}const a=new s(4);export{a as previewLoadQueue};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taprootio/espalier",
3
- "version": "4.8.0",
3
+ "version": "4.9.1",
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",