@taprootio/espalier 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,7 +9,8 @@ export type ImageScrimEdge = "none" | "flush";
9
9
  export type ImageTexture = "none" | "dots" | "halftone" | "paper" | "grain" | "grunge" | "scanlines" | "duotone";
10
10
  export type ImageTextureScale = "fine" | "medium" | "coarse";
11
11
  export type ImageBannerScheme = "auto" | "light" | "dark";
12
- export type ImageContentPosition = "bottom-start" | "bottom" | "bottom-end" | "center" | "top-start" | "top" | "top-end";
12
+ export type ImageContentPosition = "bottom-start" | "bottom" | "bottom-end" | "center" | "middle-start" | "middle-end" | "top-start" | "top" | "top-end";
13
+ export type ImageCompactPlacement = "overlay" | "below";
13
14
  export { parseImageRatio };
14
15
  /**
15
16
  * A responsive image with a native `<picture>` and an optional
@@ -117,6 +118,55 @@ export { parseImageRatio };
117
118
  * </esp-image>
118
119
  * ```
119
120
  *
121
+ * ### Headline, supporting copy, and one action
122
+ *
123
+ * The overlay takes a headline in `slot="overlay"`, an optional supporting
124
+ * sentence in `slot="overlay-supporting"`, and at most one native link or
125
+ * button in `slot="overlay-action"`. Together they form one copy stack:
126
+ * grouped spacing, the supporting sentence on the lead type role so the
127
+ * headline stays prominent, line length bounded by
128
+ * `--esp-image-overlay-measure` (`36rem`), and an action drawn in the
129
+ * overlay ink with a focus ring that reads over any photograph. The scrim
130
+ * covers the whole stack. `middle-start` and `middle-end` center the copy
131
+ * against an inline edge, and an `auto` scrim follows it to that edge:
132
+ *
133
+ * ```html
134
+ * <esp-image banner ratio="3/1" compact-ratio="4/3" content-position="middle-start" focus="0.75 0.4">
135
+ * <img src="/assets/focus-picker-unsplash.jpg" alt="A woman standing in a sunlit field with her back to the camera" />
136
+ * <h2 slot="overlay">Grow somewhere wonderful</h2>
137
+ * <p slot="overlay-supporting">Plan a garden around the light you already have, from the first frost to the last harvest.</p>
138
+ * <a slot="overlay-action" href="#start">Start planning</a>
139
+ * </esp-image>
140
+ * ```
141
+ *
142
+ * A headline on its own lays out exactly as it always has.
143
+ *
144
+ * ### Copy below the image at compact widths
145
+ *
146
+ * A crop that keeps the subject at narrow widths can lose the quiet region
147
+ * the copy sat on. `compact-placement="below"` moves the copy into a band
148
+ * under the image below the compact width, painted with the banner scheme's
149
+ * own surface and ink. Narrow this example's container to see it switch:
150
+ *
151
+ * ```html
152
+ * <div style="max-width: 24rem">
153
+ * <esp-image banner ratio="3/1" compact-ratio="3/2" compact-placement="below" focus="0.65 0.4">
154
+ * <img src="/assets/focus-picker-unsplash.jpg" alt="A woman standing in a sunlit field with her back to the camera" />
155
+ * <h2 slot="overlay">Grow somewhere wonderful</h2>
156
+ * <p slot="overlay-supporting">The band keeps the copy off the photograph.</p>
157
+ * <a slot="overlay-action" href="#start">Start planning</a>
158
+ * </esp-image>
159
+ * </div>
160
+ * ```
161
+ *
162
+ * Long copy, long words, and enlarged text grow the banner rather than being
163
+ * clipped. Copy never moves with the image: motion applied to the projected
164
+ * image or `::part(image)` stays inside the image box, and stops under
165
+ * `prefers-reduced-motion`. Server-rendered banners can lay all of this out
166
+ * before the component upgrades with the static stylesheet
167
+ * `@taprootio/espalier/image/banner-static.css`; the Image banners guide
168
+ * covers its inputs and limits.
169
+ *
120
170
  * ### The scrim follows its content
121
171
  *
122
172
  * A directional scrim holds full strength over at least the first 20% of the
@@ -300,7 +350,9 @@ export { parseImageRatio };
300
350
  * @slot - A projected native image, or `esp-image-option` children. When
301
351
  * projecting, `alt` lives on the consumer's `<img>`; `caption` remains the
302
352
  * lightbox text.
303
- * @slot overlay - Semantic banner content above the image and decorative layers.
353
+ * @slot overlay - The banner headline (or any semantic overlay content) above the image and decorative layers.
354
+ * @slot overlay-supporting - One supporting sentence under the headline. With it, or an action, the overlay becomes a copy stack.
355
+ * @slot overlay-action - One native `a` or `button` under the copy. More than one logs a warning.
304
356
  * @csspart frame - The stable banner/image frame.
305
357
  * @csspart image - The stable media-box wrapper in every source mode.
306
358
  * @csspart scrim - The decorative legibility layer.
@@ -327,6 +379,10 @@ export { parseImageRatio };
327
379
  * @cssprop --esp-image-duotone-shadow-color - Duotone shadow stop; defaults to a dark stop derived from the theme primary.
328
380
  * @cssprop --esp-image-duotone-highlight-color - Duotone highlight stop; defaults to a light stop derived from the theme complementary.
329
381
  * @cssprop --esp-image-overlay-padding - Overlay content padding.
382
+ * @cssprop --esp-image-overlay-measure - Maximum line length of the overlay copy; defaults to `36rem` for a copy stack and `none` for a headline on its own.
383
+ * @cssprop --esp-image-overlay-gap - Space between the headline and supporting copy in a copy stack; the action sits twice as far below. Defaults to `var(--esp-size-small)`.
384
+ * @cssprop --esp-image-static-ratio - Read only by the static `banner-static.css` stylesheet before upgrade: the `ratio` value, e.g. `3 / 1`. A server sets it inline beside the attribute.
385
+ * @cssprop --esp-image-static-compact-ratio - Read only by the static `banner-static.css` stylesheet before upgrade: the `compact-ratio` value, if any.
330
386
  * @cssprop --esp-image-overlay-color - Overlay text color; defaults to the theme heading color when the banner polarity matches the scheme.
331
387
  * @cssprop --esp-image-overlay-text-shadow - Overlay text shadow; defaults to a soft polarity-matched halo. Set to `none` to disable.
332
388
  * @docPageTitle Image
@@ -406,8 +462,19 @@ export declare class EspalierImage extends EspalierElementBase {
406
462
  texture: string;
407
463
  /** CSS pitch or discrete SVG-filter variant for the selected texture. */
408
464
  textureScale: ImageTextureScale;
409
- /** Logical position for semantic banner content. */
465
+ /**
466
+ * Logical position for semantic banner content. `middle-start` and
467
+ * `middle-end` center the copy vertically against the inline start or end
468
+ * edge, mirroring in right-to-left text.
469
+ */
410
470
  contentPosition: ImageContentPosition;
471
+ /**
472
+ * Where the overlay copy goes below the compact width. `overlay` (the
473
+ * default) keeps it over the image. `below` moves it into a band under the
474
+ * image, painted in the banner scheme's own surface and ink, for crops that
475
+ * lose their quiet region at narrow widths.
476
+ */
477
+ compactPlacement: ImageCompactPlacement;
411
478
  /** Normalized focal point used for cover cropping. */
412
479
  focusPoint: FocusPoint;
413
480
  /** Banner target aspect ratio, as a positive number or `number / number`. */
@@ -1,40 +1,49 @@
1
- var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")a=Reflect.decorate(m,e,t,r);else for(var l=m.length-1;l>=0;l--)(o=m[l])&&(a=(s<3?o(a):s>3?o(e,t,a):o(e,t))||a);return s>3&&a&&Object.defineProperty(e,t,a),a},p;import{css as I,html as h,nothing as P}from"lit";import{customElement as E,property as c,state as u}from"lit/decorators.js";import{EspalierElementBase as y}from"../shared/esp-element-base.js";import{slotHasContent as b}from"../shared/slot-content.js";import{renderVisualOverlay as $,visualOverlayStyles as A}from"../shared/visual-overlay.js";import{focusConverter as N,normalizeFocus as W}from"./image-focus.js";import{ensureImageTextureFilters as D,imageTextureFilterId as M}from"./image-texture-filters.js";import{getImageTexture as x,isBuiltInImageTexture as _,subscribeToImageTextureRegistry as B}from"../shared/image-texture-registry.js";import{validImageDimensions as k}from"./image-dimensions.js";import{parseImageRatio as f}from"./image-ratio.js";import{isMeasuredScrim as q,scrimReach as H,unionScrimBox as U}from"./scrim-reach.js";import"./esp-image-option.js";import{enumConverter as d}from"../shared/enum-converter.js";const w=new Set(["auto","none","flat","top","bottom","left","right","radial"]),S=new Set(["soft","medium","strong"]),z=new Set(["none","flush"]),O=new Set(["fine","medium","coarse"]),j=new Set(["auto","light","dark"]),R=new Set(["bottom-start","bottom","bottom-end","center","top-start","top","top-end"]);function T(m){const e=[];for(const t of m)getComputedStyle(t).display==="contents"?e.push(...T(t.children)):e.push(t);return e}function F(m){const e=m.getBoundingClientRect();if(e.width>0||e.height>0)return e;const t=m.ownerDocument.createRange();t.selectNodeContents(m);const r=t.getBoundingClientRect();return r.width>0||r.height>0?r:null}let i=p=class extends y{constructor(){super(...arguments),this.originalHeight=0,this.originalWidth=0,this.imageUrl="",this.localImage="",this.caption="",this.sizes="100vw",this.loading="eager",this.deferOffscreen=!1,this.banner=!1,this.bannerScheme="auto",this.scrim="auto",this.scrimStrength="medium",this.scrimEdge="none",this.texture="none",this.textureScale="medium",this.contentPosition="bottom-start",this.focusPoint={x:.5,y:.5},this.ratio="",this.compactRatio="",this.renderedWidth=0,this.measuredWidth=0,this.compact=!1,this.overlayHasContent=!1,this.resizeObserver=null,this.scrimObserver=null,this.appliedScrimReach=0,this.offscreenObserver=null,this.offscreenAdmitted=!1,this.deferredProjectedImage=null,this.unsubscribeTextures=null,this.handleSlotChange=e=>{if(e.target instanceof HTMLSlotElement){if(e.target.name==="overlay"){const t=b(e.target);t!==this.overlayHasContent&&(this.overlayHasContent=t),this.observeScrimTargets();return}this.requestUpdate()}}}get isPortrait(){const e=k(this.originalWidth,this.originalHeight);return e!==null&&e.height>e.width}findProjected(){for(const e of this.children)if(e.tagName==="PICTURE"||e.tagName==="IMG")return e;return null}findProjectedImage(e=this.findProjected()){return e?e.tagName==="IMG"?e:e.querySelector("img"):null}requiresOffscreenDeferral(e=this.findProjectedImage()){return this.deferOffscreen&&e?.getAttribute("loading")?.toLowerCase()==="lazy"}shouldDeferProjectedSizes(){return this.requiresOffscreenDeferral()&&!this.offscreenAdmitted}applyMeasuredWidth(){this.measuredWidth>0&&this.measuredWidth!==this.renderedWidth&&(this.renderedWidth=this.measuredWidth)}syncOffscreenDeferral(){const e=this.findProjectedImage();if(e!==this.deferredProjectedImage&&(this.offscreenAdmitted=!1,this.offscreenObserver?.disconnect(),this.offscreenObserver=null,this.deferredProjectedImage=e),!this.requiresOffscreenDeferral(e)){this.offscreenObserver?.disconnect(),this.offscreenObserver=null,this.offscreenAdmitted=!1,this.deferredProjectedImage=null,this.applyMeasuredWidth();return}if(!this.offscreenAdmitted){if(typeof IntersectionObserver>"u"){this.offscreenAdmitted=!0,this.applyMeasuredWidth();return}if(!this.offscreenObserver){const t=e,r=new IntersectionObserver(s=>{if(this.offscreenObserver===r){if(this.findProjectedImage()!==t){this.syncOffscreenDeferral();return}s.some(a=>a.isIntersecting)&&(this.offscreenAdmitted=!0,this.offscreenObserver?.disconnect(),this.offscreenObserver=null,this.applyMeasuredWidth(),this.requestUpdate())}},{rootMargin:"200px"});this.offscreenObserver=r}this.offscreenObserver.observe(this)}}connectedCallback(){super.connectedCallback(),p.ensureProjectionStyles(this.getRootNode()),this.unsubscribeTextures??=B(()=>this.requestUpdate()),this.resizeObserver??=new ResizeObserver(e=>{const t=e[0]?.contentBoxSize?.[0],r=Math.round(t?t.inlineSize:e[0]?.contentRect.width??0);r<=0||(this.measuredWidth=r,this.syncOffscreenDeferral(),this.applyMeasuredWidth())}),this.resizeObserver.observe(this),this.syncOffscreenDeferral(),this.hasUpdated&&this.observeScrimTargets()}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeTextures?.(),this.unsubscribeTextures=null,this.resizeObserver?.disconnect(),this.resizeObserver=null,this.scrimObserver?.disconnect(),this.scrimObserver=null,this.offscreenObserver?.disconnect(),this.offscreenObserver=null,this.offscreenAdmitted=!1,this.deferredProjectedImage=null}observeScrimTargets(){if(!this.shadowRoot)return;this.scrimObserver??=new ResizeObserver(()=>this.measureScrimReach()),this.scrimObserver.disconnect();const e=this.shadowRoot?.querySelector(".overlay");e&&this.scrimObserver.observe(e);const t=this.shadowRoot?.querySelector('[part="scrim"]');t&&this.scrimObserver.observe(t);for(const r of T(this.overlayElements()))this.scrimObserver.observe(r,{box:"border-box"})}overlayElements(){return this.shadowRoot?.querySelector('slot[name="overlay"]')?.assignedElements({flatten:!0})??[]}measureScrimReach(){const e=this.shadowRoot?.querySelector(".frame");if(!e)return;const t=this.resolvedScrim();let r=0;const s=this.shadowRoot?.querySelector('[part="scrim"]');if(this.banner&&this.overlayHasContent&&s&&q(t)){const a=s.getBoundingClientRect();if(a.width<=0||a.height<=0)return;const o=U(this.overlayElements().map(F));r=H(t,a,o)}r!==this.appliedScrimReach&&(this.appliedScrimReach=r,r>0?e.style.setProperty("--_esp-image-scrim-reach",`${r}%`):e.style.removeProperty("--_esp-image-scrim-reach"))}effectiveSizes(){return this.renderedWidth>0?`${this.renderedWidth}px`:this.sizes}buildSources(){const e=new Map;for(const t of this.querySelectorAll("esp-image-option")){const r=t.getAttribute("url"),s=Number(t.getAttribute("width"));if(!r||!Number.isFinite(s)||s<=0)continue;const a=t.getAttribute("type")??"",o=e.get(a)??[];o.push({url:r,width:s}),e.set(a,o)}return Array.from(e,([t,r])=>({type:t,srcset:r.sort((s,a)=>s.width-a.width).map(s=>`${s.url} ${s.width}w`).join(", ")})).filter(t=>t.srcset.length>0)}resolvedBannerScheme(){return this.bannerScheme!=="auto"?this.bannerScheme:this.scheme==="dark"?"dark":"light"}resolvedTexture(){return _(this.texture)?this.texture:x(this.texture)?this.texture:"none"}resolvedScrim(){return this.scrim!=="auto"?this.scrim:this.overlayHasContent?this.contentPosition.startsWith("top")?"top":this.contentPosition.startsWith("bottom")?"bottom":"radial":"none"}resolvedAspectRatio(){const e=k(this.originalWidth,this.originalHeight);if(!this.banner)return e?`${e.width} / ${e.height}`:null;const t=f(this.ratio);return(this.compact?f(this.compactRatio):null)??t??(e?`${e.width} / ${e.height}`:null)}normalizeEnums(e){e.has("scrim")&&!w.has(this.scrim)&&(this.scrim="auto"),e.has("bannerScheme")&&!j.has(this.bannerScheme)&&(this.bannerScheme="auto"),e.has("scrimStrength")&&!S.has(this.scrimStrength)&&(this.scrimStrength="medium"),e.has("scrimEdge")&&!z.has(this.scrimEdge)&&(this.scrimEdge="none"),e.has("textureScale")&&!O.has(this.textureScale)&&(this.textureScale="medium"),e.has("contentPosition")&&!R.has(this.contentPosition)&&(this.contentPosition="bottom-start")}willUpdate(e){super.willUpdate(e),this.normalizeEnums(e);const t=W(this.focusPoint),r=Number((t.x*100).toFixed(4)),s=Number((t.y*100).toFixed(4));this.style.setProperty("--_esp-image-object-position",`${r}% ${s}%`);const a=this.resolvedAspectRatio();a?this.style.setProperty("--_esp-image-aspect-ratio",a):this.style.removeProperty("--_esp-image-aspect-ratio");const o=this.resolvedTexture();if(["paper","grain","grunge"].includes(o)){const g=o==="grunge"&&this.resolvedBannerScheme()==="light"?"grunge-light":o;this.style.setProperty("--_esp-image-texture-filter",`url(#${M(g,this.textureScale)})`)}else this.style.removeProperty("--_esp-image-texture-filter");const l=_(o)?void 0:x(o),C=[["--_esp-image-registered-image",l?.image],["--_esp-image-registered-size",l?.size],["--_esp-image-registered-repeat",l?.repeat],["--_esp-image-registered-position",l?.position],["--_esp-image-registered-opacity",l?.opacity?.toString()],["--_esp-image-registered-blend-mode",l?.blendMode]];for(const[g,v]of C)v===void 0?this.style.removeProperty(g):this.style.setProperty(g,v)}firstUpdated(e){super.firstUpdated(e);const t=this.shadowRoot?.querySelector('slot[name="overlay"]');t&&(this.overlayHasContent=b(t)),this.observeScrimTargets()}updated(e){if(super.updated(e),this.syncOffscreenDeferral(),(e.has("banner")||e.has("scrim")||e.has("contentPosition")||e.has("overlayHasContent")||e.has("compact"))&&this.observeScrimTargets(),["paper","grain","grunge"].includes(this.resolvedTexture())&&this.renderRoot&&D(this.renderRoot),this.renderedWidth>0){const o=this.shadowRoot?.querySelector(".compact-sentinel")?.getBoundingClientRect().width??0,l=o>0&&this.renderedWidth<o;l!==this.compact&&(this.compact=l)}if(this.renderedWidth<=0||this.shouldDeferProjectedSizes())return;const t=this.findProjected();if(!t)return;const r=this.effectiveSizes();if(t.tagName==="PICTURE")for(const a of t.querySelectorAll("source"))a.setAttribute("sizes",r);const s=this.findProjectedImage(t);s?.hasAttribute("srcset")&&s.setAttribute("sizes",r)}renderMedia(){if(this.localImage)return h`<img
1
+ var l=function(m,e,t,r){var i=arguments.length,a=i<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,s;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")a=Reflect.decorate(m,e,t,r);else for(var n=m.length-1;n>=0;n--)(s=m[n])&&(a=(i<3?s(a):i>3?s(e,t,a):s(e,t))||a);return i>3&&a&&Object.defineProperty(e,t,a),a},y;import{css as q,html as b,nothing as F}from"lit";import{customElement as U,property as c,state as u}from"lit/decorators.js";import{EspalierElementBase as C}from"../shared/esp-element-base.js";import{slotHasContent as G}from"../shared/slot-content.js";import{renderVisualOverlay as L,visualOverlayStyles as V}from"../shared/visual-overlay.js";import{focusConverter as K,normalizeFocus as X}from"./image-focus.js";import{ensureImageTextureFilters as Y,imageTextureFilterId as J}from"./image-texture-filters.js";import{getImageTexture as R,isBuiltInImageTexture as T,subscribeToImageTextureRegistry as Q}from"../shared/image-texture-registry.js";import{validImageDimensions as O}from"./image-dimensions.js";import{parseImageRatio as z}from"./image-ratio.js";import{isMeasuredScrim as Z,scrimReach as ee,unionScrimBox as j}from"./scrim-reach.js";import"./esp-image-option.js";import{enumConverter as v}from"../shared/enum-converter.js";import{RafThrottle as te}from"../shared/raf-throttle.js";const P=new Set(["auto","none","flat","top","bottom","left","right","radial"]),I=new Set(["soft","medium","strong"]),E=new Set(["none","flush"]),A=new Set(["fine","medium","coarse"]),H=new Set(["auto","light","dark"]),N=new Set(["bottom-start","bottom","bottom-end","center","middle-start","middle-end","top-start","top","top-end"]),B=new Set(["overlay","below"]),W=["overlay","overlay-supporting","overlay-action"];function re(m){if(!m)return null;const[e,t=1]=m.split("/").map(i=>Number(i.trim())),r=e/t;return Number.isFinite(r)&&r>0?r:null}const f=new Set;let w=null;const ae={attributeFilter:["dir"],subtree:!0};function $(m,e){if(!(e?!f.has(m)&&!!f.add(m):f.delete(m))||typeof MutationObserver>"u")return;if(w?.disconnect(),f.size===0){w=null;return}w??=new MutationObserver(()=>{for(const i of f)i.requestUpdate()});const r=new Set([document.documentElement]);for(const i of f){let a=i;for(;a;){const s=a.getRootNode();s instanceof ShadowRoot&&r.add(s),a=a instanceof Element&&a.assignedSlot?a.assignedSlot:a.parentNode instanceof ShadowRoot?a.parentNode.host:a.parentNode}}for(const i of r)w.observe(i,ae)}function _(m){const e=[];for(const t of m)getComputedStyle(t).display==="contents"?e.push(..._(t.children)):e.push(t);return e}function ie(m){const e=m.getBoundingClientRect();if(e.width>0||e.height>0)return e;const t=m.ownerDocument.createRange();t.selectNodeContents(m);const r=t.getBoundingClientRect();return r.width>0||r.height>0?r:null}let o=y=class extends C{constructor(){super(...arguments),this.originalHeight=0,this.originalWidth=0,this.imageUrl="",this.localImage="",this.caption="",this.sizes="100vw",this.loading="eager",this.deferOffscreen=!1,this.banner=!1,this.bannerScheme="auto",this.scrim="auto",this.scrimStrength="medium",this.scrimEdge="none",this.texture="none",this.textureScale="medium",this.contentPosition="bottom-start",this.compactPlacement="overlay",this.focusPoint={x:.5,y:.5},this.ratio="",this.compactRatio="",this.renderedWidth=0,this.measuredWidth=0,this.compact=!1,this.overlayHasContent=!1,this.overlayHasStack=!1,this.overlayHasHeadline=!1,this.overlayHasSupporting=!1,this.renderedScrim=null,this.measuredScrim=null,this.grown=!1,this.growthWidth=null,this.growthCheckPending=!1,this.growthBlock=null,this.growthRollback=new te(()=>{this.grown&&(this.grown=!1,this.growthWidth=null)}),this.resizeObserver=null,this.scrimObserver=null,this.appliedScrimReach=0,this.offscreenObserver=null,this.offscreenAdmitted=!1,this.deferredProjectedImage=null,this.unsubscribeTextures=null,this.handleSlotChange=e=>{if(e.target instanceof HTMLSlotElement){if(W.includes(e.target.name)){this.syncOverlaySlots(),this.observeScrimTargets();return}this.requestUpdate()}},this.handleWindowResize=()=>{!this.banner||!this.overlayHasContent||(this.measureScrimReach(),this.growthBlock&&(clearTimeout(this.growthRetryTimer),this.growthRetryTimer=setTimeout(()=>{!this.growthBlock||!this.isConnected||(this.growthBlock=null,this.measureScrimReach())},150)))}}get isPortrait(){const e=O(this.originalWidth,this.originalHeight);return e!==null&&e.height>e.width}overlaySlot(e){return this.shadowRoot?.querySelector(`slot[name="${e}"]`)??null}syncOverlaySlots(){const e=n=>{const d=this.overlaySlot(n);return d?G(d):!1},t=e("overlay"),r=e("overlay-supporting"),i=r||e("overlay-action"),a=i||t;t!==this.overlayHasHeadline&&(this.overlayHasHeadline=t),r!==this.overlayHasSupporting&&(this.overlayHasSupporting=r),a!==this.overlayHasContent&&(this.overlayHasContent=a),i!==this.overlayHasStack&&(this.overlayHasStack=i);const s=this.overlaySlot("overlay-action")?.assignedElements({flatten:!0})??[];s.length>1&&console.warn(`<esp-image> takes one overlay action; ${s.length} elements are slotted into "overlay-action".`,this)}findProjected(){for(const e of this.children)if(e.tagName==="PICTURE"||e.tagName==="IMG")return e;return null}findProjectedImage(e=this.findProjected()){return e?e.tagName==="IMG"?e:e.querySelector("img"):null}requiresOffscreenDeferral(e=this.findProjectedImage()){return this.deferOffscreen&&e?.getAttribute("loading")?.toLowerCase()==="lazy"}shouldDeferProjectedSizes(){return this.requiresOffscreenDeferral()&&!this.offscreenAdmitted}applyMeasuredWidth(){this.measuredWidth>0&&this.measuredWidth!==this.renderedWidth&&(this.renderedWidth=this.measuredWidth)}syncOffscreenDeferral(){const e=this.findProjectedImage();if(e!==this.deferredProjectedImage&&(this.offscreenAdmitted=!1,this.offscreenObserver?.disconnect(),this.offscreenObserver=null,this.deferredProjectedImage=e),!this.requiresOffscreenDeferral(e)){this.offscreenObserver?.disconnect(),this.offscreenObserver=null,this.offscreenAdmitted=!1,this.deferredProjectedImage=null,this.applyMeasuredWidth();return}if(!this.offscreenAdmitted){if(typeof IntersectionObserver>"u"){this.offscreenAdmitted=!0,this.applyMeasuredWidth();return}if(!this.offscreenObserver){const t=e,r=new IntersectionObserver(i=>{if(this.offscreenObserver===r){if(this.findProjectedImage()!==t){this.syncOffscreenDeferral();return}i.some(a=>a.isIntersecting)&&(this.offscreenAdmitted=!0,this.offscreenObserver?.disconnect(),this.offscreenObserver=null,this.applyMeasuredWidth(),this.requestUpdate())}},{rootMargin:"200px"});this.offscreenObserver=r}this.offscreenObserver.observe(this)}}connectedCallback(){super.connectedCallback(),y.ensureProjectionStyles(this.getRootNode()),this.unsubscribeTextures??=Q(()=>this.requestUpdate()),this.resizeObserver??=new ResizeObserver(e=>{(this.grown||this.growthBlock)&&this.measureScrimReach();const t=e[0]?.contentBoxSize?.[0],r=Math.round(t?t.inlineSize:e[0]?.contentRect.width??0);r<=0||(this.measuredWidth=r,this.syncOffscreenDeferral(),this.applyMeasuredWidth())}),this.resizeObserver.observe(this),window.addEventListener("resize",this.handleWindowResize,{passive:!0}),this.syncOffscreenDeferral(),this.hasUpdated&&(this.observeScrimTargets(),this.syncDirectionTracking())}disconnectedCallback(){super.disconnectedCallback(),$(this,!1),window.removeEventListener("resize",this.handleWindowResize),this.growthRollback.cancel(),clearTimeout(this.growthRetryTimer),this.unsubscribeTextures?.(),this.unsubscribeTextures=null,this.resizeObserver?.disconnect(),this.resizeObserver=null,this.scrimObserver?.disconnect(),this.scrimObserver=null,this.offscreenObserver?.disconnect(),this.offscreenObserver=null,this.offscreenAdmitted=!1,this.deferredProjectedImage=null}observeScrimTargets(){if(!this.shadowRoot)return;this.scrimObserver??=new ResizeObserver(()=>this.measureScrimReach()),this.scrimObserver.disconnect();const e=this.shadowRoot?.querySelector(".overlay");e&&this.scrimObserver.observe(e);const t=this.shadowRoot?.querySelector('[part="scrim"]');t&&this.scrimObserver.observe(t);const r=this.shadowRoot?.querySelector(".stack");r&&this.overlayHasStack&&this.scrimObserver.observe(r);for(const i of _(this.overlayElements()))this.scrimObserver.observe(i,{box:"border-box"})}overlayElements(){return W.flatMap(e=>this.overlaySlot(e)?.assignedElements({flatten:!0})??[])}measureScrimReach(){const e=this.shadowRoot?.querySelector(".frame");if(!e||this.syncGrowth(e))return;const t=this.resolvedScrim();if(this.renderedScrim!==null&&t!==this.renderedScrim){this.requestUpdate();return}let r=0;const i=this.shadowRoot?.querySelector('[part="scrim"]');if(this.banner&&this.overlayHasContent&&!this.bandActive()&&i&&Z(t)){const a=i.getBoundingClientRect();if(a.width<=0||a.height<=0)return;const s=j(this.overlayElements().map(ie));r=ee(t,a,s)}r!==this.appliedScrimReach&&(this.appliedScrimReach=r,r>0?e.style.setProperty("--_esp-image-scrim-reach",`${r}%`):e.style.removeProperty("--_esp-image-scrim-reach"))}effectiveSizes(){return this.renderedWidth>0?`${this.renderedWidth}px`:this.sizes}buildSources(){const e=new Map;for(const t of this.querySelectorAll("esp-image-option")){const r=t.getAttribute("url"),i=Number(t.getAttribute("width"));if(!r||!Number.isFinite(i)||i<=0)continue;const a=t.getAttribute("type")??"",s=e.get(a)??[];s.push({url:r,width:i}),e.set(a,s)}return Array.from(e,([t,r])=>({type:t,srcset:r.sort((i,a)=>i.width-a.width).map(i=>`${i.url} ${i.width}w`).join(", ")})).filter(t=>t.srcset.length>0)}resolvedBannerScheme(){return this.bannerScheme!=="auto"?this.bannerScheme:this.scheme==="dark"?"dark":"light"}resolvedTexture(){return T(this.texture)?this.texture:R(this.texture)?this.texture:"none"}overlayContentHeight(){const e=this.shadowRoot?.querySelector(".overlay");if(!e||e.hidden)return null;const t=getComputedStyle(e),r=(Number.parseFloat(t.paddingTop)||0)+(Number.parseFloat(t.paddingBottom)||0);if(this.overlayHasStack){const s=this.shadowRoot?.querySelector(".stack");return s?r+s.getBoundingClientRect().height:null}let i=1/0,a=-1/0;for(const s of _(this.overlayElements())){const n=s.getBoundingClientRect();if(n.width<=0&&n.height<=0)continue;const d=getComputedStyle(s);i=Math.min(i,n.top-(Number.parseFloat(d.marginTop)||0)),a=Math.max(a,n.bottom+(Number.parseFloat(d.marginBottom)||0))}return a>i?r+a-i:null}syncGrowth(e){const t=re(this.resolvedAspectRatio());let r=!1;if(this.banner&&this.overlayHasContent&&!this.bandActive()&&t!==null){const i=e.getBoundingClientRect(),a=this.overlayContentHeight();if(i.width<=0||a===null)return!1;const s=getComputedStyle(this).maxBlockSize,n=this.growthBlock;n&&(Math.abs(i.width-n.width)>1||s!==n.cap||a<n.need-.5)&&(this.growthBlock=null);const d=this.getBoundingClientRect(),h=getComputedStyle(this),p=[h.borderTopWidth,h.borderBottomWidth,h.paddingTop,h.paddingBottom].reduce((x,S)=>x+(Number.parseFloat(S)||0),0),g=d.width/t,k=getComputedStyle(e),M=(Number.parseFloat(k.borderTopWidth)||0)+(Number.parseFloat(k.borderBottomWidth)||0),D=g-p-M;if(this.grown){const x=this.growthCheckPending&&this.growthWidth!==null&&i.width>this.growthWidth+1;this.growthCheckPending=!1;const S=d.height-p<i.height-.5;if(x||S)return this.growthBlock={width:x?this.growthWidth:i.width,cap:s,need:a},this.scheduleGrowthRollback(),!1;r=a>D+.5}else r=this.growthBlock===null&&this.copyClipped(i,k)&&Math.abs(d.height-g)<=1,r&&(this.growthWidth=i.width,this.growthCheckPending=!0)}return r===this.grown?!1:(this.grown=r,r||(this.growthWidth=null),!0)}scheduleGrowthRollback(){this.growthRollback.schedule()}copyClipped(e,t){const r=e.top+(Number.parseFloat(t.borderTopWidth)||0),i=e.bottom-(Number.parseFloat(t.borderBottomWidth)||0),a=[],s=this.overlayHasStack?this.shadowRoot?.querySelector(".stack"):null;if(s)a.push(s.getBoundingClientRect());else for(const d of _(this.overlayElements())){const h=d.getBoundingClientRect();(h.width>0||h.height>0)&&a.push(h)}const n=j(a);return n!==null&&(n.top<r-.5||n.bottom>i+.5)}grownActive(){return this.grown&&this.banner&&!this.bandActive()}syncDirectionTracking(){$(this,this.isConnected&&this.banner&&this.scrim==="auto"&&this.contentPosition.startsWith("middle"))}bandActive(){return this.banner&&this.compact&&this.compactPlacement==="below"&&this.overlayHasContent}resolvedScrim(){if(this.scrim!=="auto")return this.scrim;if(!this.overlayHasContent||this.bandActive())return"none";if(this.contentPosition.startsWith("top"))return"top";if(this.contentPosition.startsWith("bottom"))return"bottom";if(this.contentPosition.startsWith("middle")){const e=getComputedStyle(this).direction==="rtl";return this.contentPosition==="middle-start"!==e?"left":"right"}return"radial"}resolvedAspectRatio(){const e=O(this.originalWidth,this.originalHeight);if(!this.banner)return e?`${e.width} / ${e.height}`:null;const t=z(this.ratio);return(this.compact?z(this.compactRatio):null)??t??(e?`${e.width} / ${e.height}`:null)}normalizeEnums(e){e.has("scrim")&&!P.has(this.scrim)&&(this.scrim="auto"),e.has("bannerScheme")&&!H.has(this.bannerScheme)&&(this.bannerScheme="auto"),e.has("scrimStrength")&&!I.has(this.scrimStrength)&&(this.scrimStrength="medium"),e.has("scrimEdge")&&!E.has(this.scrimEdge)&&(this.scrimEdge="none"),e.has("textureScale")&&!A.has(this.textureScale)&&(this.textureScale="medium"),e.has("contentPosition")&&!N.has(this.contentPosition)&&(this.contentPosition="bottom-start"),e.has("compactPlacement")&&!B.has(this.compactPlacement)&&(this.compactPlacement="overlay")}willUpdate(e){super.willUpdate(e),this.normalizeEnums(e);const t=X(this.focusPoint),r=Number((t.x*100).toFixed(4)),i=Number((t.y*100).toFixed(4));this.style.setProperty("--_esp-image-object-position",`${r}% ${i}%`);const a=this.resolvedAspectRatio(),s=this.grownActive()||this.bandActive();for(const[p,g]of[["--_esp-image-aspect-ratio",!s],["--_esp-image-frame-aspect-ratio",s]])a&&g?this.style.setProperty(p,a):this.style.removeProperty(p);this.syncDirectionTracking();const n=this.resolvedTexture();if(["paper","grain","grunge"].includes(n)){const p=n==="grunge"&&this.resolvedBannerScheme()==="light"?"grunge-light":n;this.style.setProperty("--_esp-image-texture-filter",`url(#${J(p,this.textureScale)})`)}else this.style.removeProperty("--_esp-image-texture-filter");const d=T(n)?void 0:R(n),h=[["--_esp-image-registered-image",d?.image],["--_esp-image-registered-size",d?.size],["--_esp-image-registered-repeat",d?.repeat],["--_esp-image-registered-position",d?.position],["--_esp-image-registered-opacity",d?.opacity?.toString()],["--_esp-image-registered-blend-mode",d?.blendMode]];for(const[p,g]of h)g===void 0?this.style.removeProperty(p):this.style.setProperty(p,g)}firstUpdated(e){super.firstUpdated(e),this.syncOverlaySlots(),this.observeScrimTargets()}updated(e){if(super.updated(e),this.syncOffscreenDeferral(),(e.has("banner")||e.has("scrim")||e.has("contentPosition")||e.has("overlayHasContent")||e.has("overlayHasStack")||e.has("compactPlacement")||e.has("grown")||e.has("compact")||this.renderedScrim!==this.measuredScrim)&&(this.measuredScrim=this.renderedScrim,this.observeScrimTargets()),["paper","grain","grunge"].includes(this.resolvedTexture())&&this.renderRoot&&Y(this.renderRoot),this.renderedWidth>0){const s=this.shadowRoot?.querySelector(".compact-sentinel")?.getBoundingClientRect().width??0,n=s>0&&this.renderedWidth<s;n!==this.compact&&(this.compact=n)}if(this.renderedWidth<=0||this.shouldDeferProjectedSizes())return;const t=this.findProjected();if(!t)return;const r=this.effectiveSizes();if(t.tagName==="PICTURE")for(const a of t.querySelectorAll("source"))a.setAttribute("sizes",r);const i=this.findProjectedImage(t);i?.hasAttribute("srcset")&&i.setAttribute("sizes",r)}renderMedia(){if(this.localImage)return b`<img
2
2
  src=${this.localImage}
3
3
  alt=${this.caption}
4
4
  decoding="async"
5
5
  loading=${this.loading}
6
- />`;const e=h`<slot @slotchange=${this.handleSlotChange}></slot>`;if(this.findProjected())return e;const t=this.buildSources();return h`
6
+ />`;const e=b`<slot @slotchange=${this.handleSlotChange}></slot>`;if(this.findProjected())return e;const t=this.buildSources();return b`
7
7
  <picture>
8
- ${t.map(r=>h`
8
+ ${t.map(r=>b`
9
9
  <source
10
10
  srcset=${r.srcset}
11
11
  sizes=${this.effectiveSizes()}
12
- type=${r.type||P}
12
+ type=${r.type||F}
13
13
  />
14
14
  `)}
15
15
  <img src=${this.imageUrl} alt=${this.caption} decoding="async" loading=${this.loading} />
16
16
  </picture>
17
17
  ${e}
18
- `}render(){return h`
18
+ `}render(){const e=this.resolvedScrim();return this.renderedScrim=e,b`
19
19
  <div
20
20
  part="frame"
21
21
  class="frame"
22
22
  data-banner-scheme=${this.resolvedBannerScheme()}
23
- data-scrim=${this.resolvedScrim()}
23
+ data-scrim=${e}
24
24
  data-scrim-strength=${this.scrimStrength}
25
25
  data-scrim-edge=${this.scrimEdge}
26
26
  data-texture=${this.resolvedTexture()}
27
27
  data-texture-scale=${this.textureScale}
28
28
  data-content-position=${this.contentPosition}
29
+ data-placement=${this.bandActive()?"band":"overlay"}
30
+ ?data-grown=${this.grownActive()}
31
+ ?data-overlay-stack=${this.overlayHasStack}
32
+ ?data-overlay-headline=${this.overlayHasHeadline}
33
+ ?data-overlay-supporting=${this.overlayHasSupporting}
29
34
  >
30
35
  <div part="image" class="image">${this.renderMedia()}</div>
31
- ${$({className:"banner-layers",imagePart:"texture",scrimPart:"scrim",texturePart:"texture"})}
36
+ ${L({className:"banner-layers",imagePart:"texture",scrimPart:"scrim",texturePart:"texture"})}
32
37
  <div part="overlay" class="overlay" ?hidden=${!this.banner||!this.overlayHasContent}>
33
- <slot name="overlay" @slotchange=${this.handleSlotChange}></slot>
38
+ <div class="stack">
39
+ <slot name="overlay" @slotchange=${this.handleSlotChange}></slot>
40
+ <slot name="overlay-supporting" @slotchange=${this.handleSlotChange}></slot>
41
+ <slot name="overlay-action" @slotchange=${this.handleSlotChange}></slot>
42
+ </div>
34
43
  </div>
35
44
  <span class="compact-sentinel" aria-hidden="true"></span>
36
45
  </div>
37
- `}static ensureProjectionStyles(e){const t=e.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&"host"in e?e:e.nodeType===Node.DOCUMENT_NODE?e.head:e.ownerDocument?.head??document.head,r=Array.from(t.querySelectorAll("style[data-esp-image-projection-styles]")),s=r.find(o=>o.textContent===p.projectionStyles);if(s){for(const o of r)o!==s&&o.remove();return}for(const o of r)o.remove();const a=t.ownerDocument.createElement("style");a.dataset.espImageProjectionStyles="",a.textContent=p.projectionStyles,t.append(a)}};i.projectionStyles=`
46
+ `}static ensureProjectionStyles(e){const t=e.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&"host"in e?e:e.nodeType===Node.DOCUMENT_NODE?e.head:e.ownerDocument?.head??document.head,r=Array.from(t.querySelectorAll("style[data-esp-image-projection-styles]")),i=r.find(s=>s.textContent===y.projectionStyles);if(i){for(const s of r)s!==i&&s.remove();return}for(const s of r)s.remove();const a=t.ownerDocument.createElement("style");a.dataset.espImageProjectionStyles="",a.textContent=y.projectionStyles,t.append(a)}};o.projectionStyles=`
38
47
  esp-image > picture,
39
48
  esp-image > img {
40
49
  display: block;
@@ -50,7 +59,15 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
50
59
  object-fit: var(--_esp-image-object-fit, cover);
51
60
  object-position: var(--esp-image-object-position, var(--_esp-image-object-position, center));
52
61
  }
53
- `,i.styles=[...y.styles,I`
62
+ @media (prefers-reduced-motion: reduce) {
63
+ esp-image[banner] > picture,
64
+ esp-image[banner] > picture > img,
65
+ esp-image[banner] > img {
66
+ animation: none !important;
67
+ transition: none !important;
68
+ }
69
+ }
70
+ `,o.styles=[...C.styles,q`
54
71
  :host {
55
72
  display: block;
56
73
  aspect-ratio: var(--_esp-image-aspect-ratio, auto);
@@ -110,6 +127,26 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
110
127
  z-index: 0;
111
128
  }
112
129
 
130
+
131
+ :host([banner]) .image {
132
+ overflow: clip;
133
+ }
134
+
135
+
136
+ :host([banner]) .frame:is([data-grown], [data-placement="band"]) {
137
+ display: grid;
138
+ grid-template: minmax(0, 1fr) / minmax(0, 1fr);
139
+ }
140
+ :host([banner]) .frame[data-grown]::before {
141
+ content: "";
142
+ grid-area: 1 / 1;
143
+ aspect-ratio: var(--_esp-image-frame-aspect-ratio, auto);
144
+ }
145
+ :host([banner]) .frame[data-grown] .image {
146
+ position: absolute;
147
+ inset: 0;
148
+ }
149
+
113
150
  img {
114
151
  object-fit: var(--_esp-image-object-fit, cover);
115
152
  object-position: var(
@@ -441,6 +478,8 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
441
478
  z-index: 2;
442
479
  inset: 0;
443
480
  display: flex;
481
+
482
+ overflow-wrap: anywhere;
444
483
  align-items: flex-end;
445
484
  justify-content: flex-start;
446
485
  padding: var(--esp-image-overlay-padding, var(--esp-size-padding-page));
@@ -452,10 +491,90 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
452
491
  );
453
492
  pointer-events: none;
454
493
  }
494
+ :host([banner]) .frame:is([data-grown], [data-placement="band"]) .overlay {
495
+ position: relative;
496
+ inset: auto;
497
+ grid-area: 1 / 1;
498
+ }
455
499
  .overlay slot::slotted(*) {
456
500
  color: inherit !important;
457
501
  pointer-events: auto;
458
502
  }
503
+
504
+ .stack {
505
+ display: contents;
506
+ }
507
+ .overlay slot[name="overlay"]::slotted(*) {
508
+ max-inline-size: var(--esp-image-overlay-measure, none);
509
+ }
510
+
511
+ .frame[data-overlay-stack] .stack {
512
+ display: flex;
513
+ flex-direction: column;
514
+ align-items: start;
515
+ min-inline-size: 0;
516
+ max-inline-size: var(--esp-image-overlay-measure, 36rem);
517
+ }
518
+ .frame[data-overlay-stack][data-content-position="bottom"] .stack,
519
+ .frame[data-overlay-stack][data-content-position="center"] .stack,
520
+ .frame[data-overlay-stack][data-content-position="top"] .stack {
521
+ align-items: center;
522
+ }
523
+ .frame[data-overlay-stack][data-content-position$="-end"] .stack {
524
+ align-items: end;
525
+ }
526
+ .frame[data-overlay-stack] .stack slot::slotted(*) {
527
+ max-inline-size: 100%;
528
+ margin-block: 0 !important;
529
+ }
530
+
531
+ .frame[data-overlay-stack][data-overlay-headline]
532
+ .stack
533
+ slot[name="overlay-supporting"]::slotted(*) {
534
+ margin-block-start: var(--esp-image-overlay-gap, var(--esp-size-small, 0.75rem)) !important;
535
+ }
536
+ .frame[data-overlay-stack]:is([data-overlay-headline], [data-overlay-supporting])
537
+ .stack
538
+ slot[name="overlay-action"]::slotted(*) {
539
+ margin-block-start: calc(
540
+ 2 * var(--esp-image-overlay-gap, var(--esp-size-small, 0.75rem))
541
+ ) !important;
542
+ }
543
+
544
+ .overlay slot[name="overlay-supporting"]::slotted(*) {
545
+ font-family: var(--esp-font-body, inherit);
546
+ font-weight: var(--esp-type-lead-font-weight, var(--esp-font-weight-body, 400));
547
+ font-size: var(--esp-type-lead-font-size, 1.25rem);
548
+ line-height: 1.4;
549
+ }
550
+
551
+ .overlay slot[name="overlay-action"]::slotted(a),
552
+ .overlay slot[name="overlay-action"]::slotted(button) {
553
+ display: inline-flex;
554
+ align-items: center;
555
+ justify-content: center;
556
+ box-sizing: border-box;
557
+ min-block-size: 2.75rem;
558
+ padding: 0.5em 1.25em;
559
+ border: 2px solid currentColor;
560
+ border-radius: var(--esp-size-border-radius, 0.375rem);
561
+ background: transparent;
562
+ font-family: var(--esp-font-body, inherit);
563
+ font-size: var(--esp-type-normal, 1rem);
564
+ font-weight: 600;
565
+ line-height: 1.2;
566
+ text-align: center;
567
+ cursor: pointer;
568
+ }
569
+ .overlay slot[name="overlay-action"]::slotted(a:hover),
570
+ .overlay slot[name="overlay-action"]::slotted(button:hover) {
571
+ background: color-mix(in oklch, currentColor 14%, transparent);
572
+ }
573
+ .overlay slot[name="overlay-action"]::slotted(:focus-visible) {
574
+ outline: 2px solid currentColor;
575
+ outline-offset: 3px;
576
+ box-shadow: 0 0 0 7px var(--_esp-image-scrim-resolved);
577
+ }
459
578
  .frame[data-content-position="bottom"] .overlay {
460
579
  justify-content: center;
461
580
  text-align: center;
@@ -469,6 +588,14 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
469
588
  justify-content: center;
470
589
  text-align: center;
471
590
  }
591
+ .frame[data-content-position="middle-start"] .overlay {
592
+ align-items: center;
593
+ }
594
+ .frame[data-content-position="middle-end"] .overlay {
595
+ align-items: center;
596
+ justify-content: flex-end;
597
+ text-align: end;
598
+ }
472
599
  .frame[data-content-position="top-start"] .overlay {
473
600
  align-items: flex-start;
474
601
  }
@@ -483,6 +610,32 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
483
610
  text-align: end;
484
611
  }
485
612
 
613
+
614
+ :host([banner]) .frame[data-placement="band"] {
615
+ grid-template: minmax(0, 1fr) auto / minmax(0, 1fr);
616
+ }
617
+ :host([banner]) .frame[data-placement="band"]::before {
618
+ display: none;
619
+ }
620
+ :host([banner]) .frame[data-placement="band"] .image {
621
+ position: relative;
622
+ inset: auto;
623
+ grid-area: 1 / 1;
624
+ align-self: stretch;
625
+ block-size: auto;
626
+ aspect-ratio: var(--_esp-image-frame-aspect-ratio, auto);
627
+ }
628
+ :host([banner]) .frame[data-placement="band"] .banner-layers {
629
+ position: relative;
630
+ inset: auto;
631
+ grid-area: 1 / 1;
632
+ }
633
+ :host([banner]) .frame[data-placement="band"] .overlay {
634
+ grid-area: 2 / 1;
635
+ background: var(--_esp-image-scrim-resolved);
636
+ text-shadow: none;
637
+ }
638
+
486
639
  .compact-sentinel {
487
640
  position: absolute;
488
641
  inline-size: var(--esp-image-compact-width, 40rem);
@@ -516,17 +669,23 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
516
669
  display: none;
517
670
  }
518
671
 
519
- .overlay {
672
+
673
+ .overlay,
674
+ :host([banner]) .frame[data-placement="band"] .overlay {
520
675
  background: white;
521
676
  color: black;
522
677
  }
523
678
  }
524
679
 
680
+
525
681
  @media (prefers-reduced-motion: reduce) {
526
682
  .banner-layers,
683
+ .image,
684
+ .image picture,
685
+ .image img,
527
686
  .overlay {
528
687
  animation: none !important;
529
688
  transition: none !important;
530
689
  }
531
690
  }
532
- `,A],n([c({attribute:"original-height",type:Number})],i.prototype,"originalHeight",void 0),n([c({attribute:"original-width",type:Number})],i.prototype,"originalWidth",void 0),n([c({attribute:"low-res",type:String})],i.prototype,"imageUrl",void 0),n([c({attribute:"local-image",type:String})],i.prototype,"localImage",void 0),n([c({type:String})],i.prototype,"caption",void 0),n([c({attribute:"sizes",type:String})],i.prototype,"sizes",void 0),n([c({attribute:"loading",type:String})],i.prototype,"loading",void 0),n([c({attribute:"defer-offscreen",type:Boolean})],i.prototype,"deferOffscreen",void 0),n([c({type:Boolean,reflect:!0})],i.prototype,"banner",void 0),n([c({attribute:"banner-scheme",converter:d(j,"auto"),reflect:!0})],i.prototype,"bannerScheme",void 0),n([c({converter:d(w,"auto"),reflect:!0})],i.prototype,"scrim",void 0),n([c({attribute:"scrim-strength",converter:d(S,"medium"),reflect:!0})],i.prototype,"scrimStrength",void 0),n([c({attribute:"scrim-edge",converter:d(z,"none"),reflect:!0})],i.prototype,"scrimEdge",void 0),n([c({type:String,reflect:!0})],i.prototype,"texture",void 0),n([c({attribute:"texture-scale",converter:d(O,"medium"),reflect:!0})],i.prototype,"textureScale",void 0),n([c({attribute:"content-position",converter:d(R,"bottom-start"),reflect:!0})],i.prototype,"contentPosition",void 0),n([c({attribute:"focus",converter:N,reflect:!0})],i.prototype,"focusPoint",void 0),n([c({type:String})],i.prototype,"ratio",void 0),n([c({attribute:"compact-ratio",type:String})],i.prototype,"compactRatio",void 0),n([u()],i.prototype,"renderedWidth",void 0),n([u()],i.prototype,"compact",void 0),n([u()],i.prototype,"overlayHasContent",void 0),i=p=n([E("esp-image")],i);export{i as EspalierImage,f as parseImageRatio};
691
+ `,V],l([c({attribute:"original-height",type:Number})],o.prototype,"originalHeight",void 0),l([c({attribute:"original-width",type:Number})],o.prototype,"originalWidth",void 0),l([c({attribute:"low-res",type:String})],o.prototype,"imageUrl",void 0),l([c({attribute:"local-image",type:String})],o.prototype,"localImage",void 0),l([c({type:String})],o.prototype,"caption",void 0),l([c({attribute:"sizes",type:String})],o.prototype,"sizes",void 0),l([c({attribute:"loading",type:String})],o.prototype,"loading",void 0),l([c({attribute:"defer-offscreen",type:Boolean})],o.prototype,"deferOffscreen",void 0),l([c({type:Boolean,reflect:!0})],o.prototype,"banner",void 0),l([c({attribute:"banner-scheme",converter:v(H,"auto"),reflect:!0})],o.prototype,"bannerScheme",void 0),l([c({converter:v(P,"auto"),reflect:!0})],o.prototype,"scrim",void 0),l([c({attribute:"scrim-strength",converter:v(I,"medium"),reflect:!0})],o.prototype,"scrimStrength",void 0),l([c({attribute:"scrim-edge",converter:v(E,"none"),reflect:!0})],o.prototype,"scrimEdge",void 0),l([c({type:String,reflect:!0})],o.prototype,"texture",void 0),l([c({attribute:"texture-scale",converter:v(A,"medium"),reflect:!0})],o.prototype,"textureScale",void 0),l([c({attribute:"content-position",converter:v(N,"bottom-start"),reflect:!0})],o.prototype,"contentPosition",void 0),l([c({attribute:"compact-placement",converter:v(B,"overlay"),reflect:!0})],o.prototype,"compactPlacement",void 0),l([c({attribute:"focus",converter:K,reflect:!0})],o.prototype,"focusPoint",void 0),l([c({type:String})],o.prototype,"ratio",void 0),l([c({attribute:"compact-ratio",type:String})],o.prototype,"compactRatio",void 0),l([u()],o.prototype,"renderedWidth",void 0),l([u()],o.prototype,"compact",void 0),l([u()],o.prototype,"overlayHasContent",void 0),l([u()],o.prototype,"overlayHasStack",void 0),l([u()],o.prototype,"overlayHasHeadline",void 0),l([u()],o.prototype,"overlayHasSupporting",void 0),l([u()],o.prototype,"grown",void 0),o=y=l([U("esp-image")],o);export{o as EspalierImage,z as parseImageRatio};
@@ -1,18 +1,16 @@
1
- var u=function(a,t,s,e){var i=arguments.length,n=i<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,s):e,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")n=Reflect.decorate(a,t,s,e);else for(var l=a.length-1;l>=0;l--)(o=a[l])&&(n=(i<3?o(n):i>3?o(t,s,n):o(t,s))||n);return i>3&&n&&Object.defineProperty(t,s,n),n};import{css as d,html as m}from"lit";import{customElement as f,property as I,state as y}from"lit/decorators.js";import{classMap as k}from"lit/directives/class-map.js";import{ref as h}from"lit/directives/ref.js";import"./esp-picker-item.js";import"./esp-picker-menu.js";import{samePickerItemDisplay as g}from"./esp-picker-item.js";import{EspalierElementBase as P}from"../shared/esp-element-base.js";import{styleMap as v}from"lit/directives/style-map.js";import{caretUpDown as w}from"../shared/svgs/caret-up-down.js";import{filter as $}from"../shared/svgs/filter.js";import{EspalierPickerBase as p}from"./esp-picker-base.js";import{PickOneSelection as r}from"./pick-one-selection.js";let c=class extends p{constructor(){super(...arguments),this.selection=r.empty(),this.suppressAutoSelect=!1,this.lastMenuPointSelectionAt=Number.NEGATIVE_INFINITY,this.suppressNextHostClick=!1,this.handleHostPointerDown=t=>{this.selectOpenMenuAtPoint(t)&&(this.lastMenuPointSelectionAt=performance.now())},this.handleHostMouseDown=t=>{if(performance.now()-this.lastMenuPointSelectionAt<500){t.preventDefault(),t.stopPropagation();return}this.selectOpenMenuAtPoint(t)}}get selectedItem(){return this.selection.item}decorateFilteredItems(t){if(!this.selectedItem)return t.map(e=>({...e}));const s=this.selectedItem.value;return t.map(e=>({...e,selected:e.value===s}))}get typeaheadRestoreText(){return this.selectedItem?.text??""}get preservesRemoteResultsOnReset(){return this.typeaheadIsRemote&&this.selectedItem!==void 0}get value(){return this.selectedItem?.value}set value(t){const s=this.pickerItems??[];for(const i of s)i.selected=i.value===t;const e=this.pickerMenu.value?.pickerItems;if(e&&e!==s)for(const i of e)i.selected=i.value===t;this.selection=r.resolve(s,t),this.formCtrl.syncValue()}getPickerFormValue(){return this.selectedItem?.value??null}getPickerValidity(){return this.required&&!this.selectedItem?{flags:{valueMissing:!0},message:this.requiredMessage||"Please select an option."}:null}handlePickerReset(){this.selection=r.empty()}handlePickerRestore(t){this.value=t}syncSelectionFromItems(t){if(!t.has("pickerItems"))return;if(this.selection.hasPending){this.value=this.selection.pending;return}if(!this.selectedItem){const e=this.pickerItems.find(i=>i.selected);e&&(this.selection=r.of(e));return}const s=this.pickerItems.find(e=>e.value===this.selectedItem.value);s&&s!==this.selectedItem&&!g(s,this.selectedItem)&&(this.selection=r.of(s))}selectOpenMenuAtPoint(t){return!this.showOptions||!(this.pickerMenu.value?.selectItemAtPoint(t.clientX,t.clientY)??!1)?!1:(this.suppressNextHostClick=!0,t.preventDefault(),t.stopPropagation(),!0)}render(){const{showOptions:t}=this,s={"esp-field":!0,"show-options":t};return m`
1
+ var u=function(h,t,i,e){var s=arguments.length,l=s<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,i):e,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")l=Reflect.decorate(h,t,i,e);else for(var n=h.length-1;n>=0;n--)(o=h[n])&&(l=(s<3?o(l):s>3?o(t,i,l):o(t,i))||l);return s>3&&l&&Object.defineProperty(t,i,l),l};import{css as d,html as m}from"lit";import{customElement as f,property as I,state as y}from"lit/decorators.js";import{classMap as k}from"lit/directives/class-map.js";import{ref as a}from"lit/directives/ref.js";import"./esp-picker-item.js";import"./esp-picker-menu.js";import{samePickerItemDisplay as v}from"./esp-picker-item.js";import{EspalierElementBase as g}from"../shared/esp-element-base.js";import{styleMap as $}from"lit/directives/style-map.js";import{caretUpDown as P}from"../shared/svgs/caret-up-down.js";import{filter as w}from"../shared/svgs/filter.js";import{EspalierPickerBase as p}from"./esp-picker-base.js";import{PickOneSelection as r}from"./pick-one-selection.js";let c=class extends p{constructor(){super(...arguments),this.selection=r.empty(),this.suppressAutoSelect=!1}get selectedItem(){return this.selection.item}decorateFilteredItems(t){if(!this.selectedItem)return t.map(e=>({...e}));const i=this.selectedItem.value;return t.map(e=>({...e,selected:e.value===i}))}get typeaheadRestoreText(){return this.selectedItem?.text??""}get preservesRemoteResultsOnReset(){return this.typeaheadIsRemote&&this.selectedItem!==void 0}get value(){return this.selectedItem?.value}set value(t){const i=this.pickerItems??[];for(const s of i)s.selected=s.value===t;const e=this.pickerMenu.value?.pickerItems;if(e&&e!==i)for(const s of e)s.selected=s.value===t;this.selection=r.resolve(i,t),this.formCtrl.syncValue()}getPickerFormValue(){return this.selectedItem?.value??null}getPickerValidity(){return this.required&&!this.selectedItem?{flags:{valueMissing:!0},message:this.requiredMessage||"Please select an option."}:null}handlePickerReset(){this.selection=r.empty()}handlePickerRestore(t){this.value=t}syncSelectionFromItems(t){if(!t.has("pickerItems"))return;if(this.selection.hasPending){this.value=this.selection.pending;return}if(!this.selectedItem){const e=this.pickerItems.find(s=>s.selected);e&&(this.selection=r.of(e));return}const i=this.pickerItems.find(e=>e.value===this.selectedItem.value);i&&i!==this.selectedItem&&!v(i,this.selectedItem)&&(this.selection=r.of(i))}render(){const{showOptions:t}=this,i={"esp-field":!0,"show-options":t};return m`
2
2
  <div
3
- ${h(this.pickerField)}
3
+ ${a(this.pickerField)}
4
4
  tabindex="-1"
5
- class=${k(s)}
6
- @pointerdown=${this.handleHostPointerDown}
7
- @mousedown=${this.handleHostMouseDown}
8
- @click=${e=>{if(this.suppressNextHostClick){this.suppressNextHostClick=!1,e.preventDefault(),e.stopPropagation();return}if(this.hasAttribute("data-picker-menu-fullscreen")&&this.theInput.value&&e.composedPath().includes(this.theInput.value)){e.stopPropagation();return}this.typeahead&&!this.showOptions&&(this.suppressAutoSelect=!0),this.theInput.value?.focus(),this.showOptions?this.closeAndResetTypeahead():this.showOptions=!0,e.stopPropagation()}}
5
+ class=${k(i)}
6
+ @click=${e=>{if(this.hasAttribute("data-picker-menu-fullscreen")&&this.theInput.value&&e.composedPath().includes(this.theInput.value)){e.stopPropagation();return}this.typeahead&&!this.showOptions&&(this.suppressAutoSelect=!0),this.theInput.value?.focus(),this.showOptions?this.closeAndResetTypeahead():this.showOptions=!0,e.stopPropagation()}}
9
7
  >
10
8
  <section>
11
9
  <input
12
- ${h(this.theInput)}
10
+ ${a(this.theInput)}
13
11
  class="esp-input"
14
12
  value=${this.selectedItem?.text??""}
15
- style=${v(this.selectedItem?.styles??{})}
13
+ style=${$(this.selectedItem?.styles??{})}
16
14
  placeholder=${this.placeholder}
17
15
  ?disabled=${this.disabled}
18
16
  ?readonly=${!this.typeahead}
@@ -22,7 +20,7 @@ var u=function(a,t,s,e){var i=arguments.length,n=i<3?t:e===null?e=Object.getOwnP
22
20
  @keydown=${e=>{if(this.pickerMenu.value&&!this.handleSharedPickerKeydown(e))switch(e.key){case"ArrowDown":case"ArrowUp":case"Enter":case"Home":case"End":this.handleMenuNavigationKey(e.key,e);break}}}
23
21
  />
24
22
  </section>
25
- <label>${this.typeahead&&this.inputFocused?$:w}</label>
23
+ <label>${this.typeahead&&this.inputFocused?w:P}</label>
26
24
  ${this.renderPickerMenuDismissButton()}
27
25
 
28
26
  <esp-picker-menu
@@ -31,15 +29,15 @@ var u=function(a,t,s,e){var i=arguments.length,n=i<3?t:e===null?e=Object.getOwnP
31
29
  .emptyMessage=${this.typeahead?"No matches":""}
32
30
  .label=${this.placeholder}
33
31
  tabindex="-1"
34
- ${h(this.pickerMenu)}
35
- @esp-picker-menu-selection-changed=${e=>{if(e.stopPropagation(),this.typeahead)return;const i=e.detail,n=i.length>0?i[0]:void 0;if(!(i.length>0?this.selectedItem!==n:this.selectedItem!==void 0))return;const l=this.pickerMenu.value?.isVisitorPick===!0;this.selection=l?r.of(n):this.selection.withProvisionalItem(n),l?(this.formCtrl.syncValue(),this.emitValueChanged(this.selectedItem)):this.formCtrl.syncValueSilently()}}
36
- @esp-picker-menu-close-requested=${e=>{if(this.showOptions=!1,this.clearActiveDescendant(),this.typeahead){const i=e.detail,n=i.length>0?i[0]:void 0;if(n?this.selectedItem?.value!==n.value:this.selectedItem!==void 0){if(this.selection=r.of(n),n)for(const l of this.pickerItems)l.selected=l.value===n.value;this.formCtrl.syncValue(),this.emitValueChanged(this.selectedItem)}this.suppressAutoSelect=!0,this.theInput.value?.focus(),this.resetTypeaheadInput()}else this.theInput.value?.focus()}}
32
+ ${a(this.pickerMenu)}
33
+ @esp-picker-menu-selection-changed=${e=>{if(e.stopPropagation(),this.typeahead)return;const s=e.detail,l=s.length>0?s[0]:void 0;if(!(s.length>0?this.selectedItem!==l:this.selectedItem!==void 0))return;const n=this.pickerMenu.value?.isVisitorPick===!0;this.selection=n?r.of(l):this.selection.withProvisionalItem(l),n?(this.formCtrl.syncValue(),this.emitValueChanged(this.selectedItem)):this.formCtrl.syncValueSilently()}}
34
+ @esp-picker-menu-close-requested=${e=>{if(this.showOptions=!1,this.clearActiveDescendant(),this.typeahead){const s=e.detail,l=s.length>0?s[0]:void 0;if(l?this.selectedItem?.value!==l.value:this.selectedItem!==void 0){if(this.selection=r.of(l),l)for(const n of this.pickerItems)n.selected=n.value===l.value;this.formCtrl.syncValue(),this.emitValueChanged(this.selectedItem)}this.suppressAutoSelect=!0,this.theInput.value?.focus(),this.resetTypeaheadInput()}else this.theInput.value?.focus()}}
37
35
  @esp-picker-menu-dismiss-requested=${this.handleMenuDismissRequested}
38
36
  >
39
37
  </esp-picker-menu>
40
38
  </div>
41
- <slot ${h(this.itemsSlot)}></slot>
42
- `}};c.styles=[...P.styles,...p.pickerFieldStyles,d`
39
+ <slot ${a(this.itemsSlot)}></slot>
40
+ `}};c.styles=[...g.styles,...p.pickerFieldStyles,d`
43
41
  .esp-field input.esp-input {
44
42
  width: 0;
45
43
  flex-grow: 1;