@taprootio/espalier 6.0.0 → 6.2.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,12 @@ 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-banner-max-block-size - A soft height cap for a banner: the ratio-sized height is the smaller of the ratio height and this length, and copy that would not fit (spacing included) grows the banner past it. In the compact band it caps only the image box. Unlike `max-block-size`, it never clips copy. Defaults to none.
385
+ * @cssprop --esp-image-banner-block-size - A soft height target for a banner: it replaces the ratio as the banner height (viewport-fill banners), and copy that would not fit grows the banner past it. In the compact band it sizes only the image box. Unlike `block-size`, it never clips copy. Defaults to none.
386
+ * @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.
387
+ * @cssprop --esp-image-static-compact-ratio - Read only by the static `banner-static.css` stylesheet before upgrade: the `compact-ratio` value, if any.
330
388
  * @cssprop --esp-image-overlay-color - Overlay text color; defaults to the theme heading color when the banner polarity matches the scheme.
331
389
  * @cssprop --esp-image-overlay-text-shadow - Overlay text shadow; defaults to a soft polarity-matched halo. Set to `none` to disable.
332
390
  * @docPageTitle Image
@@ -406,8 +464,19 @@ export declare class EspalierImage extends EspalierElementBase {
406
464
  texture: string;
407
465
  /** CSS pitch or discrete SVG-filter variant for the selected texture. */
408
466
  textureScale: ImageTextureScale;
409
- /** Logical position for semantic banner content. */
467
+ /**
468
+ * Logical position for semantic banner content. `middle-start` and
469
+ * `middle-end` center the copy vertically against the inline start or end
470
+ * edge, mirroring in right-to-left text.
471
+ */
410
472
  contentPosition: ImageContentPosition;
473
+ /**
474
+ * Where the overlay copy goes below the compact width. `overlay` (the
475
+ * default) keeps it over the image. `below` moves it into a band under the
476
+ * image, painted in the banner scheme's own surface and ink, for crops that
477
+ * lose their quiet region at narrow widths.
478
+ */
479
+ compactPlacement: ImageCompactPlacement;
411
480
  /** Normalized focal point used for cover cropping. */
412
481
  focusPoint: FocusPoint;
413
482
  /** Banner target aspect ratio, as a positive number or `number / number`. */
@@ -1,40 +1,50 @@
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 n=function(d,e,t,r){var a=arguments.length,i=a<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,s;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(d,e,t,r);else for(var l=d.length-1;l>=0;l--)(s=d[l])&&(i=(a<3?s(i):a>3?s(e,t,i):s(e,t))||i);return a>3&&i&&Object.defineProperty(e,t,i),i},y;import{css as q,html as b,nothing as F}from"lit";import{customElement as U,property as c,state as g}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 H}from"./scrim-reach.js";import"./esp-image-option.js";import{enumConverter as f}from"../shared/enum-converter.js";import{RafThrottle as te}from"../shared/raf-throttle.js";const j=new Set(["auto","none","flat","top","bottom","left","right","radial"]),P=new Set(["soft","medium","strong"]),I=new Set(["none","flush"]),A=new Set(["fine","medium","coarse"]),E=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"]),$=["overlay","overlay-supporting","overlay-action"];function re(d){if(!d)return null;const[e,t=1]=d.split("/").map(a=>Number(a.trim())),r=e/t;return Number.isFinite(r)&&r>0?r:null}const v=new Set;let w=null;const ae={attributeFilter:["dir"],subtree:!0};function W(d,e){if(!(e?!v.has(d)&&!!v.add(d):v.delete(d))||typeof MutationObserver>"u")return;if(w?.disconnect(),v.size===0){w=null;return}w??=new MutationObserver(()=>{for(const a of v)a.requestUpdate()});const r=new Set([document.documentElement]);for(const a of v){let i=a;for(;i;){const s=i.getRootNode();s instanceof ShadowRoot&&r.add(s),i=i instanceof Element&&i.assignedSlot?i.assignedSlot:i.parentNode instanceof ShadowRoot?i.parentNode.host:i.parentNode}}for(const a of r)w.observe(a,ae)}function k(d){const e=[];for(const t of d)getComputedStyle(t).display==="contents"?e.push(...k(t.children)):e.push(t);return e}function ie(d){const e=d.getBoundingClientRect();if(e.width>0||e.height>0)return e;const t=d.ownerDocument.createRange();t.selectNodeContents(d);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.softHeight=!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($.includes(e.target.name)){this.syncOverlaySlots(),this.observeScrimTargets();return}this.requestUpdate()}},this.handleWindowResize=()=>{this.syncSoftHeight()||!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=l=>{const h=this.overlaySlot(l);return h?G(h):!1},t=e("overlay"),r=e("overlay-supporting"),a=r||e("overlay-action"),i=a||t;t!==this.overlayHasHeadline&&(this.overlayHasHeadline=t),r!==this.overlayHasSupporting&&(this.overlayHasSupporting=r),i!==this.overlayHasContent&&(this.overlayHasContent=i),a!==this.overlayHasStack&&(this.overlayHasStack=a);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(a=>{if(this.offscreenObserver===r){if(this.findProjectedImage()!==t){this.syncOffscreenDeferral();return}a.some(i=>i.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(),W(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 a of k(this.overlayElements()))this.scrimObserver.observe(a,{box:"border-box"})}overlayElements(){return $.flatMap(e=>this.overlaySlot(e)?.assignedElements({flatten:!0})??[])}measureScrimReach(){const e=this.shadowRoot?.querySelector(".frame");if(!e||this.syncSoftHeight()||this.syncGrowth(e))return;const t=this.resolvedScrim();if(this.renderedScrim!==null&&t!==this.renderedScrim){this.requestUpdate();return}let r=0;const a=this.shadowRoot?.querySelector('[part="scrim"]');if(this.banner&&this.overlayHasContent&&!this.bandActive()&&a&&Z(t)){const i=a.getBoundingClientRect();if(i.width<=0||i.height<=0)return;const s=H(this.overlayElements().map(ie));r=ee(t,i,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"),a=Number(t.getAttribute("width"));if(!r||!Number.isFinite(a)||a<=0)continue;const i=t.getAttribute("type")??"",s=e.get(i)??[];s.push({url:r,width:a}),e.set(i,s)}return Array.from(e,([t,r])=>({type:t,srcset:r.sort((a,i)=>a.width-i.width).map(a=>`${a.url} ${a.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 a=1/0,i=-1/0;for(const s of k(this.overlayElements())){const l=s.getBoundingClientRect();if(l.width<=0&&l.height<=0)continue;const h=getComputedStyle(s);a=Math.min(a,l.top-(Number.parseFloat(h.marginTop)||0)),i=Math.max(i,l.bottom+(Number.parseFloat(h.marginBottom)||0))}return i>a?r+i-a:null}syncGrowth(e){const t=re(this.resolvedAspectRatio());let r=!1;if(this.banner&&this.overlayHasContent&&!this.bandActive()&&!this.softHeight&&t!==null){const a=e.getBoundingClientRect(),i=this.overlayContentHeight();if(a.width<=0||i===null)return!1;const s=getComputedStyle(this).maxBlockSize,l=this.growthBlock;l&&(Math.abs(a.width-l.width)>1||s!==l.cap||i<l.need-.5)&&(this.growthBlock=null);const h=this.getBoundingClientRect(),m=getComputedStyle(this),p=[m.borderTopWidth,m.borderBottomWidth,m.paddingTop,m.paddingBottom].reduce((x,S)=>x+(Number.parseFloat(S)||0),0),u=h.width/t,_=getComputedStyle(e),M=(Number.parseFloat(_.borderTopWidth)||0)+(Number.parseFloat(_.borderBottomWidth)||0),D=u-p-M;if(this.grown){const x=this.growthCheckPending&&this.growthWidth!==null&&a.width>this.growthWidth+1;this.growthCheckPending=!1;const S=h.height-p<a.height-.5;if(x||S)return this.growthBlock={width:x?this.growthWidth:a.width,cap:s,need:i},this.scheduleGrowthRollback(),!1;r=i>D+.5}else r=this.growthBlock===null&&this.copyClipped(a,_)&&Math.abs(h.height-u)<=1,r&&(this.growthWidth=a.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),a=e.bottom-(Number.parseFloat(t.borderBottomWidth)||0),i=[],s=this.overlayHasStack?this.shadowRoot?.querySelector(".stack"):null;if(s)i.push(s.getBoundingClientRect());else for(const h of k(this.overlayElements())){const m=h.getBoundingClientRect();(m.width>0||m.height>0)&&i.push(m)}const l=H(i);return l!==null&&(l.top<r-.5||l.bottom>a+.5)}readSoftHeight(){if(!this.banner)return!1;const e=getComputedStyle(this),t=a=>!["","none","auto","initial"].includes(e.getPropertyValue(a).trim()),r=t("--esp-image-banner-block-size");return(r||t("--esp-image-banner-max-block-size"))&&(r||this.resolvedAspectRatio()!==null)}syncSoftHeight(){const e=this.readSoftHeight();return e===this.softHeight?!1:(this.softHeight=e,!0)}grownActive(){return(this.grown||this.softHeight)&&this.banner&&!this.bandActive()}syncDirectionTracking(){W(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")&&!j.has(this.scrim)&&(this.scrim="auto"),e.has("bannerScheme")&&!E.has(this.bannerScheme)&&(this.bannerScheme="auto"),e.has("scrimStrength")&&!P.has(this.scrimStrength)&&(this.scrimStrength="medium"),e.has("scrimEdge")&&!I.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),this.softHeight=this.readSoftHeight();const t=X(this.focusPoint),r=Number((t.x*100).toFixed(4)),a=Number((t.y*100).toFixed(4));this.style.setProperty("--_esp-image-object-position",`${r}% ${a}%`);const i=this.resolvedAspectRatio(),s=this.grownActive()||this.bandActive();for(const[p,u]of[["--_esp-image-aspect-ratio",!s],["--_esp-image-frame-aspect-ratio",s]])this.style.setProperty(p,i&&u?i:"auto");this.style.setProperty("--_esp-image-host-block-size",this.banner&&this.softHeight?"fit-content":"auto"),this.syncDirectionTracking();const l=this.resolvedTexture();if(["paper","grain","grunge"].includes(l)){const p=l==="grunge"&&this.resolvedBannerScheme()==="light"?"grunge-light":l;this.style.setProperty("--_esp-image-texture-filter",`url(#${J(p,this.textureScale)})`)}else this.style.removeProperty("--_esp-image-texture-filter");const h=T(l)?void 0:R(l),m=[["--_esp-image-registered-image",h?.image],["--_esp-image-registered-size",h?.size],["--_esp-image-registered-repeat",h?.repeat],["--_esp-image-registered-position",h?.position],["--_esp-image-registered-opacity",h?.opacity?.toString()],["--_esp-image-registered-blend-mode",h?.blendMode]];for(const[p,u]of m)u===void 0?this.style.removeProperty(p):this.style.setProperty(p,u)}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,l=s>0&&this.renderedWidth<s;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 i of t.querySelectorAll("source"))i.setAttribute("sizes",r);const a=this.findProjectedImage(t);a?.hasAttribute("srcset")&&a.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-soft=${this.grownActive()&&this.softHeight}
32
+ ?data-overlay-stack=${this.overlayHasStack}
33
+ ?data-overlay-headline=${this.overlayHasHeadline}
34
+ ?data-overlay-supporting=${this.overlayHasSupporting}
29
35
  >
30
36
  <div part="image" class="image">${this.renderMedia()}</div>
31
- ${$({className:"banner-layers",imagePart:"texture",scrimPart:"scrim",texturePart:"texture"})}
37
+ ${L({className:"banner-layers",imagePart:"texture",scrimPart:"scrim",texturePart:"texture"})}
32
38
  <div part="overlay" class="overlay" ?hidden=${!this.banner||!this.overlayHasContent}>
33
- <slot name="overlay" @slotchange=${this.handleSlotChange}></slot>
39
+ <div class="stack">
40
+ <slot name="overlay" @slotchange=${this.handleSlotChange}></slot>
41
+ <slot name="overlay-supporting" @slotchange=${this.handleSlotChange}></slot>
42
+ <slot name="overlay-action" @slotchange=${this.handleSlotChange}></slot>
43
+ </div>
34
44
  </div>
35
45
  <span class="compact-sentinel" aria-hidden="true"></span>
36
46
  </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=`
47
+ `}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]")),a=r.find(s=>s.textContent===y.projectionStyles);if(a){for(const s of r)s!==a&&s.remove();return}for(const s of r)s.remove();const i=t.ownerDocument.createElement("style");i.dataset.espImageProjectionStyles="",i.textContent=y.projectionStyles,t.append(i)}};o.projectionStyles=`
38
48
  esp-image > picture,
39
49
  esp-image > img {
40
50
  display: block;
@@ -50,7 +60,15 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
50
60
  object-fit: var(--_esp-image-object-fit, cover);
51
61
  object-position: var(--esp-image-object-position, var(--_esp-image-object-position, center));
52
62
  }
53
- `,i.styles=[...y.styles,I`
63
+ @media (prefers-reduced-motion: reduce) {
64
+ esp-image[banner] > picture,
65
+ esp-image[banner] > picture > img,
66
+ esp-image[banner] > img {
67
+ animation: none !important;
68
+ transition: none !important;
69
+ }
70
+ }
71
+ `,o.styles=[...C.styles,q`
54
72
  :host {
55
73
  display: block;
56
74
  aspect-ratio: var(--_esp-image-aspect-ratio, auto);
@@ -70,6 +88,8 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
70
88
  :host([banner]) {
71
89
  --_esp-image-border-default: none;
72
90
  --_esp-image-radius-default: 0;
91
+
92
+ block-size: var(--_esp-image-host-block-size, auto);
73
93
  }
74
94
 
75
95
  [hidden] {
@@ -110,6 +130,34 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
110
130
  z-index: 0;
111
131
  }
112
132
 
133
+
134
+ :host([banner]) .image {
135
+ overflow: clip;
136
+ }
137
+
138
+
139
+ :host([banner]) .frame:is([data-grown], [data-placement="band"]) {
140
+ display: grid;
141
+ grid-template: minmax(0, 1fr) / minmax(0, 1fr);
142
+ }
143
+
144
+ :host([banner]) .frame[data-grown]::before {
145
+ content: "";
146
+ grid-area: 1 / 1;
147
+ aspect-ratio: var(--_esp-image-frame-aspect-ratio, auto);
148
+ block-size: var(--esp-image-banner-block-size, auto);
149
+ max-block-size: var(--esp-image-banner-max-block-size, none);
150
+ }
151
+ :host([banner]) .frame[data-grown] .image {
152
+ position: absolute;
153
+ inset: 0;
154
+ }
155
+
156
+ :host([banner]) .frame[data-soft] {
157
+ min-block-size: inherit;
158
+ max-block-size: inherit;
159
+ }
160
+
113
161
  img {
114
162
  object-fit: var(--_esp-image-object-fit, cover);
115
163
  object-position: var(
@@ -441,6 +489,8 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
441
489
  z-index: 2;
442
490
  inset: 0;
443
491
  display: flex;
492
+
493
+ overflow-wrap: anywhere;
444
494
  align-items: flex-end;
445
495
  justify-content: flex-start;
446
496
  padding: var(--esp-image-overlay-padding, var(--esp-size-padding-page));
@@ -452,10 +502,90 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
452
502
  );
453
503
  pointer-events: none;
454
504
  }
505
+ :host([banner]) .frame:is([data-grown], [data-placement="band"]) .overlay {
506
+ position: relative;
507
+ inset: auto;
508
+ grid-area: 1 / 1;
509
+ }
455
510
  .overlay slot::slotted(*) {
456
511
  color: inherit !important;
457
512
  pointer-events: auto;
458
513
  }
514
+
515
+ .stack {
516
+ display: contents;
517
+ }
518
+ .overlay slot[name="overlay"]::slotted(*) {
519
+ max-inline-size: var(--esp-image-overlay-measure, none);
520
+ }
521
+
522
+ .frame[data-overlay-stack] .stack {
523
+ display: flex;
524
+ flex-direction: column;
525
+ align-items: start;
526
+ min-inline-size: 0;
527
+ max-inline-size: var(--esp-image-overlay-measure, 36rem);
528
+ }
529
+ .frame[data-overlay-stack][data-content-position="bottom"] .stack,
530
+ .frame[data-overlay-stack][data-content-position="center"] .stack,
531
+ .frame[data-overlay-stack][data-content-position="top"] .stack {
532
+ align-items: center;
533
+ }
534
+ .frame[data-overlay-stack][data-content-position$="-end"] .stack {
535
+ align-items: end;
536
+ }
537
+ .frame[data-overlay-stack] .stack slot::slotted(*) {
538
+ max-inline-size: 100%;
539
+ margin-block: 0 !important;
540
+ }
541
+
542
+ .frame[data-overlay-stack][data-overlay-headline]
543
+ .stack
544
+ slot[name="overlay-supporting"]::slotted(*) {
545
+ margin-block-start: var(--esp-image-overlay-gap, var(--esp-size-small, 0.75rem)) !important;
546
+ }
547
+ .frame[data-overlay-stack]:is([data-overlay-headline], [data-overlay-supporting])
548
+ .stack
549
+ slot[name="overlay-action"]::slotted(*) {
550
+ margin-block-start: calc(
551
+ 2 * var(--esp-image-overlay-gap, var(--esp-size-small, 0.75rem))
552
+ ) !important;
553
+ }
554
+
555
+ .overlay slot[name="overlay-supporting"]::slotted(*) {
556
+ font-family: var(--esp-font-body, inherit);
557
+ font-weight: var(--esp-type-lead-font-weight, var(--esp-font-weight-body, 400));
558
+ font-size: var(--esp-type-lead-font-size, 1.25rem);
559
+ line-height: 1.4;
560
+ }
561
+
562
+ .overlay slot[name="overlay-action"]::slotted(a),
563
+ .overlay slot[name="overlay-action"]::slotted(button) {
564
+ display: inline-flex;
565
+ align-items: center;
566
+ justify-content: center;
567
+ box-sizing: border-box;
568
+ min-block-size: 2.75rem;
569
+ padding: 0.5em 1.25em;
570
+ border: 2px solid currentColor;
571
+ border-radius: var(--esp-size-border-radius, 0.375rem);
572
+ background: transparent;
573
+ font-family: var(--esp-font-body, inherit);
574
+ font-size: var(--esp-type-normal, 1rem);
575
+ font-weight: 600;
576
+ line-height: 1.2;
577
+ text-align: center;
578
+ cursor: pointer;
579
+ }
580
+ .overlay slot[name="overlay-action"]::slotted(a:hover),
581
+ .overlay slot[name="overlay-action"]::slotted(button:hover) {
582
+ background: color-mix(in oklch, currentColor 14%, transparent);
583
+ }
584
+ .overlay slot[name="overlay-action"]::slotted(:focus-visible) {
585
+ outline: 2px solid currentColor;
586
+ outline-offset: 3px;
587
+ box-shadow: 0 0 0 7px var(--_esp-image-scrim-resolved);
588
+ }
459
589
  .frame[data-content-position="bottom"] .overlay {
460
590
  justify-content: center;
461
591
  text-align: center;
@@ -469,6 +599,14 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
469
599
  justify-content: center;
470
600
  text-align: center;
471
601
  }
602
+ .frame[data-content-position="middle-start"] .overlay {
603
+ align-items: center;
604
+ }
605
+ .frame[data-content-position="middle-end"] .overlay {
606
+ align-items: center;
607
+ justify-content: flex-end;
608
+ text-align: end;
609
+ }
472
610
  .frame[data-content-position="top-start"] .overlay {
473
611
  align-items: flex-start;
474
612
  }
@@ -483,6 +621,34 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
483
621
  text-align: end;
484
622
  }
485
623
 
624
+
625
+ :host([banner]) .frame[data-placement="band"] {
626
+ grid-template: minmax(0, 1fr) auto / minmax(0, 1fr);
627
+ }
628
+ :host([banner]) .frame[data-placement="band"]::before {
629
+ display: none;
630
+ }
631
+ :host([banner]) .frame[data-placement="band"] .image {
632
+ position: relative;
633
+ inset: auto;
634
+ grid-area: 1 / 1;
635
+ align-self: stretch;
636
+
637
+ block-size: var(--esp-image-banner-block-size, auto);
638
+ max-block-size: var(--esp-image-banner-max-block-size, none);
639
+ aspect-ratio: var(--_esp-image-frame-aspect-ratio, auto);
640
+ }
641
+ :host([banner]) .frame[data-placement="band"] .banner-layers {
642
+ position: relative;
643
+ inset: auto;
644
+ grid-area: 1 / 1;
645
+ }
646
+ :host([banner]) .frame[data-placement="band"] .overlay {
647
+ grid-area: 2 / 1;
648
+ background: var(--_esp-image-scrim-resolved);
649
+ text-shadow: none;
650
+ }
651
+
486
652
  .compact-sentinel {
487
653
  position: absolute;
488
654
  inline-size: var(--esp-image-compact-width, 40rem);
@@ -516,17 +682,23 @@ var n=function(m,e,t,r){var s=arguments.length,a=s<3?e:r===null?r=Object.getOwnP
516
682
  display: none;
517
683
  }
518
684
 
519
- .overlay {
685
+
686
+ .overlay,
687
+ :host([banner]) .frame[data-placement="band"] .overlay {
520
688
  background: white;
521
689
  color: black;
522
690
  }
523
691
  }
524
692
 
693
+
525
694
  @media (prefers-reduced-motion: reduce) {
526
695
  .banner-layers,
696
+ .image,
697
+ .image picture,
698
+ .image img,
527
699
  .overlay {
528
700
  animation: none !important;
529
701
  transition: none !important;
530
702
  }
531
703
  }
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};
704
+ `,V],n([c({attribute:"original-height",type:Number})],o.prototype,"originalHeight",void 0),n([c({attribute:"original-width",type:Number})],o.prototype,"originalWidth",void 0),n([c({attribute:"low-res",type:String})],o.prototype,"imageUrl",void 0),n([c({attribute:"local-image",type:String})],o.prototype,"localImage",void 0),n([c({type:String})],o.prototype,"caption",void 0),n([c({attribute:"sizes",type:String})],o.prototype,"sizes",void 0),n([c({attribute:"loading",type:String})],o.prototype,"loading",void 0),n([c({attribute:"defer-offscreen",type:Boolean})],o.prototype,"deferOffscreen",void 0),n([c({type:Boolean,reflect:!0})],o.prototype,"banner",void 0),n([c({attribute:"banner-scheme",converter:f(E,"auto"),reflect:!0})],o.prototype,"bannerScheme",void 0),n([c({converter:f(j,"auto"),reflect:!0})],o.prototype,"scrim",void 0),n([c({attribute:"scrim-strength",converter:f(P,"medium"),reflect:!0})],o.prototype,"scrimStrength",void 0),n([c({attribute:"scrim-edge",converter:f(I,"none"),reflect:!0})],o.prototype,"scrimEdge",void 0),n([c({type:String,reflect:!0})],o.prototype,"texture",void 0),n([c({attribute:"texture-scale",converter:f(A,"medium"),reflect:!0})],o.prototype,"textureScale",void 0),n([c({attribute:"content-position",converter:f(N,"bottom-start"),reflect:!0})],o.prototype,"contentPosition",void 0),n([c({attribute:"compact-placement",converter:f(B,"overlay"),reflect:!0})],o.prototype,"compactPlacement",void 0),n([c({attribute:"focus",converter:K,reflect:!0})],o.prototype,"focusPoint",void 0),n([c({type:String})],o.prototype,"ratio",void 0),n([c({attribute:"compact-ratio",type:String})],o.prototype,"compactRatio",void 0),n([g()],o.prototype,"renderedWidth",void 0),n([g()],o.prototype,"compact",void 0),n([g()],o.prototype,"overlayHasContent",void 0),n([g()],o.prototype,"overlayHasStack",void 0),n([g()],o.prototype,"overlayHasHeadline",void 0),n([g()],o.prototype,"overlayHasSupporting",void 0),n([g()],o.prototype,"grown",void 0),n([g()],o.prototype,"softHeight",void 0),o=y=n([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;