@taprootio/espalier 6.7.0 → 6.8.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.
@@ -1,17 +1,26 @@
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}
1
+ var l=function(n,e,t,o){var i=arguments.length,r=i<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(n,e,t,o);else for(var u=n.length-1;u>=0;u--)(a=n[u])&&(r=(i<3?a(r):i>3?a(e,t,r):a(e,t))||r);return i>3&&r&&Object.defineProperty(e,t,r),r};import{css as v,html as d,nothing as h}from"lit";import{customElement as b,property as c}from"lit/decorators.js";import{classMap as g}from"lit/directives/class-map.js";import{keyed as f}from"lit/directives/keyed.js";import{createRef as w,ref as y}from"lit/directives/ref.js";import"../button/esp-button.js";import"../progress/esp-progress.js";import"../tooltip/esp-tooltip.js";import{EspalierElementBase as m}from"../shared/esp-element-base.js";import{getIconHrefForHost as k}from"../shared/intent-values.js";import{previewLoadQueue as x}from"./preview-load-queue.js";const T="esp-internal-image-preview-remove",E="esp-internal-image-preview-retry",L="esp-internal-image-preview-action",R=2,I=250,C=6e4;function p(n){const e=n.trim().toLowerCase();return e.length>0&&!e.startsWith("blob:")&&!e.startsWith("data:")}let s=class extends m{constructor(){super(...arguments),this.image=w(),this.url="",this.alt="",this.failed=!1,this.positionLabel="",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||!p(this.url))){if(typeof IntersectionObserver>"u"){this.remotePreviewVisible=!0,this.requestRemoteLoad();return}this.visibilityObserver??=new IntersectionObserver((e,t)=>{if(t!==this.visibilityObserver)return;const o=e.find(i=>i.target===this);!o||!this.isConnected||!p(this.url)||(this.remotePreviewVisible=o.isIntersecting,o.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||!p(this.url)||!this.remotePreviewVisible||this.imageLoadFailed||this.remoteImageLoaded||this.loadSlotRelease||this.queuedLoadCancel||this.retryTimer)return;let e=!1;const t=x.request(o=>{if(e=!0,this.queuedLoadCancel=null,!this.isConnected||!p(this.url)||!this.remotePreviewVisible||this.imageLoadFailed||this.remoteImageLoaded){o();return}this.loadSlotRelease=o;const i=++this.sourceToken;this.activeSourceToken=i,this.admittedUrl=this.url,this.loadTimeoutTimer=setTimeout(()=>this.handleImageFailure(i),C),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>=R){this.imageLoadFailed=!0,this.requestUpdate();return}this.automaticRetryCount+=1;const t=.75+Math.random()*.5,o=Math.round(I*2**(this.automaticRetryCount-1)*t),i=this.sourceToken;this.retryTimer=setTimeout(()=>{this.retryTimer=null,i===this.sourceToken&&this.requestRemoteLoad()},o)}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(){p(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=p(this.url)?this.admittedUrl:this.url,o=this.sourceToken;return f(`${t}:${o}`,d`<img
2
+ ${y(this.image)}
3
+ src=${t||h}
4
4
  alt=${this.alt}
5
5
  draggable="false"
6
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>
7
+ @load=${i=>this.handleImageLoad(i,o)}
8
+ @error=${i=>this.handleImageError(i,o)}
9
+ />`)}renderAction(){const{action:e}=this,t=this.alt||this.positionLabel,o=e?.label?.trim();return!e||!o||!k(e.icon,this)?h:d`<esp-tooltip class="preview-action" text=${o}>
10
+ <esp-button
11
+ data-preview-action
12
+ icon-only
13
+ collapsed
14
+ icon=${e.icon}
15
+ label=${t?`${o}: ${t}`:o}
16
+ @esp-clicked=${i=>{i.stopPropagation(),this.dispatchEvent(new CustomEvent(L))}}
17
+ ></esp-button>
18
+ </esp-tooltip>`}render(){const e=this.progress!==void 0,t=this.failed&&!e,o=this.imageLoadFailed&&!e&&!t,i=this.alt||this.positionLabel,r=e?i?`Cancel upload and remove ${i}`:"Cancel upload and remove image":i?`Remove ${i}`:"Remove image";return d`<div>
10
19
  ${this.renderImage()}
11
20
  <button
12
21
  type="button"
13
- aria-label=${i}
14
- class=${b({uploading:e})}
22
+ aria-label=${r}
23
+ class=${g({uploading:e})}
15
24
  @click=${()=>{this.dispatchEvent(new CustomEvent(T,{detail:this,bubbles:!0,composed:!0}))}}
16
25
  >
17
26
  <svg
@@ -38,7 +47,7 @@ var n=function(a,e,t,r){var i=arguments.length,o=i<3?e:r===null?r=Object.getOwnP
38
47
  label="Upload progress"
39
48
  ></esp-progress>
40
49
  </div>
41
- `:c}
50
+ `:h}
42
51
  ${t?d`
43
52
  <div class="upload-overlay failed">
44
53
  <svg
@@ -63,13 +72,13 @@ var n=function(a,e,t,r){var i=arguments.length,o=i<3?e:r===null?r=Object.getOwnP
63
72
  class="retry-btn"
64
73
  collapsed
65
74
  label="Retry upload"
66
- @esp-clicked=${o=>{o.stopPropagation(),this.dispatchEvent(new CustomEvent(R,{detail:this,bubbles:!0,composed:!0}))}}
75
+ @esp-clicked=${a=>{a.stopPropagation(),this.dispatchEvent(new CustomEvent(E,{detail:this,bubbles:!0,composed:!0}))}}
67
76
  >
68
77
  Retry
69
78
  </esp-button>
70
79
  </div>
71
- `:c}
72
- ${r?d`
80
+ `:h}
81
+ ${o?d`
73
82
  <div class="upload-overlay failed image-load-failed">
74
83
  <svg
75
84
  class="alert-icon"
@@ -93,17 +102,48 @@ var n=function(a,e,t,r){var i=arguments.length,o=i<3?e:r===null?r=Object.getOwnP
93
102
  class="image-retry-btn"
94
103
  collapsed
95
104
  label="Retry image"
96
- @esp-clicked=${o=>{o.stopPropagation(),this.retryImage()}}
105
+ @esp-clicked=${a=>{a.stopPropagation(),this.retryImage()}}
97
106
  >
98
107
  Retry image
99
108
  </esp-button>
100
109
  </div>
101
- `:c}
110
+ `:h}
111
+ ${e||t||o?h:this.renderAction()}
102
112
  </div>`}};s.styles=[...m.styles,v`
103
113
  :host {
104
114
  display: block;
105
115
  box-sizing: border-box;
106
116
  position: relative;
117
+
118
+ container-type: size;
119
+ }
120
+
121
+
122
+ .preview-action {
123
+ position: absolute;
124
+ right: var(--esp-size-padding);
125
+ bottom: var(--esp-size-padding);
126
+ z-index: 3;
127
+ }
128
+
129
+ .preview-action esp-button::part(wrapper) {
130
+ box-shadow: 1px 1px 2px var(--esp-color-shadow);
131
+ }
132
+
133
+
134
+ .preview-action esp-button:focus-within::part(wrapper) {
135
+ box-shadow: 0 0 0 2px var(--esp-color-background);
136
+ outline: 2px solid var(--esp-color-text);
137
+ outline-offset: 2px;
138
+ }
139
+
140
+ @container (max-width: 96px) or (max-height: 150px) {
141
+ .preview-action {
142
+
143
+ right: 4px;
144
+ bottom: 4px;
145
+ --esp-button-padding: calc(var(--esp-size-tiny) / 2);
146
+ }
107
147
  }
108
148
 
109
149
  div {
@@ -122,7 +162,6 @@ var n=function(a,e,t,r){var i=arguments.length,o=i<3?e:r===null?r=Object.getOwnP
122
162
  }
123
163
 
124
164
  button:not(.retry-btn) {
125
- visibility: hidden;
126
165
  display: grid;
127
166
  place-content: center;
128
167
  cursor: pointer;
@@ -148,20 +187,23 @@ var n=function(a,e,t,r){var i=arguments.length,o=i<3?e:r===null?r=Object.getOwnP
148
187
  border-color: oklch(from var(--esp-color-danger) var(--esp-l-shadow) c h);
149
188
  }
150
189
 
151
- svg {
152
- height: var(--esp-size-medium);
190
+
191
+ &:focus-visible {
192
+ box-shadow: 0 0 0 2px var(--esp-color-background);
193
+ outline: 2px solid var(--esp-color-text);
194
+ outline-offset: 2px;
153
195
  }
154
196
 
155
-
156
- &.uploading {
157
- visibility: visible;
197
+ svg {
198
+ height: var(--esp-size-medium);
158
199
  }
159
200
  }
160
201
 
161
- &:hover,
162
- &:focus-within {
163
- button:not(.retry-btn) {
164
- visibility: visible;
202
+
203
+ @media (hover: hover) {
204
+ &:not(:hover, :focus-within) button:not(.retry-btn, .uploading) {
205
+ opacity: 0;
206
+ pointer-events: none;
165
207
  }
166
208
  }
167
209
  }
@@ -208,4 +250,4 @@ var n=function(a,e,t,r){var i=arguments.length,o=i<3?e:r===null?r=Object.getOwnP
208
250
  --esp-color-action-text: var(--esp-image-preview-overlay-text, var(--esp-color-layer-1));
209
251
  --esp-color-border: var(--esp-image-preview-overlay-text, var(--esp-color-layer-1));
210
252
  }
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};
253
+ `],l([c()],s.prototype,"url",void 0),l([c()],s.prototype,"alt",void 0),l([c({type:Number})],s.prototype,"progress",void 0),l([c({type:Boolean})],s.prototype,"failed",void 0),l([c({attribute:!1})],s.prototype,"action",void 0),l([c({attribute:!1})],s.prototype,"positionLabel",void 0),s=l([b("esp-image-preview")],s);export{s as EspalierImagePreview};
@@ -1,4 +1,4 @@
1
- import { type EspalierUploadImage, type ExistingImage } from "./image-helpers.js";
1
+ import { type EspalierUploadImage, type ExistingImage, type ImagePreviewAction } from "./image-helpers.js";
2
2
  import { EspalierElementBase } from "../shared/esp-element-base.js";
3
3
  /**
4
4
  * Used to upload images.
@@ -116,6 +116,66 @@ import { EspalierElementBase } from "../shared/esp-element-base.js";
116
116
  * <esp-image-upload></esp-image-upload>
117
117
  * ```
118
118
  *
119
+ * **Keyboard and touch**
120
+ *
121
+ * Tab reaches each preview's remove button, then its action if `previewAction` is
122
+ * set, and finally Add photos. Enter or Space removes that image and moves focus to
123
+ * Add photos, scrolling it into view if a long album has pushed it off screen.
124
+ *
125
+ * With a mouse, the remove button appears when the pointer is over a preview or
126
+ * focus is inside it. A device without hover (`(hover: none)`) always shows it,
127
+ * because a tap on a hidden button would remove the image with no warning. A
128
+ * touchscreen laptop whose primary pointer has hover keeps the mouse behaviour, so a
129
+ * tap on a photo's empty corner there can still remove it.
130
+ *
131
+ * Each control's accessible name says which image it acts on. A selected image uses
132
+ * its file name, as in `Remove holiday.jpg`. An existing image uses its position, as
133
+ * in `Remove image 3 of 12`, which follows removal and reordering.
134
+ *
135
+ * **Adding an action to each preview**
136
+ *
137
+ * Set `previewAction` to show a labelled icon button in the lower-right of each
138
+ * completed preview, for example to open your own dialog about one image. There
139
+ * is no button by default.
140
+ *
141
+ * - `label` is the tooltip and the start of the accessible name, which continues
142
+ * with the image's file name or position, as in `Edit details: image 3 of 12`.
143
+ * - `icon` is an icon name from the sprite configured on `esp-root`.
144
+ *
145
+ * Existing images offer the button straight away, and selected images once
146
+ * `onComplete` has run. It is hidden while an image uploads, after `onFailed`,
147
+ * after Retry until the next `onComplete`, and while the preview shows that its
148
+ * image failed to load. Activating it never removes the image, opens the file
149
+ * picker or starts a drag.
150
+ *
151
+ * `detail.image` on `esp-image-upload-preview-action` is the object in
152
+ * `uploadedImages` itself, and it stays the same object through reorder and
153
+ * upload completion. An album can hold the same image twice, so keep anything
154
+ * specific to one use against this object, not against `uploadedId` or an index.
155
+ * If your dialog applies a change later, first check that
156
+ * `uploadedImages.includes(image)` is still true.
157
+ *
158
+ * ```html
159
+ * <script>
160
+ * const uploader = findByTagName("esp-image-upload")[0];
161
+ * uploader.previewAction = { label: "Edit details", icon: "edit" };
162
+ * uploader.setExistingImages([
163
+ * { url: "https://picsum.photos/id/29/1200/800", width: 1200, height: 800, uploadedId: "img-1" },
164
+ * { url: "https://picsum.photos/id/15/900/1200", width: 900, height: 1200, uploadedId: "img-2" },
165
+ * ]);
166
+ * uploader.addEventListener("esp-image-upload-file-selected", (e) => {
167
+ * // Stub — replace with your real upload. The button appears on completion.
168
+ * setTimeout(() => e.detail.onComplete("id-" + e.detail.image.file.name), 1500);
169
+ * });
170
+ * uploader.addEventListener("esp-image-upload-preview-action", (e) => {
171
+ * const { image } = e.detail;
172
+ * const name = image.source === "selected" ? image.file.name : image.uploadedId;
173
+ * showToast({ message: "Edit details for " + name, icon: "info-i", duration: 3 });
174
+ * });
175
+ * </script>
176
+ * <esp-image-upload></esp-image-upload>
177
+ * ```
178
+ *
119
179
  * @event {CustomEvent<EspalierUploadImage>} esp-image-upload-file-removed - Fired when
120
180
  * an image has been removed by the user. Narrow on `detail.source` to
121
181
  * distinguish newly selected images from pre-existing server images.
@@ -141,6 +201,13 @@ import { EspalierElementBase } from "../shared/esp-element-base.js";
141
201
  * (`detail.unsupported`) or because they could not be read or decoded
142
202
  * (`detail.unreadable`). The component also shows a transient inline notice.
143
203
  *
204
+ * @event {CustomEvent<ImagePreviewActionDetail>} esp-image-upload-preview-action - Fired
205
+ * once each time the user activates the `previewAction` button on a completed
206
+ * preview, whether by pointer, touch or keyboard. `detail.image` is the object in
207
+ * `uploadedImages` itself, so it identifies one use of an image even when an album
208
+ * holds the same `uploadedId` twice, and it stays the same object through reorder
209
+ * and upload completion.
210
+ *
144
211
  * @cssprop --esp-image-upload-preview-background - The background color of the image preview area.
145
212
  * @docPageTitle Image Upload
146
213
  * @docUrl /components/image-upload
@@ -172,6 +239,16 @@ export declare class EspalierImageUpload extends EspalierElementBase {
172
239
  * @type {number}
173
240
  */
174
241
  maxRowHeightVh: number;
242
+ /**
243
+ * An optional action button in the lower-right of each completed preview,
244
+ * reported through `esp-image-upload-preview-action`. Clear it, or leave it
245
+ * unset, for no button. A blank `label` or an invalid `icon` name also shows
246
+ * none. Assign a new object to change it, since the component does not watch
247
+ * the object's fields.
248
+ *
249
+ * @type {ImagePreviewAction}
250
+ */
251
+ previewAction?: ImagePreviewAction | null;
175
252
  connectedCallback(): void;
176
253
  disconnectedCallback(): void;
177
254
  /**
@@ -1,25 +1,25 @@
1
- var f=function(_,e,t,i){var o=arguments.length,r=o<3?e:i===null?i=Object.getOwnPropertyDescriptor(e,t):i,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(_,e,t,i);else for(var n=_.length-1;n>=0;n--)(d=_[n])&&(r=(o<3?d(r):o>3?d(e,t,r):d(e,t))||r);return o>3&&r&&Object.defineProperty(e,t,r),r},m;import{css as A,html as w}from"lit";import{customElement as R,property as x,state as b}from"lit/decorators.js";import{createRef as I,ref as E}from"lit/directives/ref.js";import"./esp-image-preview.js";import{classMap as P}from"lit/directives/class-map.js";import{getImageDetails as M,releasePreviewUrl as y}from"./image-helpers.js";const U=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1
+ var g=function(_,e,t,i){var o=arguments.length,r=o<3?e:i===null?i=Object.getOwnPropertyDescriptor(e,t):i,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(_,e,t,i);else for(var l=_.length-1;l>=0;l--)(d=_[l])&&(r=(o<3?d(r):o>3?d(e,t,r):d(e,t))||r);return o>3&&r&&Object.defineProperty(e,t,r),r},m;import{css as D,html as b}from"lit";import{customElement as R,property as w,state as x}from"lit/decorators.js";import{createRef as I,ref as E}from"lit/directives/ref.js";import"./esp-image-preview.js";import{classMap as P}from"lit/directives/class-map.js";import{getImageDetails as M,releasePreviewUrl as y}from"./image-helpers.js";const L=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
2
2
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
3
3
  <path d="M11.911 3.634a2 2 0 0 1 1.089 1.78l.001 2.586h6.999a2 2 0 0 1 2 2v4l-.005 .15a2 2 0 0 1 -1.995 1.85l-6.999 -.001l-.001 2.587a2 2 0 0 1 -3.414 1.414l-6.586 -6.586a2 2 0 0 1 0 -2.828l6.586 -6.586a2 2 0 0 1 2.18 -.434l.145 .068z" />
4
- </svg>`,k=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
4
+ </svg>`,U=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
5
5
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
6
6
  <path d="M12.089 3.634a2 2 0 0 0 -1.089 1.78l-.001 2.586h-6.999a2 2 0 0 0 -2 2v4l.005 .15a2 2 0 0 0 1.995 1.85l6.999 -.001l.001 2.587a2 2 0 0 0 3.414 1.414l6.586 -6.586a2 2 0 0 0 0 -2.828l-6.586 -6.586a2 2 0 0 0 -2.18 -.434l-.145 .068z" />
7
- </svg>`;import{EspalierElementBase as D}from"../shared/esp-element-base.js";import{calculateAlbumLayout as C,DEFAULT_ALBUM_MAX_ROW_HEIGHT_VH as L,normalizeAlbumMaxRowHeightVh as O}from"../shared/justified-layout.js";import{ESP_EVENTS as v}from"../shared/events.js";import{viewportSize as H}from"../shared/viewport.js";const S=220,T=4,$=8e3;let c=m=class extends D{constructor(){super(...arguments),this.uploadInput=I(),this.previewsDiv=I(),this.dropAreaDiv=I(),this.draggingOver=!1,this.uploadedImages=[],this.accept="image/jpeg, image/png, image/webp",this.maxRowHeightVh=L,this._rejectionNotice="",this._uploadState=new WeakMap,this._selectionGeneration=0,this._chromeWidth=null,this._resizeObserver=new ResizeObserver(()=>{this._chromeWidth=null,this.requestUpdate()}),this._handleViewportResize=()=>{this._chromeWidth=null,this.requestUpdate()},this._dragPointerId=null,this._dragSourceIndex=null,this._dragOverIndex=null,this._dragStartX=0,this._dragStartY=0,this._dragActive=!1,this._ghostEl=null,this._ghostHalfW=0,this._ghostHalfH=0,this._arrowEl=null,this._cachedPreviews=null,this._lastDropHit=null,this._savedBodyUserSelect="",this._handleDragPointerDown=e=>{if(e.button!==0||this._dragPointerId!==null||e.composedPath().some(o=>o instanceof HTMLElement&&(o.tagName==="BUTTON"||o.tagName==="ESP-BUTTON")))return;const i=this._getPreviewIndex(e);i!==null&&(this._dragPointerId=e.pointerId,this._dragSourceIndex=i,this._dragStartX=e.clientX,this._dragStartY=e.clientY,this._dragActive=!1,document.addEventListener("pointermove",this._onDocPointerMove),document.addEventListener("pointerup",this._onDocPointerUp),document.addEventListener("pointercancel",this._onDocPointerUp))},this._onDocPointerMove=e=>{if(this._dragSourceIndex===null||e.pointerId!==this._dragPointerId)return;const t=e.clientX-this._dragStartX,i=e.clientY-this._dragStartY;if(!this._dragActive){if(Math.sqrt(t*t+i*i)<m._DRAG_THRESHOLD)return;this._dragActive=!0,this._createGhost(e.clientX,e.clientY);const n=this.shadowRoot?.querySelectorAll("esp-image-preview");n&&(this._cachedPreviews=Array.from(n).map(s=>({el:s,rect:s.getBoundingClientRect()})),this._dragSourceIndex!==null&&this._dragSourceIndex<this._cachedPreviews.length&&(this._cachedPreviews[this._dragSourceIndex].el.style.opacity="0.3")),this._savedBodyUserSelect=document.body.style.userSelect,document.body.style.userSelect="none",this.previewsDiv.value&&(this.previewsDiv.value.style.touchAction="none")}this._ghostEl&&(this._ghostEl.style.transform=`translate(${e.clientX-this._ghostHalfW}px, ${e.clientY-this._ghostHalfH}px)`);const o=this._cachedPreviews;if(!o||o.length===0)return;let r=null,d=!1;for(let n=0;n<o.length;n++){const s=o[n].rect;if(e.clientX>=s.left&&e.clientX<=s.right&&e.clientY>=s.top&&e.clientY<=s.bottom){r=n,d=e.clientX>s.left+s.width/2;break}}if(r===null){let n=1/0;for(let s=0;s<o.length;s++){const l=o[s].rect,a=e.clientX-(l.left+l.width/2),h=e.clientY-(l.top+l.height/2),p=a*a+h*h;p<n&&(n=p,r=s)}if(r!==null){const s=o[r].rect;d=e.clientX>s.left+s.width/2}}r!==null&&(this._dragOverIndex=d?r+1:r,!(this._lastDropHit&&this._lastDropHit.index===r&&this._lastDropHit.after===d)&&(this._lastDropHit={index:r,after:d},this._updateDropTargets(o.map(n=>n.el),r,d)))},this._onDocPointerUp=e=>{if(e.pointerId===this._dragPointerId){if(this._dragActive&&this._dragSourceIndex!==null&&this._dragOverIndex!==null&&this._dragSourceIndex!==this._dragOverIndex&&this._dragSourceIndex+1!==this._dragOverIndex){const t=[...this.uploadedImages],[i]=t.splice(this._dragSourceIndex,1),o=this._dragOverIndex>this._dragSourceIndex?this._dragOverIndex-1:this._dragOverIndex;t.splice(o,0,i),this.uploadedImages=t,this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_IMAGES_REORDERED,{detail:{images:this.uploadedImages},bubbles:!0,composed:!0}))}this._clearDragState()}},this._arrowColor=null,this.filesSelected=async e=>{const t=[],i=[];for(const a of e)(this._isAccepted(a)?t:i).push(a);if(!t.length){i.length&&this._reportRejectedFiles({unsupported:i,unreadable:[]});return}const o=this._selectionGeneration,r=Math.round(S*Math.min(globalThis.devicePixelRatio||1,2)),d=new Array(t.length).fill(null),n=[];let s=0;const l=async()=>{for(;s<t.length;){const a=s++,h=t[a];try{const p=await M(h,{thumbnailHeight:r});if(o!==this._selectionGeneration){y(p);continue}this._addSelectedImage(d,a,p)}catch{n.push(h)}}};await Promise.all(Array.from({length:Math.min(T,t.length)},()=>l())),(i.length||n.length)&&o===this._selectionGeneration&&this._reportRejectedFiles({unsupported:i,unreadable:n})},this._makeCallbacks=e=>({onProgress:t=>{const i=this._uploadState.get(e);i&&(i.progress=t,i.failed=!1,this.requestUpdate())},onComplete:t=>{if(!this._uploadState.get(e))return;e.uploadedId=t,this._uploadState.delete(e),!this.uploadedImages.find(r=>!r.uploadedId)?this.uploadedImages=[...this.uploadedImages]:this.requestUpdate()},onFailed:()=>{const t=this._uploadState.get(e);t&&(t.progress=void 0,t.failed=!0,this.requestUpdate())}}),this._fullPreviewUrls=new Map,this.setExistingImages=e=>{this._selectionGeneration++,this._releaseSelectedImages(),this.uploadedImages=e.filter(t=>t.url&&t.uploadedId&&Number.isFinite(t.width)&&t.width>0&&Number.isFinite(t.height)&&t.height>0).map(t=>({source:"existing",url:t.url,urls:t.urls,height:t.height,width:t.width,uploadedId:t.uploadedId,orientation:t.width>t.height?"landscape":"portrait"})),this._uploadState=new WeakMap}}connectedCallback(){super.connectedCallback(),this._resizeObserver.observe(this),window.addEventListener("resize",this._handleViewportResize)}disconnectedCallback(){super.disconnectedCallback(),this._resizeObserver.disconnect(),window.removeEventListener("resize",this._handleViewportResize),this._clearDragState(),clearTimeout(this._noticeTimer),this._selectionGeneration++,this._releaseSelectedImages()}_getPreviewIndex(e){const t=this.shadowRoot?.querySelectorAll("esp-image-preview");if(!t)return null;for(const i of e.composedPath())if(i instanceof HTMLElement&&i.tagName==="ESP-IMAGE-PREVIEW"){for(let o=0;o<t.length;o++)if(t[o]===i)return o}return null}_clearDragState(){document.removeEventListener("pointermove",this._onDocPointerMove),document.removeEventListener("pointerup",this._onDocPointerUp),document.removeEventListener("pointercancel",this._onDocPointerUp),this._dragActive&&(this._cachedPreviews&&this._dragSourceIndex!==null&&this._dragSourceIndex<this._cachedPreviews.length&&(this._cachedPreviews[this._dragSourceIndex].el.style.opacity=""),this._clearDropTargets(),document.body.style.userSelect=this._savedBodyUserSelect,this.previewsDiv.value&&(this.previewsDiv.value.style.touchAction="")),this._ghostEl?.remove(),this._ghostEl=null,this._cachedPreviews=null,this._lastDropHit=null,this._dragPointerId=null,this._dragSourceIndex=null,this._dragOverIndex=null,this._dragActive=!1}_createGhost(e,t){const i=this.shadowRoot?.querySelectorAll("esp-image-preview");if(!i||this._dragSourceIndex===null)return;const o=i[this._dragSourceIndex],r=o.getBoundingClientRect(),d=document.createElement("div"),n=Math.min(120/r.width,120/r.height),s=r.width*n,l=r.height*n;d.style.cssText=`
7
+ </svg>`;import{EspalierElementBase as A}from"../shared/esp-element-base.js";import{calculateAlbumLayout as C,DEFAULT_ALBUM_MAX_ROW_HEIGHT_VH as k,normalizeAlbumMaxRowHeightVh as O}from"../shared/justified-layout.js";import{ESP_EVENTS as v}from"../shared/events.js";import{viewportSize as H}from"../shared/viewport.js";const S=220,T=4,$=8e3;let p=m=class extends A{constructor(){super(...arguments),this.uploadInput=I(),this.previewsDiv=I(),this.dropAreaDiv=I(),this.draggingOver=!1,this.uploadedImages=[],this.accept="image/jpeg, image/png, image/webp",this.maxRowHeightVh=k,this._rejectionNotice="",this._uploadState=new WeakMap,this._selectionGeneration=0,this._chromeWidth=null,this._resizeObserver=new ResizeObserver(()=>{this._chromeWidth=null,this.requestUpdate()}),this._handleViewportResize=()=>{this._chromeWidth=null,this.requestUpdate()},this._dragPointerId=null,this._dragSourceIndex=null,this._dragOverIndex=null,this._dragStartX=0,this._dragStartY=0,this._dragActive=!1,this._ghostEl=null,this._ghostHalfW=0,this._ghostHalfH=0,this._arrowEl=null,this._cachedPreviews=null,this._lastDropHit=null,this._savedBodyUserSelect="",this._handleDragPointerDown=e=>{if(e.button!==0||this._dragPointerId!==null||e.composedPath().some(o=>o instanceof HTMLElement&&(o.tagName==="BUTTON"||o.tagName==="ESP-BUTTON")))return;const i=this._getPreviewIndex(e);i!==null&&(this._dragPointerId=e.pointerId,this._dragSourceIndex=i,this._dragStartX=e.clientX,this._dragStartY=e.clientY,this._dragActive=!1,document.addEventListener("pointermove",this._onDocPointerMove),document.addEventListener("pointerup",this._onDocPointerUp),document.addEventListener("pointercancel",this._onDocPointerUp))},this._onDocPointerMove=e=>{if(this._dragSourceIndex===null||e.pointerId!==this._dragPointerId)return;const t=e.clientX-this._dragStartX,i=e.clientY-this._dragStartY;if(!this._dragActive){if(Math.sqrt(t*t+i*i)<m._DRAG_THRESHOLD)return;this._dragActive=!0,this._createGhost(e.clientX,e.clientY);const l=this.shadowRoot?.querySelectorAll("esp-image-preview");l&&(this._cachedPreviews=Array.from(l).map(s=>({el:s,rect:s.getBoundingClientRect()})),this._dragSourceIndex!==null&&this._dragSourceIndex<this._cachedPreviews.length&&(this._cachedPreviews[this._dragSourceIndex].el.style.opacity="0.3")),this._savedBodyUserSelect=document.body.style.userSelect,document.body.style.userSelect="none",this.previewsDiv.value&&(this.previewsDiv.value.style.touchAction="none")}this._ghostEl&&(this._ghostEl.style.transform=`translate(${e.clientX-this._ghostHalfW}px, ${e.clientY-this._ghostHalfH}px)`);const o=this._cachedPreviews;if(!o||o.length===0)return;let r=null,d=!1;for(let l=0;l<o.length;l++){const s=o[l].rect;if(e.clientX>=s.left&&e.clientX<=s.right&&e.clientY>=s.top&&e.clientY<=s.bottom){r=l,d=e.clientX>s.left+s.width/2;break}}if(r===null){let l=1/0;for(let s=0;s<o.length;s++){const n=o[s].rect,a=e.clientX-(n.left+n.width/2),h=e.clientY-(n.top+n.height/2),c=a*a+h*h;c<l&&(l=c,r=s)}if(r!==null){const s=o[r].rect;d=e.clientX>s.left+s.width/2}}r!==null&&(this._dragOverIndex=d?r+1:r,!(this._lastDropHit&&this._lastDropHit.index===r&&this._lastDropHit.after===d)&&(this._lastDropHit={index:r,after:d},this._updateDropTargets(o.map(l=>l.el),r,d)))},this._onDocPointerUp=e=>{if(e.pointerId===this._dragPointerId){if(this._dragActive&&this._dragSourceIndex!==null&&this._dragOverIndex!==null&&this._dragSourceIndex!==this._dragOverIndex&&this._dragSourceIndex+1!==this._dragOverIndex){const t=[...this.uploadedImages],[i]=t.splice(this._dragSourceIndex,1),o=this._dragOverIndex>this._dragSourceIndex?this._dragOverIndex-1:this._dragOverIndex;t.splice(o,0,i),this.uploadedImages=t,this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_IMAGES_REORDERED,{detail:{images:this.uploadedImages},bubbles:!0,composed:!0}))}this._clearDragState()}},this._arrowColor=null,this.filesSelected=async e=>{const t=[],i=[];for(const a of e)(this._isAccepted(a)?t:i).push(a);if(!t.length){i.length&&this._reportRejectedFiles({unsupported:i,unreadable:[]});return}const o=this._selectionGeneration,r=Math.round(S*Math.min(globalThis.devicePixelRatio||1,2)),d=new Array(t.length).fill(null),l=[];let s=0;const n=async()=>{for(;s<t.length;){const a=s++,h=t[a];try{const c=await M(h,{thumbnailHeight:r});if(o!==this._selectionGeneration){y(c);continue}this._addSelectedImage(d,a,c)}catch{l.push(h)}}};await Promise.all(Array.from({length:Math.min(T,t.length)},()=>n())),(i.length||l.length)&&o===this._selectionGeneration&&this._reportRejectedFiles({unsupported:i,unreadable:l})},this._makeCallbacks=e=>({onProgress:t=>{const i=this._uploadState.get(e);i&&(i.progress=t,i.failed=!1,this.requestUpdate())},onComplete:t=>{if(!this._uploadState.get(e))return;e.uploadedId=t,this._uploadState.delete(e),!this.uploadedImages.find(r=>!r.uploadedId)?this.uploadedImages=[...this.uploadedImages]:this.requestUpdate()},onFailed:()=>{const t=this._uploadState.get(e);t&&(t.progress=void 0,t.failed=!0,this.requestUpdate())}}),this._fullPreviewUrls=new Map,this.setExistingImages=e=>{this._selectionGeneration++,this._releaseSelectedImages(),this.uploadedImages=e.filter(t=>t.url&&t.uploadedId&&Number.isFinite(t.width)&&t.width>0&&Number.isFinite(t.height)&&t.height>0).map(t=>({source:"existing",url:t.url,urls:t.urls,height:t.height,width:t.width,uploadedId:t.uploadedId,orientation:t.width>t.height?"landscape":"portrait"})),this._uploadState=new WeakMap}}connectedCallback(){super.connectedCallback(),this._resizeObserver.observe(this),window.addEventListener("resize",this._handleViewportResize)}disconnectedCallback(){super.disconnectedCallback(),this._resizeObserver.disconnect(),window.removeEventListener("resize",this._handleViewportResize),this._clearDragState(),clearTimeout(this._noticeTimer),this._selectionGeneration++,this._releaseSelectedImages()}_getPreviewIndex(e){const t=this.shadowRoot?.querySelectorAll("esp-image-preview");if(!t)return null;for(const i of e.composedPath())if(i instanceof HTMLElement&&i.tagName==="ESP-IMAGE-PREVIEW"){for(let o=0;o<t.length;o++)if(t[o]===i)return o}return null}_clearDragState(){document.removeEventListener("pointermove",this._onDocPointerMove),document.removeEventListener("pointerup",this._onDocPointerUp),document.removeEventListener("pointercancel",this._onDocPointerUp),this._dragActive&&(this._cachedPreviews&&this._dragSourceIndex!==null&&this._dragSourceIndex<this._cachedPreviews.length&&(this._cachedPreviews[this._dragSourceIndex].el.style.opacity=""),this._clearDropTargets(),document.body.style.userSelect=this._savedBodyUserSelect,this.previewsDiv.value&&(this.previewsDiv.value.style.touchAction="")),this._ghostEl?.remove(),this._ghostEl=null,this._cachedPreviews=null,this._lastDropHit=null,this._dragPointerId=null,this._dragSourceIndex=null,this._dragOverIndex=null,this._dragActive=!1}_createGhost(e,t){const i=this.shadowRoot?.querySelectorAll("esp-image-preview");if(!i||this._dragSourceIndex===null)return;const o=i[this._dragSourceIndex],r=o.getBoundingClientRect(),d=document.createElement("div"),l=Math.min(120/r.width,120/r.height),s=r.width*l,n=r.height*l;d.style.cssText=`
8
8
  position: fixed;
9
9
  left: 0;
10
10
  top: 0;
11
11
  z-index: 10001;
12
12
  pointer-events: none;
13
13
  width: ${s}px;
14
- height: ${l}px;
14
+ height: ${n}px;
15
15
  border: 2px dashed var(--esp-color-action-background, #4aa);
16
16
  border-radius: var(--esp-size-border-radius, 4px);
17
17
  background-size: cover;
18
18
  background-position: center;
19
19
  opacity: 0.85;
20
20
  will-change: transform;
21
- transform: translate(${e-s/2}px, ${t-l/2}px);
22
- `;const a=o.shadowRoot?.querySelector("img");a&&(d.style.backgroundImage=`url(${a.src})`),document.body.appendChild(d),this._ghostEl=d,this._ghostHalfW=s/2,this._ghostHalfH=l/2}_updateDropTargets(e,t,i){for(let a=0;a<e.length;a++){const h=e[a];a===t&&a!==this._dragSourceIndex?h.setAttribute("data-drop-side",i?"right":"left"):h.removeAttribute("data-drop-side")}if(t===this._dragSourceIndex){this._arrowEl&&(this._arrowEl.style.display="none");return}const o=this._cachedPreviews,r=o?o[t].rect:e[t].getBoundingClientRect(),d=i?k:U;if(!this._arrowEl){const a=document.createElement("div");a.style.cssText=`
21
+ transform: translate(${e-s/2}px, ${t-n/2}px);
22
+ `;const a=o.shadowRoot?.querySelector("img");a&&(d.style.backgroundImage=`url(${a.src})`),document.body.appendChild(d),this._ghostEl=d,this._ghostHalfW=s/2,this._ghostHalfH=n/2}_updateDropTargets(e,t,i){for(let a=0;a<e.length;a++){const h=e[a];a===t&&a!==this._dragSourceIndex?h.setAttribute("data-drop-side",i?"right":"left"):h.removeAttribute("data-drop-side")}if(t===this._dragSourceIndex){this._arrowEl&&(this._arrowEl.style.display="none");return}const o=this._cachedPreviews,r=o?o[t].rect:e[t].getBoundingClientRect(),d=i?U:L;if(!this._arrowEl){const a=document.createElement("div");a.style.cssText=`
23
23
  position: fixed;
24
24
  left: 0;
25
25
  top: 0;
@@ -30,27 +30,30 @@ var f=function(_,e,t,i){var o=arguments.length,r=o<3?e:i===null?i=Object.getOwnP
30
30
  justify-content: center;
31
31
  will-change: transform;
32
32
  filter: drop-shadow(0 1px 3px rgba(0,0,0,0.4));
33
- `,document.body.appendChild(a),this._arrowEl=a;const h=e[t],u=getComputedStyle(h).getPropertyValue("--esp-color-complementary").trim();this._arrowColor=u?`oklch(from ${u} var(--esp-l-accent) c h)`:"oklch(0.7 0.2 330)"}this._arrowEl.innerHTML=d;const n=this._arrowEl.querySelector("svg");n&&(n.style.width="40px",n.style.height="40px",n.style.color=this._arrowColor??"oklch(0.7 0.2 330)"),this._arrowEl.style.display="flex";const s=i?r.left+r.width*.75:r.left+r.width*.25,l=r.top+r.height/2;this._arrowEl.style.transform=`translate(${s-20}px, ${l-20}px)`}_clearDropTargets(){const e=this.shadowRoot?.querySelectorAll("esp-image-preview");if(e)for(const t of e)t.removeAttribute("data-drop-side");this._arrowEl?.remove(),this._arrowEl=null,this._arrowColor=null}getContainerWidth(){const e=this.parentElement??this.offsetParent,t=e?e.getBoundingClientRect().width:window.innerWidth;if(t<=0){const i=window.innerWidth;return i<640?i-32:i<1024?i*90/100-32:Math.min(i*85/100-32,1400)}if(this._chromeWidth===null){const i=this.previewsDiv.value;if(i){const o=l=>{const a=parseFloat(l);return Number.isFinite(a)?a:0},r=getComputedStyle(i),d=o(r.paddingLeft)+o(r.paddingRight),n=this.shadowRoot?.querySelector(".esp-field"),s=n?o(getComputedStyle(n).borderLeftWidth)+o(getComputedStyle(n).borderRightWidth):0;this._chromeWidth=d+s}}return Math.max(t-(this._chromeWidth??0),1)}_isAccepted(e){const t=this.accept.split(",").map(r=>r.trim().toLowerCase()).filter(Boolean);if(!t.length)return e.type.toLowerCase().startsWith("image/");const i=e.type.toLowerCase(),o=e.name.toLowerCase();return t.some(r=>r.startsWith(".")?o.endsWith(r):r.endsWith("/*")?i.startsWith(r.slice(0,-1)):i===r)}_addSelectedImage(e,t,i){e[t]=i;const o=[...this.uploadedImages];let r=-1;for(let n=t-1;n>=0&&r<0;n--){const s=e[n];if(!s)continue;const l=o.indexOf(s);l>=0&&(r=l+1)}for(let n=t+1;n<e.length&&r<0;n++){const s=e[n];if(!s)continue;const l=o.indexOf(s);l>=0&&(r=l)}r<0&&(r=o.length),o.splice(r,0,i);const d=new AbortController;this._uploadState.set(i,{progress:null,failed:!1,controller:d}),this.uploadedImages=o,this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_FILE_SELECTED,{detail:{image:i,signal:d.signal,...this._makeCallbacks(i)},bubbles:!0,composed:!0}))}_reportRejectedFiles(e){this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_FILES_REJECTED,{detail:e,bubbles:!0,composed:!0}));const t=o=>o===1?"file":"files",i=[];e.unsupported.length&&i.push(`${e.unsupported.length} unsupported ${t(e.unsupported.length)} skipped`),e.unreadable.length&&i.push(`${e.unreadable.length} ${t(e.unreadable.length)} could not be read`),this._rejectionNotice=i.join("; "),clearTimeout(this._noticeTimer),this._noticeTimer=setTimeout(()=>{this._rejectionNotice=""},$)}_previewUrlFor(e,t,i){const o=e.width>0&&e.height>0?e.width/e.height:1,r=Math.max(t,(i??0)/o);if(e.source!=="selected")return this._pickExistingPreviewUrl(e,r);const d=Math.min(globalThis.devicePixelRatio||1,2),n=S*d;if(r*d<=n*m._THUMBNAIL_UPSCALE_SLACK||e.height<=n)return e.url;let a=this._fullPreviewUrls.get(e);return a||(a=URL.createObjectURL(e.file),this._fullPreviewUrls.set(e,a)),a}_pickExistingPreviewUrl(e,t){const i=e.urls;if(!i?.length)return e.url;const o=Math.min(globalThis.devicePixelRatio||1,2),r=e.height>0?e.width/e.height:1,d=t*r*o,n=[...i].sort((l,a)=>l.minWidth-a.minWidth);return(n.find(l=>l.minWidth>=d)??n[n.length-1]).url}_releaseFullPreviewUrl(e){if(e.source!=="selected")return;const t=this._fullPreviewUrls.get(e);t&&(URL.revokeObjectURL(t),this._fullPreviewUrls.delete(e))}_releaseSelectedImages(){for(const e of this.uploadedImages)e.source==="selected"&&(this._uploadState.get(e)?.controller.abort(),y(e));for(const e of this._fullPreviewUrls.values())URL.revokeObjectURL(e);this._fullPreviewUrls.clear()}render(){const{draggingOver:e,uploadedImages:t}=this,i={"dragging-over":e,"has-previews":t.length},o=this.getContainerWidth(),{height:r}=H(),d=r>0?r*O(this.maxRowHeightVh)/100:Number.POSITIVE_INFINITY,n=C(t,{containerWidth:o,targetRowHeight:S,gap:8,maxRowHeight:d,maxImagesPerRow:this.maxImagesPerRow});return w` <div
33
+ `,document.body.appendChild(a),this._arrowEl=a;const h=e[t],u=getComputedStyle(h).getPropertyValue("--esp-color-complementary").trim();this._arrowColor=u?`oklch(from ${u} var(--esp-l-accent) c h)`:"oklch(0.7 0.2 330)"}this._arrowEl.innerHTML=d;const l=this._arrowEl.querySelector("svg");l&&(l.style.width="40px",l.style.height="40px",l.style.color=this._arrowColor??"oklch(0.7 0.2 330)"),this._arrowEl.style.display="flex";const s=i?r.left+r.width*.75:r.left+r.width*.25,n=r.top+r.height/2;this._arrowEl.style.transform=`translate(${s-20}px, ${n-20}px)`}_clearDropTargets(){const e=this.shadowRoot?.querySelectorAll("esp-image-preview");if(e)for(const t of e)t.removeAttribute("data-drop-side");this._arrowEl?.remove(),this._arrowEl=null,this._arrowColor=null}getContainerWidth(){const e=this.parentElement??this.offsetParent,t=e?e.getBoundingClientRect().width:window.innerWidth;if(t<=0){const i=window.innerWidth;return i<640?i-32:i<1024?i*90/100-32:Math.min(i*85/100-32,1400)}if(this._chromeWidth===null){const i=this.previewsDiv.value;if(i){const o=n=>{const a=parseFloat(n);return Number.isFinite(a)?a:0},r=getComputedStyle(i),d=o(r.paddingLeft)+o(r.paddingRight),l=this.shadowRoot?.querySelector(".esp-field"),s=l?o(getComputedStyle(l).borderLeftWidth)+o(getComputedStyle(l).borderRightWidth):0;this._chromeWidth=d+s}}return Math.max(t-(this._chromeWidth??0),1)}_isAccepted(e){const t=this.accept.split(",").map(r=>r.trim().toLowerCase()).filter(Boolean);if(!t.length)return e.type.toLowerCase().startsWith("image/");const i=e.type.toLowerCase(),o=e.name.toLowerCase();return t.some(r=>r.startsWith(".")?o.endsWith(r):r.endsWith("/*")?i.startsWith(r.slice(0,-1)):i===r)}_addSelectedImage(e,t,i){e[t]=i;const o=[...this.uploadedImages];let r=-1;for(let l=t-1;l>=0&&r<0;l--){const s=e[l];if(!s)continue;const n=o.indexOf(s);n>=0&&(r=n+1)}for(let l=t+1;l<e.length&&r<0;l++){const s=e[l];if(!s)continue;const n=o.indexOf(s);n>=0&&(r=n)}r<0&&(r=o.length),o.splice(r,0,i);const d=new AbortController;this._uploadState.set(i,{progress:null,failed:!1,controller:d}),this.uploadedImages=o,this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_FILE_SELECTED,{detail:{image:i,signal:d.signal,...this._makeCallbacks(i)},bubbles:!0,composed:!0}))}_reportRejectedFiles(e){this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_FILES_REJECTED,{detail:e,bubbles:!0,composed:!0}));const t=o=>o===1?"file":"files",i=[];e.unsupported.length&&i.push(`${e.unsupported.length} unsupported ${t(e.unsupported.length)} skipped`),e.unreadable.length&&i.push(`${e.unreadable.length} ${t(e.unreadable.length)} could not be read`),this._rejectionNotice=i.join("; "),clearTimeout(this._noticeTimer),this._noticeTimer=setTimeout(()=>{this._rejectionNotice=""},$)}_emitPreviewAction(e){!this.uploadedImages.includes(e)||this._uploadState.has(e)||this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_PREVIEW_ACTION,{detail:{image:e},bubbles:!0,composed:!0}))}_previewUrlFor(e,t,i){const o=e.width>0&&e.height>0?e.width/e.height:1,r=Math.max(t,(i??0)/o);if(e.source!=="selected")return this._pickExistingPreviewUrl(e,r);const d=Math.min(globalThis.devicePixelRatio||1,2),l=S*d;if(r*d<=l*m._THUMBNAIL_UPSCALE_SLACK||e.height<=l)return e.url;let a=this._fullPreviewUrls.get(e);return a||(a=URL.createObjectURL(e.file),this._fullPreviewUrls.set(e,a)),a}_pickExistingPreviewUrl(e,t){const i=e.urls;if(!i?.length)return e.url;const o=Math.min(globalThis.devicePixelRatio||1,2),r=e.height>0?e.width/e.height:1,d=t*r*o,l=[...i].sort((n,a)=>n.minWidth-a.minWidth);return(l.find(n=>n.minWidth>=d)??l[l.length-1]).url}_releaseFullPreviewUrl(e){if(e.source!=="selected")return;const t=this._fullPreviewUrls.get(e);t&&(URL.revokeObjectURL(t),this._fullPreviewUrls.delete(e))}_releaseSelectedImages(){for(const e of this.uploadedImages)e.source==="selected"&&(this._uploadState.get(e)?.controller.abort(),y(e));for(const e of this._fullPreviewUrls.values())URL.revokeObjectURL(e);this._fullPreviewUrls.clear()}render(){const{draggingOver:e,uploadedImages:t}=this,i={"dragging-over":e,"has-previews":t.length},o=this.getContainerWidth(),{height:r}=H(),d=r>0?r*O(this.maxRowHeightVh)/100:Number.POSITIVE_INFINITY,l=C(t,{containerWidth:o,targetRowHeight:S,gap:8,maxRowHeight:d,maxImagesPerRow:this.maxImagesPerRow});return b` <div
34
34
  class="esp-field"
35
- @click=${()=>{this.dropAreaDiv.value?.focus({preventScroll:!0})}}
35
+ @click=${s=>{const n=s.composedPath();if(n.some(c=>c instanceof HTMLElement&&c.hasAttribute("data-preview-action")))return;const h=s.detail===0&&n.some(c=>c instanceof HTMLElement&&c.localName==="esp-image-preview");this.dropAreaDiv.value?.focus({preventScroll:!h})}}
36
36
  @dragover=${s=>{s.preventDefault(),this.draggingOver=!0}}
37
37
  @dragleave=${s=>{s.preventDefault(),this.draggingOver=!1}}
38
- @drop=${s=>{s.preventDefault(),this.draggingOver=!1;const l=s.dataTransfer?.files;l&&l.length&&this.filesSelected(l)}}
38
+ @drop=${s=>{s.preventDefault(),this.draggingOver=!1;const n=s.dataTransfer?.files;n&&n.length&&this.filesSelected(n)}}
39
39
  >
40
40
  <div
41
41
  ${E(this.previewsDiv)}
42
42
  class=${P({previews:!0,...i})}
43
43
  @pointerdown=${this._handleDragPointerDown}
44
44
  >
45
- ${n.map(s=>w`<div class="photo-row" style="height: ${s.height}px;">
46
- ${s.items.map(({image:l,width:a})=>{const h=s.height,p=this._uploadState.get(l);return w`<esp-image-preview
45
+ ${l.map(s=>b`<div class="photo-row" style="height: ${s.height}px;">
46
+ ${s.items.map(({image:n,width:a})=>{const h=s.height,c=this._uploadState.get(n);return b`<esp-image-preview
47
47
  style="width: ${a}px; height: ${h}px; flex-shrink: 0;"
48
- .url=${this._previewUrlFor(l,h,a)}
49
- .alt=${l.source==="selected"?l.file.name:""}
50
- .progress=${p?.progress}
51
- .failed=${p?.failed??!1}
52
- @esp-internal-image-preview-remove=${()=>{const u=this.uploadedImages.indexOf(l);if(u<0)return;this._uploadState.get(l)?.controller.abort(),this._uploadState.delete(l),y(l),this._releaseFullPreviewUrl(l);const g=[...this.uploadedImages];g.splice(u,1),this.uploadedImages=g,this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_FILE_REMOVED,{detail:l,bubbles:!0,composed:!0}))}}
53
- @esp-internal-image-preview-retry=${()=>{if(l.source!=="selected")return;const u=new AbortController,g=this._uploadState.get(l);g?(g.failed=!1,g.progress=null,g.controller=u):this._uploadState.set(l,{progress:null,failed:!1,controller:u}),this.requestUpdate(),this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_RETRY,{detail:{image:l,signal:u.signal,...this._makeCallbacks(l)},bubbles:!0,composed:!0}))}}
48
+ .url=${this._previewUrlFor(n,h,a)}
49
+ .alt=${n.source==="selected"?n.file.name:""}
50
+ .positionLabel=${`image ${t.indexOf(n)+1} of ${t.length}`}
51
+ .progress=${c?.progress}
52
+ .failed=${c?.failed??!1}
53
+ .action=${this.previewAction}
54
+ @esp-internal-image-preview-action=${()=>this._emitPreviewAction(n)}
55
+ @esp-internal-image-preview-remove=${()=>{const u=this.uploadedImages.indexOf(n);if(u<0)return;this._uploadState.get(n)?.controller.abort(),this._uploadState.delete(n),y(n),this._releaseFullPreviewUrl(n);const f=[...this.uploadedImages];f.splice(u,1),this.uploadedImages=f,this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_FILE_REMOVED,{detail:n,bubbles:!0,composed:!0}))}}
56
+ @esp-internal-image-preview-retry=${()=>{if(n.source!=="selected")return;const u=new AbortController,f=this._uploadState.get(n);f?(f.failed=!1,f.progress=null,f.controller=u):this._uploadState.set(n,{progress:null,failed:!1,controller:u}),this.requestUpdate(),this.dispatchEvent(new CustomEvent(v.IMAGE_UPLOAD_RETRY,{detail:{image:n,signal:u.signal,...this._makeCallbacks(n)},bubbles:!0,composed:!0}))}}
54
57
  ></esp-image-preview>`})}
55
58
  </div>`)}
56
59
  </div>
@@ -61,7 +64,7 @@ var f=function(_,e,t,i){var o=arguments.length,r=o<3?e:i===null?i=Object.getOwnP
61
64
  aria-label="Add photos"
62
65
  class=${P({"drop-area":!0,...i})}
63
66
  @click=${()=>{this.uploadInput.value?.click()}}
64
- @keydown=${s=>{(s.code==="Enter"||s.code==="Space")&&(s.preventDefault(),this.uploadInput.value?.click())}}
67
+ @keydown=${s=>{(s.code==="Enter"||s.code==="Space")&&(s.preventDefault(),s.repeat||this.uploadInput.value?.click())}}
65
68
  >
66
69
  <svg
67
70
  xmlns="http://www.w3.org/2000/svg"
@@ -111,7 +114,7 @@ var f=function(_,e,t,i){var o=arguments.length,r=o<3?e:i===null?i=Object.getOwnP
111
114
  hidden
112
115
  @change=${()=>{const s=this.uploadInput.value;!s||!s.files||!s.files.length||(this.filesSelected(s.files),s.value="")}}
113
116
  />
114
- </div>`}};c._DRAG_THRESHOLD=8,c._THUMBNAIL_UPSCALE_SLACK=1.1,c.styles=[...D.styles,A`
117
+ </div>`}};p._DRAG_THRESHOLD=8,p._THUMBNAIL_UPSCALE_SLACK=1.1,p.styles=[...A.styles,D`
115
118
  :host {
116
119
  overflow: hidden;
117
120
  }
@@ -238,4 +241,4 @@ var f=function(_,e,t,i){var o=arguments.length,r=o<3?e:i===null?i=Object.getOwnP
238
241
  }
239
242
  }
240
243
  }
241
- `],f([b()],c.prototype,"draggingOver",void 0),f([b()],c.prototype,"uploadedImages",void 0),f([x({type:String})],c.prototype,"accept",void 0),f([x({attribute:"max-images-per-row",type:Number})],c.prototype,"maxImagesPerRow",void 0),f([x({attribute:"max-row-height-vh",type:Number})],c.prototype,"maxRowHeightVh",void 0),f([b()],c.prototype,"_rejectionNotice",void 0),c=m=f([R("esp-image-upload")],c);export{c as EspalierImageUpload};
244
+ `],g([x()],p.prototype,"draggingOver",void 0),g([x()],p.prototype,"uploadedImages",void 0),g([w({type:String})],p.prototype,"accept",void 0),g([w({attribute:"max-images-per-row",type:Number})],p.prototype,"maxImagesPerRow",void 0),g([w({attribute:"max-row-height-vh",type:Number})],p.prototype,"maxRowHeightVh",void 0),g([w({attribute:!1})],p.prototype,"previewAction",void 0),g([x()],p.prototype,"_rejectionNotice",void 0),p=m=g([R("esp-image-upload")],p);export{p as EspalierImageUpload};
@@ -31,6 +31,16 @@ export type ExistingUploadImage = UploadImageBase & {
31
31
  * Narrow on `source` to access variant-specific fields.
32
32
  */
33
33
  export type EspalierUploadImage = SelectedUploadImage | ExistingUploadImage;
34
+ /**
35
+ * Configures the optional action button on each completed preview of
36
+ * `esp-image-upload`. Assign a new object to change it.
37
+ */
38
+ export interface ImagePreviewAction {
39
+ /** Tooltip text and accessible name of the button. */
40
+ label: string;
41
+ /** Icon name from the sprite configured on the surrounding `esp-root`. */
42
+ icon: string;
43
+ }
34
44
  /** Callbacks attached to `esp-image-upload-file-selected` and `esp-image-upload-retry` event details. */
35
45
  export interface UploadCallbacks {
36
46
  /** Update the progress overlay (0–100 determinate, `null` for indeterminate). */
package/dist/index.d.ts CHANGED
@@ -72,7 +72,7 @@ export { showFlyout, closeFlyout, type FlyoutConfig, type FlyoutCloseReason, } f
72
72
  export { requestHelp, type HelpRequest, type HelpState } from "./shared/help-events.js";
73
73
  export { getEspBus, type EspBusEventMap, type SchemeEvents, type ToastEvents, type FlyoutEvents, type HelpEvents, type PopoverEvents, type SizeEvents, type PageEventMap, type SeedColorRoot, } from "./shared/bus-events.js";
74
74
  export * from "./shared/events.js";
75
- export { getImageDetails, releasePreviewUrl, type EspalierUploadImage, type ImageDetailsOptions, type SelectedUploadImage, type ExistingUploadImage, type ExistingImage, type ResponsiveImageUrl, type UploadCallbacks, type UploadEventDetail, } from "./image-upload/image-helpers.js";
75
+ export { getImageDetails, releasePreviewUrl, type EspalierUploadImage, type ImageDetailsOptions, type ImagePreviewAction, type SelectedUploadImage, type ExistingUploadImage, type ExistingImage, type ResponsiveImageUrl, type UploadCallbacks, type UploadEventDetail, } from "./image-upload/image-helpers.js";
76
76
  export { calculateAlbumLayout, DEFAULT_ALBUM_MAX_ROW_HEIGHT_VH, normalizeAlbumMaxRowHeightVh, normalizeMaxImagesPerRow, type AlbumLayoutItem, type AlbumLayoutOptions, type AlbumLayoutRow, type LayoutImage, } from "./shared/justified-layout.js";
77
77
  export { type TypeaheadFetchItems } from "./pickers/types.js";
78
78
  export { type EspalierTheme, type LightnessKey, type LightnessReference, type PartialTheme, type PartialThemeContexts, type PartialThemeTones, type ThemeContext, type ThemeContexts, type ThemeTones, type ToneReference, type VariantColorSource, encodeTheme, parseTheme, mergePartials, layerThemes, validateThemePair, resolveContextTheme, isObjectRecord, isSemanticColorName, buildTaprootLightTheme, buildTaprootDarkTheme, NESTED_THEME_KEYS, } from "./shared/theme.js";
@@ -94,6 +94,7 @@ export declare const ESP_EVENTS: {
94
94
  readonly IMAGE_UPLOAD_FILES_REJECTED: "esp-image-upload-files-rejected";
95
95
  readonly IMAGE_UPLOAD_RETRY: "esp-image-upload-retry";
96
96
  readonly IMAGE_UPLOAD_IMAGES_REORDERED: "esp-image-upload-images-reordered";
97
+ readonly IMAGE_UPLOAD_PREVIEW_ACTION: "esp-image-upload-preview-action";
97
98
  readonly INFO_DESTROY: "esp-info-destroy";
98
99
  readonly INPUT_ICON_CLICKED: "esp-input-icon-clicked";
99
100
  readonly LIGHTBOX_CHANGED: "esp-lightbox-changed";
@@ -406,6 +407,21 @@ export interface FilesRejectedDetail {
406
407
  /** Files skipped because they could not be read or decoded. */
407
408
  unreadable: File[];
408
409
  }
410
+ /**
411
+ * Detail for `esp-image-upload-preview-action` on `esp-image-upload`.
412
+ *
413
+ * @docUrl /api/image-preview-action-detail
414
+ * @menuGroup Event Details
415
+ * @menuLabel ImagePreviewActionDetail
416
+ */
417
+ export interface ImagePreviewActionDetail {
418
+ /**
419
+ * The object in `uploadedImages` itself. An album can hold the same server
420
+ * image twice, so this reference, not `uploadedId` or an index, identifies
421
+ * the use the action was activated on.
422
+ */
423
+ image: EspalierUploadImage;
424
+ }
409
425
  /** Events fired by `<esp-image-upload>`. */
410
426
  export interface EspalierImageUploadEventMap {
411
427
  [ESP_EVENTS.IMAGE_UPLOAD_FILE_SELECTED]: CustomEvent<UploadEventDetail>;
@@ -413,6 +429,7 @@ export interface EspalierImageUploadEventMap {
413
429
  [ESP_EVENTS.IMAGE_UPLOAD_FILES_REJECTED]: CustomEvent<FilesRejectedDetail>;
414
430
  [ESP_EVENTS.IMAGE_UPLOAD_RETRY]: CustomEvent<UploadEventDetail>;
415
431
  [ESP_EVENTS.IMAGE_UPLOAD_IMAGES_REORDERED]: CustomEvent<ImagesReorderedDetail>;
432
+ [ESP_EVENTS.IMAGE_UPLOAD_PREVIEW_ACTION]: CustomEvent<ImagePreviewActionDetail>;
416
433
  }
417
434
  /** Events fired by `<esp-file-upload>`. */
418
435
  export interface EspalierFileUploadEventMap {
@@ -1 +1 @@
1
- import{VALIDITY_CHANGED_EVENT as r}from"./validation.js";import{VALIDITY_CHANGED_EVENT as e}from"./validation.js";const s={VALUE_CHANGED:"esp-value-changed",VALIDITY_CHANGED:e,CLICKED:"esp-clicked",ACTION_MENU_SELECT:"esp-action-menu-select",BURGER_OPENED:"esp-burger-opened",BURGER_CLOSED:"esp-burger-closed",DETAILS_TOGGLE:"esp-details-toggle",DETAILS_GROUP_CHANGE:"esp-details-group-change",DIALOG_OPENED:"esp-dialog-opened",DIALOG_CLOSING:"esp-dialog-closing",DIALOG_CLOSED:"esp-dialog-closed",FILE_UPLOAD_FILES_SELECTED:"esp-file-upload-files-selected",FLYOUT_OPENED:"esp-flyout-opened",FLYOUT_CLOSED:"esp-flyout-closed",FLYOUT_STATE_CHANGED:"esp-flyout-state-changed",FOCUS_PICKER_CHANGED:"esp-focus-picker-changed",FORM_DIALOG_CLOSE_REQUESTED:"esp-form-dialog-close-requested",FORM_SUBMIT:"esp-form-submit",FORM_SUBMIT_RESPONSE:"esp-form-submit-response",FORM_SUBMIT_ERROR:"esp-form-submit-error",GRID_EVENT:"esp-grid-event",GRID_LOAD_START:"esp-grid-load-start",GRID_LOAD_SUCCESS:"esp-grid-load-success",GRID_LOAD_ERROR:"esp-grid-load-error",GRID_ITEMS_CHANGED:"esp-grid-items-changed",HEADER_THEME_TOGGLE:"esp-header-theme-toggle",IMAGE_UPLOAD_FILE_SELECTED:"esp-image-upload-file-selected",IMAGE_UPLOAD_FILE_REMOVED:"esp-image-upload-file-removed",IMAGE_UPLOAD_FILES_REJECTED:"esp-image-upload-files-rejected",IMAGE_UPLOAD_RETRY:"esp-image-upload-retry",IMAGE_UPLOAD_IMAGES_REORDERED:"esp-image-upload-images-reordered",INFO_DESTROY:"esp-info-destroy",INPUT_ICON_CLICKED:"esp-input-icon-clicked",LIGHTBOX_CHANGED:"esp-lightbox-changed",MENU_GROUP_TOGGLE:"esp-menu-group-toggle",MENU_DRAWER_OPENED:"esp-menu-drawer-opened",MENU_DRAWER_CLOSED:"esp-menu-drawer-closed",MENU_DRAWER_PRESENTED:"esp-menu-drawer-presented",PAGE_WORKSPACE_RESIZE:"esp-page-workspace-resize",PICKER_MENU_SELECTION_CHANGED:"esp-picker-menu-selection-changed",PICKER_MENU_CLOSE_REQUESTED:"esp-picker-menu-close-requested",PICKER_MENU_DISMISS_REQUESTED:"esp-picker-menu-dismiss-requested",PICKER_MENU_RANGE_CHANGED:"esp-picker-menu-range-changed",POPOVER_OPENED:"esp-popover-opened",POPOVER_CLOSED:"esp-popover-closed",SEARCH_REQUESTED:"esp-search-requested",SEARCH_RESULT_SELECTED:"esp-search-result-selected",SEARCH_CLOSED:"esp-search-closed",TAB_GROUP_CHANGED:"esp-tab-group-changed",TREE_SELECT:"esp-tree-select",TREE_TOGGLE:"esp-tree-toggle",TREE_GRAFT_REQUEST:"esp-tree-graft-request",TREE_GRAFT:"esp-tree-graft",TREE_EDIT:"esp-tree-edit",TREE_DELETE:"esp-tree-delete",TREE_MOVE_UP:"esp-tree-move-up",TREE_MOVE_DOWN:"esp-tree-move-down",TREE_CUT:"esp-tree-cut",TREE_PASTE_CHILD:"esp-tree-paste-child",TREE_GRAFT_INPUT:"esp-tree-graft-input",VIDEO_READY:"esp-video-ready",VIDEO_PLAY:"esp-video-play",VIDEO_ERROR:"esp-video-error"};export{s as ESP_EVENTS,r as VALIDITY_CHANGED_EVENT};
1
+ import{VALIDITY_CHANGED_EVENT as r}from"./validation.js";import{VALIDITY_CHANGED_EVENT as e}from"./validation.js";const _={VALUE_CHANGED:"esp-value-changed",VALIDITY_CHANGED:e,CLICKED:"esp-clicked",ACTION_MENU_SELECT:"esp-action-menu-select",BURGER_OPENED:"esp-burger-opened",BURGER_CLOSED:"esp-burger-closed",DETAILS_TOGGLE:"esp-details-toggle",DETAILS_GROUP_CHANGE:"esp-details-group-change",DIALOG_OPENED:"esp-dialog-opened",DIALOG_CLOSING:"esp-dialog-closing",DIALOG_CLOSED:"esp-dialog-closed",FILE_UPLOAD_FILES_SELECTED:"esp-file-upload-files-selected",FLYOUT_OPENED:"esp-flyout-opened",FLYOUT_CLOSED:"esp-flyout-closed",FLYOUT_STATE_CHANGED:"esp-flyout-state-changed",FOCUS_PICKER_CHANGED:"esp-focus-picker-changed",FORM_DIALOG_CLOSE_REQUESTED:"esp-form-dialog-close-requested",FORM_SUBMIT:"esp-form-submit",FORM_SUBMIT_RESPONSE:"esp-form-submit-response",FORM_SUBMIT_ERROR:"esp-form-submit-error",GRID_EVENT:"esp-grid-event",GRID_LOAD_START:"esp-grid-load-start",GRID_LOAD_SUCCESS:"esp-grid-load-success",GRID_LOAD_ERROR:"esp-grid-load-error",GRID_ITEMS_CHANGED:"esp-grid-items-changed",HEADER_THEME_TOGGLE:"esp-header-theme-toggle",IMAGE_UPLOAD_FILE_SELECTED:"esp-image-upload-file-selected",IMAGE_UPLOAD_FILE_REMOVED:"esp-image-upload-file-removed",IMAGE_UPLOAD_FILES_REJECTED:"esp-image-upload-files-rejected",IMAGE_UPLOAD_RETRY:"esp-image-upload-retry",IMAGE_UPLOAD_IMAGES_REORDERED:"esp-image-upload-images-reordered",IMAGE_UPLOAD_PREVIEW_ACTION:"esp-image-upload-preview-action",INFO_DESTROY:"esp-info-destroy",INPUT_ICON_CLICKED:"esp-input-icon-clicked",LIGHTBOX_CHANGED:"esp-lightbox-changed",MENU_GROUP_TOGGLE:"esp-menu-group-toggle",MENU_DRAWER_OPENED:"esp-menu-drawer-opened",MENU_DRAWER_CLOSED:"esp-menu-drawer-closed",MENU_DRAWER_PRESENTED:"esp-menu-drawer-presented",PAGE_WORKSPACE_RESIZE:"esp-page-workspace-resize",PICKER_MENU_SELECTION_CHANGED:"esp-picker-menu-selection-changed",PICKER_MENU_CLOSE_REQUESTED:"esp-picker-menu-close-requested",PICKER_MENU_DISMISS_REQUESTED:"esp-picker-menu-dismiss-requested",PICKER_MENU_RANGE_CHANGED:"esp-picker-menu-range-changed",POPOVER_OPENED:"esp-popover-opened",POPOVER_CLOSED:"esp-popover-closed",SEARCH_REQUESTED:"esp-search-requested",SEARCH_RESULT_SELECTED:"esp-search-result-selected",SEARCH_CLOSED:"esp-search-closed",TAB_GROUP_CHANGED:"esp-tab-group-changed",TREE_SELECT:"esp-tree-select",TREE_TOGGLE:"esp-tree-toggle",TREE_GRAFT_REQUEST:"esp-tree-graft-request",TREE_GRAFT:"esp-tree-graft",TREE_EDIT:"esp-tree-edit",TREE_DELETE:"esp-tree-delete",TREE_MOVE_UP:"esp-tree-move-up",TREE_MOVE_DOWN:"esp-tree-move-down",TREE_CUT:"esp-tree-cut",TREE_PASTE_CHILD:"esp-tree-paste-child",TREE_GRAFT_INPUT:"esp-tree-graft-input",VIDEO_READY:"esp-video-ready",VIDEO_PLAY:"esp-video-play",VIDEO_ERROR:"esp-video-error"};export{_ as ESP_EVENTS,r as VALIDITY_CHANGED_EVENT};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taprootio/espalier",
3
- "version": "6.7.0",
3
+ "version": "6.8.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",