@taprootio/espalier 4.10.0 → 4.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- var u=function(a,e,t,r){var s=arguments.length,i=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(a,e,t,r);else for(var n=a.length-1;n>=0;n--)(l=a[n])&&(i=(s<3?l(i):s>3?l(e,t,i):l(e,t))||i);return s>3&&i&&Object.defineProperty(e,t,i),i};import{LitElement as S,css as k,html as g,unsafeCSS as C}from"lit";import{customElement as T,property as P,state as w}from"lit/decorators.js";import{createRef as E,ref as H}from"lit/directives/ref.js";import{styleMap as A}from"lit/directives/style-map.js";import"../shared/virtualizer/lit-virtualizer.js";import{spaceAroundRect as I,viewportSize as m}from"../shared/viewport.js";import{ESP_EVENTS as f}from"../shared/events.js";import{COMPACT_VIEWPORT_MEDIA_QUERY as R,compactViewportMatches as z}from"../shared/responsive.js";import{findContainingPopovers as M}from"../shared/popover-controller.js";const y="highlighted",F=44;function x(a){if(!a)return null;const e=a;return typeof e.enterPickerMenuFullscreen=="function"&&typeof e.exitPickerMenuFullscreen=="function"&&typeof e.pickerMenuIsOpen=="function"?a:null}function $(a){if(M(a).some(t=>[...t.shadowRoot?.querySelectorAll("[popover]")??[]].some(r=>r.matches(":popover-open"))))return!0;let e=a;for(;e;){const t=e.getRootNode();if(e=e.assignedSlot??e.parentElement??(t instanceof ShadowRoot?t.host:null),!e)return!1;if(e.matches(":popover-open")||e.matches("dialog[open], esp-dialog[is-open], esp-flyout[open]"))return!0}return!1}let p=class extends S{get fullscreenPresentation(){return this.hasAttribute("data-fullscreen")}constructor(){super(),this.internals=this.attachInternals(),this.virtualizerRef=E(),this.internalPoolClone=null,this.internalPoolFingerprint=null,this.internalPickScrollTop=null,this.lastPoolFingerprint=null,this.preRenderScrollTop=null,this.openSessionGeneration=0,this.maxAvailableHeight=0,this.lastViewportHeight=0,this.positionTarget=null,this.label="",this.virtualizedItemsPool=[],this.highlightIndex=-1,this.multiSelect=!1,this.loading=!1,this.emptyMessage="",this.handleItemPointerDown=e=>{this.selectItemFromPointerEvent(e)},this.menuDirty=!1,this.settlerActive=!1,this.pendingItemsChanged=!1,this.retargetingSequence=!1,this.renderPickerItem=(e,t)=>{const r={display:"block",cursor:"pointer",width:"100%",...e.styles};return g`<esp-picker-item
1
+ var u=function(a,e,t,r){var s=arguments.length,i=s<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(a,e,t,r);else for(var n=a.length-1;n>=0;n--)(l=a[n])&&(i=(s<3?l(i):s>3?l(e,t,i):l(e,t))||i);return s>3&&i&&Object.defineProperty(e,t,i),i};import{LitElement as C,css as T,html as f,unsafeCSS as E}from"lit";import{customElement as H,property as b,state as S}from"lit/decorators.js";import{createRef as A,ref as R}from"lit/directives/ref.js";import{styleMap as M}from"lit/directives/style-map.js";import"../shared/virtualizer/lit-virtualizer.js";import{spaceAroundRect as x,viewportSize as g}from"../shared/viewport.js";import{ESP_EVENTS as y}from"../shared/events.js";import{COMPACT_VIEWPORT_MEDIA_QUERY as z,compactViewportMatches as F}from"../shared/responsive.js";import{findContainingPopovers as $}from"../shared/popover-controller.js";const v="highlighted",D=44;function w(a){if(!a)return null;const e=a;return typeof e.enterPickerMenuFullscreen=="function"&&typeof e.exitPickerMenuFullscreen=="function"&&typeof e.pickerMenuIsOpen=="function"?a:null}function _(a){if($(a).some(t=>[...t.shadowRoot?.querySelectorAll("[popover]")??[]].some(r=>r.matches(":popover-open"))))return!0;let e=a;for(;e;){const t=e.getRootNode();if(e=e.assignedSlot??e.parentElement??(t instanceof ShadowRoot?t.host:null),!e)return!1;if(e.matches(":popover-open")||e.matches("dialog[open], esp-dialog[is-open], esp-flyout[open]"))return!0}return!1}let c=class extends C{get fullscreenPresentation(){return this.hasAttribute("data-fullscreen")}constructor(){super(),this.internals=this.attachInternals(),this.virtualizerRef=A(),this.internalPoolClone=null,this.internalPoolFingerprint=null,this.internalPickScrollTop=null,this.lastPoolFingerprint=null,this.preRenderScrollTop=null,this.openSessionGeneration=0,this.maxAvailableHeight=0,this.lastViewportHeight=0,this.positionTarget=null,this.label="",this.virtualizedItemsPool=[],this.highlightIndex=-1,this.multiSelect=!1,this.loading=!1,this.emptyMessage="",this.handleItemPointerDown=e=>{this.selectItemFromPointerEvent(e)},this.menuDirty=!1,this.settlerActive=!1,this.pendingItemsChanged=!1,this.retargetingSequence=!1,this.renderPickerItem=(e,t)=>{const r={display:"block",cursor:"pointer",width:"100%",...e.styles};return f`<esp-picker-item
2
2
  class="picker-item"
3
3
  data-picker-index=${t}
4
4
  .text=${e.text}
@@ -6,19 +6,19 @@ var u=function(a,e,t,r){var s=arguments.length,i=s<3?e:r===null?r=Object.getOwnP
6
6
  .selected=${e.selected}
7
7
  .icon=${e.icon??""}
8
8
  .highlightRanges=${e.highlightRanges}
9
- style=${A(r)}
9
+ style=${M(r)}
10
10
  >
11
11
  ${e.slotNodes?.map(s=>s.cloneNode(!0))}
12
- </esp-picker-item>`},this.internals.role="listbox"}connectedCallback(){super.connectedCallback(),this.setAttribute("popover","manual"),this.hasAttribute("role")||this.setAttribute("role","listbox")}willUpdate(e){if(super.willUpdate(e),e.has("virtualizedItemsPool")&&this.preRenderScrollTop===null&&!this.retargetingSequence&&this.matches(":popover-open")){const t=this.virtualizerRef.value?.scrollTop??0;t>0&&(this.preRenderScrollTop=t)}}updated(e){super.updated(e),e.has("multiSelect")&&(this.internals.ariaMultiSelectable=String(this.multiSelect),this.setAttribute("aria-multiselectable",String(this.multiSelect))),e.has("label")&&(this.internals.ariaLabel=this.label,this.label?this.setAttribute("aria-label",this.label):this.removeAttribute("aria-label"));const t=e.has("virtualizedItemsPool");let r=!1;if(t){const s=this.virtualizedItemsPool.map(l=>`${l.value}\0${l.text}\0${l.selected===!0}`),i=this.virtualizedItemsPool===this.internalPoolClone||this.internalPoolFingerprint!==null&&this.internalPoolFingerprint.length===s.length&&this.internalPoolFingerprint.every((l,n)=>l===s[n]);this.internalPoolClone=null,i||(this.internalPoolFingerprint=null,this.internalPickScrollTop=null),r=!i&&(this.lastPoolFingerprint===null||this.lastPoolFingerprint.length!==s.length||this.lastPoolFingerprint.some((l,n)=>l!==s[n])),this.lastPoolFingerprint=s}(t||e.has("loading"))&&this.maxAvailableHeight>0&&this.matches(":popover-open")&&(this.pendingItemsChanged||=r,this.menuDirty=!0,this.settleMenuAfterUpdate())}get pickerItems(){return this.virtualizedItemsPool}set pickerItems(e){const t=this.virtualizedItemsPool.filter(i=>i.selected).map(i=>i.value);this.virtualizedItemsPool=e;const r=e.filter(i=>i.selected),s=r.map(i=>i.value);(t.length!==s.length||t.some((i,l)=>i!==s[l]))&&this.dispatchEvent(new CustomEvent(f.PICKER_MENU_SELECTION_CHANGED,{detail:r,bubbles:!0,composed:!0}))}setHighlight(e){const t=this.virtualizedItemsPool;if(t.length===0)return;(this.highlightIndex<0||this.highlightIndex>t.length-1)&&(this.highlightIndex=e);const r=this.virtualizerRef.value;r&&r.scrollToIndex(this.highlightIndex,"nearest"),this.applyHighlightClass()}async setHighlightAsync(e){const t=this.openSessionGeneration,r=()=>t!==this.openSessionGeneration||!this.isConnected,s=this.virtualizedItemsPool;if(s.length===0)return;(this.highlightIndex<0||this.highlightIndex>s.length-1)&&(this.highlightIndex=e);const i=this.virtualizerRef.value;if(i){if(await this.stableLayout(i),r())return;const l=i.scrollTop;for(let n=0;n<3;n+=1)try{i.scrollToIndex(this.highlightIndex,"nearest");break}catch{if(await this.stableLayout(i),r()||i.scrollTop!==l)return}if(await this.stableLayout(i),r())return}this.applyHighlightWithRetry(3)}applyHighlightClass(){const e=this.getHighlightedElement();e&&(this.clearHighlight(),e.classList.add(y))}clearHighlight(){const e=this.virtualizerRef.value;if(e)for(const t of e.querySelectorAll(`esp-picker-item.${y}`))t.classList.remove(y)}resetHighlight(){this.clearHighlight();const e=this.virtualizedItemsPool.find(t=>t.selected);this.highlightIndex=e?this.virtualizedItemsPool.indexOf(e):-1}applyHighlightWithRetry(e){if(!this.isConnected||!this.matches(":popover-open"))return;const t=this.getHighlightedElement();if(t){this.clearHighlight(),t.classList.add(y);return}e>0&&requestAnimationFrame(()=>this.applyHighlightWithRetry(e-1))}getHighlightedElement(){if(this.highlightIndex<0)return null;const e=this.virtualizerRef.value;if(!e)return null;const t=e.querySelectorAll("esp-picker-item");for(const r of t)if(this.virtualizedItemsPool.findIndex(i=>i.value===r.value&&i.text===r.text)===this.highlightIndex)return r;return null}pickItem(e){const t=this.virtualizerRef.value?.scrollTop??0;this.preRenderScrollTop===null&&t>0&&(this.preRenderScrollTop=t),t>0&&(this.internalPickScrollTop=t);for(const i of this.pickerItems)i===e?i.selected=!i.selected:this.multiSelect||(i.selected=!1);const r=this.virtualizedItemsPool.indexOf(e);if(r!==-1){this.highlightIndex=r;const i=this.getHighlightedElement();i&&(this.clearHighlight(),i.classList.add(y))}const s=[...this.pickerItems];this.internalPoolClone=s,this.internalPoolFingerprint=s.map(i=>`${i.value}\0${i.text}\0${i.selected===!0}`),this.pickerItems=s,this.dispatchEvent(new CustomEvent(f.PICKER_MENU_SELECTION_CHANGED,{detail:this.pickerItems.filter(i=>i.selected),bubbles:!0,composed:!0})),this.multiSelect||this.dispatchEvent(new CustomEvent(f.PICKER_MENU_CLOSE_REQUESTED,{detail:this.pickerItems.filter(i=>i.selected),bubbles:!0,composed:!0}))}selectItemByIndex(e){const t=Number.isInteger(e)?this.virtualizedItemsPool[e]:void 0;return t?(this.pickItem(t),!0):!1}getPickerItemElementAtPoint(e,t){const r=this.shadowRoot?.querySelectorAll("esp-picker-item[data-picker-index]");if(!r)return null;for(const s of r){const i=s.getBoundingClientRect();if(e>=i.left&&e<=i.right&&t>=i.top&&t<=i.bottom)return s}return null}selectPickerItemElement(e){return e?this.selectItemByIndex(Number(e.dataset.pickerIndex)):!1}selectItemAtPoint(e,t){return this.selectPickerItemElement(this.getPickerItemElementAtPoint(e,t))}selectItemFromPointerEvent(e){const t=e.composedPath().find(s=>s instanceof HTMLElement&&s.matches("esp-picker-item[data-picker-index]"));return this.selectPickerItemElement(t??this.getPickerItemElementAtPoint(e.clientX,e.clientY))?(e.preventDefault(),e.stopPropagation(),!0):!1}requestDismiss(){this.dispatchEvent(new CustomEvent(f.PICKER_MENU_DISMISS_REQUESTED,{bubbles:!0,composed:!0,cancelable:!0}))&&this.hideMenu()}clearFullscreenTarget(e=this.positionTarget){x(e)?.exitPickerMenuFullscreen()}syncPresentation(e){const t=this.positionTarget;t&&t!==e&&this.clearFullscreenTarget(t),this.positionTarget=e;const r=x(e),s=z()&&r!==null&&!$(e);if(!s)return this.clearFullscreenTarget(e),this.toggleAttribute("data-fullscreen",!1),{fullscreen:s,rect:e.getBoundingClientRect()};const i=r.enterPickerMenuFullscreen();return i?(this.toggleAttribute("data-fullscreen",!0),{fullscreen:s,rect:i}):(this.clearFullscreenTarget(e),this.toggleAttribute("data-fullscreen",!1),{fullscreen:!1,rect:e.getBoundingClientRect()})}applyFullscreenGeometry(e){const{height:t,width:r}=m(),s=Math.min(Math.max(e.bottom,F),t);this.maxAvailableHeight=Math.max(t-s,0),this.lastViewportHeight=t;const i={viewportWidth:r,viewportHeight:t,inputBottom:s};this.lastFullscreenGeometry?.viewportWidth===i.viewportWidth&&this.lastFullscreenGeometry.viewportHeight===i.viewportHeight&&this.lastFullscreenGeometry.inputBottom===i.inputBottom||(this.lastFullscreenGeometry=i,this.style.setProperty("height",`${t}px`),this.style.setProperty("width",`${r}px`),this.style.setProperty("min-width",`${r}px`),this.style.setProperty("left","0px"),this.style.setProperty("top","0px"),this.style.removeProperty("bottom"),this.style.setProperty("--_esp-picker-menu-input-bottom",`${s}px`))}clearFullscreenGeometry(){this.lastFullscreenGeometry=void 0,this.style.removeProperty("height"),this.style.removeProperty("width"),this.style.removeProperty("min-width"),this.style.removeProperty("left"),this.style.removeProperty("top"),this.style.removeProperty("bottom"),this.style.removeProperty("--_esp-picker-menu-input-bottom")}positionSelf(e){this.resetSettleState();const{fullscreen:t,rect:r}=this.syncPresentation(e),{height:s}=m();let i;if(t)this.applyFullscreenGeometry(r),i=this.maxAvailableHeight;else{this.clearFullscreenGeometry();const{spaceAbove:o,spaceBelow:h}=I(r,s);i=Math.max(Math.max(o,h)-75,0),this.maxAvailableHeight=i,this.lastViewportHeight=s,this.style.setProperty("height",`${i}px`),this.style.setProperty("min-width",`${r.width}px`),this.style.setProperty("left",`${r.left}px`),this.style.removeProperty("top"),this.style.removeProperty("bottom"),o>h?this.style.setProperty("bottom",`${s-r.top}px`):this.style.setProperty("top",`${r.bottom}px`)}this.classList.remove("visible"),this.matches(":popover-open")||this.showPopover();const l=this.pickerItems.find(o=>o.selected);this.highlightIndex=l?this.pickerItems.indexOf(l):0,this.openSessionGeneration+=1;const n=this.openSessionGeneration;this.setHighlightAsync(0).then(()=>{requestAnimationFrame(()=>{n!==this.openSessionGeneration||!this.isConnected||(this.fullscreenPresentation||(this.shrinkToFit(i),this.widenToFitContent(r)),this.classList.add("visible"))})})}async stableLayout(e){for(let t=0;t<20;t+=1){const r=e.layoutComplete;if(!r)return;const s=await Promise.race([r.then(()=>"settled",()=>"superseded"),new Promise(i=>setTimeout(()=>i("deadline"),250))]);if(s==="settled"||s==="deadline"||e.layoutComplete===r)return}}async settleMenuAfterUpdate(){if(this.settlerActive)return;this.settlerActive=!0;const e=this.openSessionGeneration,t=()=>e!==this.openSessionGeneration?!0:!this.isConnected||!this.matches(":popover-open")?(this.menuDirty=!1,this.preRenderScrollTop=null,this.pendingItemsChanged=!1,this.retargetingSequence=!1,this.internalPickScrollTop=null,!0):!1;try{for(let r=0;r<10&&this.menuDirty;r+=1){this.menuDirty=!1;try{await this.updateComplete}catch{this.menuDirty=!1;return}if(t())return;const s=this.virtualizerRef.value;if(!s){requestAnimationFrame(()=>{if(t()||this.fullscreenPresentation)return;const h=this.shadowRoot?.querySelector(".status-message");if(h){const c=Math.min(h.scrollHeight,this.maxAvailableHeight);this.style.setProperty("height",`${c}px`)}});continue}if(await this.stableLayout(s),t())return;if(this.menuDirty)continue;const i=this.preRenderScrollTop??0,l=i>0&&!this.pendingItemsChanged&&!this.retargetingSequence;if(s.scrollTop=0,this.sizeToContent(this.maxAvailableHeight),l&&s.scrollTop<i){if(s.scrollTop=i,await this.stableLayout(s),t())return;if(this.menuDirty)continue}const n=this.virtualizedItemsPool;if(n.length===0)continue;if(this.pendingItemsChanged){this.pendingItemsChanged=!1,this.retargetingSequence=!0,this.preRenderScrollTop=null;const h=n.findIndex(c=>c.selected);h>=0?this.highlightIndex=h:this.highlightIndex>=n.length?this.highlightIndex=n.length-1:this.highlightIndex<0&&(this.highlightIndex=0)}if(this.retargetingSequence){try{s.scrollToIndex(this.highlightIndex,"nearest")}catch{}if(await this.stableLayout(s),t())return;if(this.menuDirty)continue}this.applyHighlightWithRetry(3);const o=Math.max(l?i:0,this.internalPickScrollTop??0);if(o>0){if(s.scrollTop<o&&(s.scrollTop=o),await this.stableLayout(s),t())return;if(this.menuDirty)continue;if(await new Promise(h=>requestAnimationFrame(()=>h())),t())return;if(this.menuDirty)continue;s.scrollTop<o&&(s.scrollTop=o)}this.internalPickScrollTop=null,this.preRenderScrollTop=null,this.retargetingSequence=!1}}finally{this.settlerActive=!1,this.menuDirty&&this.settleMenuAfterUpdate()}}sizeToContent(e){if(this.fullscreenPresentation)return;const t=this.measureContentHeight();t>0&&this.style.setProperty("height",`${Math.min(t,e)}px`)}shrinkToFit(e){if(this.fullscreenPresentation)return;const t=this.measureContentHeight();t>2&&t<e&&this.style.setProperty("height",`${t}px`)}measureContentHeight(){const e=this.virtualizerRef.value;if(!e)return 0;const t=e.querySelectorAll("esp-picker-item");if(t.length===0)return 0;const r=getComputedStyle(this),s=(parseFloat(r.borderTopWidth)||0)+(parseFloat(r.borderBottomWidth)||0),i=this.virtualizedItemsPool.length;if(t.length<i)return e.scrollHeight+s;const l=e.scrollTop;e.scrollTop=0;const n=e.getBoundingClientRect(),o=t[t.length-1].getBoundingClientRect();return l>0&&(e.scrollTop=l),o.bottom-n.top+s}widenToFitContent(e){if(this.fullscreenPresentation)return;const t=this.virtualizerRef.value;if(!t)return;const r=t.querySelectorAll("esp-picker-item");let s=e.width;for(const i of r)s=Math.max(s,i.scrollWidth);if(s+=2,s>e.width){const{width:i}=m(),l=Math.min(s,i-e.left);this.style.setProperty("width",`${l}px`)}}updatePosition(e){const t=x(e);if(t&&!t.pickerMenuIsOpen())return;const r=this.fullscreenPresentation,{fullscreen:s,rect:i}=this.syncPresentation(e),l=r!==s;if(l){const c=this.virtualizerRef.value?.scrollTop??0;c>0&&this.preRenderScrollTop===null&&!this.pendingItemsChanged&&!this.retargetingSequence&&(this.preRenderScrollTop=c),this.openSessionGeneration+=1,this.menuDirty=!0}if(!this.matches(":popover-open")){if(!t?.pickerMenuIsOpen())return;try{this.showPopover()}catch{this.menuDirty=!1,this.clearFullscreenTarget(e),this.removeAttribute("data-fullscreen"),this.clearFullscreenGeometry(),this.requestDismiss();return}this.classList.add("visible")}if(l&&this.settleMenuAfterUpdate(),s){this.applyFullscreenGeometry(i),l&&this.classList.add("visible");return}if(r){this.clearFullscreenGeometry(),this.style.setProperty("min-width",`${i.width}px`);const{height:c}=m(),{spaceAbove:b,spaceBelow:d}=I(i,c),v=Math.max(Math.max(b,d)-75,0);this.maxAvailableHeight=v,this.lastViewportHeight=c,this.style.setProperty("height",`${v}px`),this.sizeToContent(v)}const{height:n}=m();if(n!==this.lastViewportHeight){const{spaceAbove:c,spaceBelow:b}=I(i,n),d=Math.max(Math.max(c,b)-75,0);this.maxAvailableHeight=d,this.lastViewportHeight=n,(parseFloat(this.style.getPropertyValue("height"))||0)>d&&this.style.setProperty("height",`${d}px`),this.sizeToContent(d)}this.style.setProperty("left",`${i.left}px`);const o=i.top,h=n-i.bottom;o>h?(this.style.removeProperty("top"),this.style.setProperty("bottom",`${n-i.top}px`)):(this.style.removeProperty("bottom"),this.style.setProperty("top",`${i.bottom}px`)),l&&this.classList.add("visible")}hideMenu(){this.openSessionGeneration+=1,this.classList.remove("visible"),this.resetSettleState(),this.clearFullscreenTarget(),this.positionTarget=null,this.removeAttribute("data-fullscreen"),this.clearFullscreenGeometry();try{this.hidePopover()}catch{}}resetSettleState(){this.preRenderScrollTop=null,this.pendingItemsChanged=!1,this.retargetingSequence=!1,this.internalPickScrollTop=null,this.menuDirty=!1}disconnectedCallback(){this.hideMenu(),super.disconnectedCallback()}doKeyboardNav(e){const t=this.virtualizedItemsPool;if(t.length!==0)switch(e){case"ArrowDown":this.highlightIndex+=1,this.setHighlight(0);break;case"ArrowUp":this.highlightIndex-=1,this.setHighlight(t.length-1);break;case"Home":this.highlightIndex=0,this.setHighlight(0);break;case"End":this.highlightIndex=t.length-1,this.setHighlight(t.length-1);break;case"Enter":if(this.highlightIndex===-1)return;this.pickItem(t[this.highlightIndex]);break}}render(){let e;return this.loading?e=g`<div class="status-message">Searching…</div>`:this.virtualizedItemsPool.length===0&&this.emptyMessage?e=g`<div class="status-message">${this.emptyMessage}</div>`:e=g`<lit-virtualizer
13
- ${H(this.virtualizerRef)}
12
+ </esp-picker-item>`},this.internals.role="listbox"}connectedCallback(){super.connectedCallback(),this.setAttribute("popover","manual"),this.hasAttribute("role")||this.setAttribute("role","listbox")}willUpdate(e){if(super.willUpdate(e),e.has("virtualizedItemsPool")&&this.preRenderScrollTop===null&&!this.retargetingSequence&&this.matches(":popover-open")){const t=this.virtualizerRef.value?.scrollTop??0;t>0&&(this.preRenderScrollTop=t)}}updated(e){super.updated(e),e.has("multiSelect")&&(this.internals.ariaMultiSelectable=String(this.multiSelect),this.setAttribute("aria-multiselectable",String(this.multiSelect))),e.has("label")&&(this.internals.ariaLabel=this.label,this.label?this.setAttribute("aria-label",this.label):this.removeAttribute("aria-label"));const t=e.has("virtualizedItemsPool");let r=!1;if(t){const s=this.virtualizedItemsPool.map(l=>`${l.value}\0${l.text}\0${l.selected===!0}`),i=this.virtualizedItemsPool===this.internalPoolClone||this.internalPoolFingerprint!==null&&this.internalPoolFingerprint.length===s.length&&this.internalPoolFingerprint.every((l,n)=>l===s[n]);this.internalPoolClone=null,i||(this.internalPoolFingerprint=null,this.internalPickScrollTop=null),r=!i&&(this.lastPoolFingerprint===null||this.lastPoolFingerprint.length!==s.length||this.lastPoolFingerprint.some((l,n)=>l!==s[n])),this.lastPoolFingerprint=s}(t||e.has("loading"))&&this.maxAvailableHeight>0&&this.matches(":popover-open")&&(this.pendingItemsChanged||=r,this.menuDirty=!0,this.settleMenuAfterUpdate())}get pickerItems(){return this.virtualizedItemsPool}set pickerItems(e){const t=this.virtualizedItemsPool.filter(i=>i.selected).map(i=>i.value);this.virtualizedItemsPool=e;const r=e.filter(i=>i.selected),s=r.map(i=>i.value);(t.length!==s.length||t.some((i,l)=>i!==s[l]))&&this.dispatchEvent(new CustomEvent(y.PICKER_MENU_SELECTION_CHANGED,{detail:r,bubbles:!0,composed:!0}))}setHighlight(e){const t=this.virtualizedItemsPool;if(t.length===0)return;(this.highlightIndex<0||this.highlightIndex>t.length-1)&&(this.highlightIndex=e);const r=this.virtualizerRef.value;r&&r.scrollToIndex(this.highlightIndex,"nearest"),this.applyHighlightClass()}async setHighlightAsync(e){const t=this.openSessionGeneration,r=()=>t!==this.openSessionGeneration||!this.isConnected,s=this.virtualizedItemsPool;if(s.length===0)return;(this.highlightIndex<0||this.highlightIndex>s.length-1)&&(this.highlightIndex=e);const i=this.virtualizerRef.value;if(i){if(await this.stableLayout(i),r())return;const l=i.scrollTop;for(let n=0;n<3;n+=1)try{i.scrollToIndex(this.highlightIndex,"nearest");break}catch{if(await this.stableLayout(i),r()||i.scrollTop!==l)return}if(await this.stableLayout(i),r())return}this.applyHighlightWithRetry(3)}applyHighlightClass(){const e=this.getHighlightedElement();e&&(this.clearHighlight(),e.classList.add(v))}clearHighlight(){const e=this.virtualizerRef.value;if(e)for(const t of e.querySelectorAll(`esp-picker-item.${v}`))t.classList.remove(v)}resetHighlight(){this.clearHighlight();const e=this.virtualizedItemsPool.find(t=>t.selected);this.highlightIndex=e?this.virtualizedItemsPool.indexOf(e):-1}applyHighlightWithRetry(e){if(!this.isConnected||!this.matches(":popover-open"))return;const t=this.getHighlightedElement();if(t){this.clearHighlight(),t.classList.add(v);return}e>0&&requestAnimationFrame(()=>this.applyHighlightWithRetry(e-1))}getHighlightedElement(){if(this.highlightIndex<0)return null;const e=this.virtualizerRef.value;if(!e)return null;const t=e.querySelectorAll("esp-picker-item");for(const r of t)if(this.virtualizedItemsPool.findIndex(i=>i.value===r.value&&i.text===r.text)===this.highlightIndex)return r;return null}pickItem(e){const t=this.virtualizerRef.value?.scrollTop??0;this.preRenderScrollTop===null&&t>0&&(this.preRenderScrollTop=t),t>0&&(this.internalPickScrollTop=t);for(const i of this.pickerItems)i===e?i.selected=!i.selected:this.multiSelect||(i.selected=!1);const r=this.virtualizedItemsPool.indexOf(e);if(r!==-1){this.highlightIndex=r;const i=this.getHighlightedElement();i&&(this.clearHighlight(),i.classList.add(v))}const s=[...this.pickerItems];this.internalPoolClone=s,this.internalPoolFingerprint=s.map(i=>`${i.value}\0${i.text}\0${i.selected===!0}`),this.pickerItems=s,this.dispatchEvent(new CustomEvent(y.PICKER_MENU_SELECTION_CHANGED,{detail:this.pickerItems.filter(i=>i.selected),bubbles:!0,composed:!0})),this.multiSelect||this.dispatchEvent(new CustomEvent(y.PICKER_MENU_CLOSE_REQUESTED,{detail:this.pickerItems.filter(i=>i.selected),bubbles:!0,composed:!0}))}selectItemByIndex(e){const t=Number.isInteger(e)?this.virtualizedItemsPool[e]:void 0;return t?(this.pickItem(t),!0):!1}getPickerItemElementAtPoint(e,t){const r=this.shadowRoot?.querySelectorAll("esp-picker-item[data-picker-index]");if(!r)return null;for(const s of r){const i=s.getBoundingClientRect();if(e>=i.left&&e<=i.right&&t>=i.top&&t<=i.bottom)return s}return null}selectPickerItemElement(e){return e?this.selectItemByIndex(Number(e.dataset.pickerIndex)):!1}selectItemAtPoint(e,t){return this.selectPickerItemElement(this.getPickerItemElementAtPoint(e,t))}selectItemFromPointerEvent(e){const t=e.composedPath().find(s=>s instanceof HTMLElement&&s.matches("esp-picker-item[data-picker-index]"));return this.selectPickerItemElement(t??this.getPickerItemElementAtPoint(e.clientX,e.clientY))?(e.preventDefault(),e.stopPropagation(),!0):!1}requestDismiss(){this.dispatchEvent(new CustomEvent(y.PICKER_MENU_DISMISS_REQUESTED,{bubbles:!0,composed:!0,cancelable:!0}))&&this.hideMenu()}clearFullscreenTarget(e=this.positionTarget){w(e)?.exitPickerMenuFullscreen()}syncPresentation(e){const t=this.positionTarget;t&&t!==e&&this.clearFullscreenTarget(t),this.positionTarget=e;const r=w(e),s=F()&&r!==null&&!_(e);if(!s)return this.clearFullscreenTarget(e),this.toggleAttribute("data-fullscreen",!1),{fullscreen:s,rect:e.getBoundingClientRect()};const i=r.enterPickerMenuFullscreen();return i?(this.toggleAttribute("data-fullscreen",!0),{fullscreen:s,rect:i}):(this.clearFullscreenTarget(e),this.toggleAttribute("data-fullscreen",!1),{fullscreen:!1,rect:e.getBoundingClientRect()})}applyFullscreenGeometry(e){const{height:t,width:r}=g(),s=Math.min(Math.max(e.bottom,D),t);this.maxAvailableHeight=Math.max(t-s,0),this.lastViewportHeight=t;const i={viewportWidth:r,viewportHeight:t,inputBottom:s};this.lastFullscreenGeometry?.viewportWidth===i.viewportWidth&&this.lastFullscreenGeometry.viewportHeight===i.viewportHeight&&this.lastFullscreenGeometry.inputBottom===i.inputBottom||(this.lastFullscreenGeometry=i,this.style.setProperty("height",`${t}px`),this.style.setProperty("width",`${r}px`),this.style.setProperty("min-width",`${r}px`),this.style.setProperty("left","0px"),this.style.setProperty("top","0px"),this.style.removeProperty("bottom"),this.style.setProperty("--_esp-picker-menu-input-bottom",`${s}px`))}clearFullscreenGeometry(){this.lastFullscreenGeometry=void 0,this.style.removeProperty("height"),this.style.removeProperty("width"),this.style.removeProperty("min-width"),this.style.removeProperty("left"),this.style.removeProperty("top"),this.style.removeProperty("bottom"),this.style.removeProperty("--_esp-picker-menu-input-bottom")}positionSelf(e){this.resetSettleState();const{fullscreen:t,rect:r}=this.syncPresentation(e),{height:s}=g();let i;if(t)this.applyFullscreenGeometry(r),i=this.maxAvailableHeight;else{this.clearFullscreenGeometry();const{spaceAbove:o,spaceBelow:h}=x(r,s);i=Math.max(Math.max(o,h)-75,0),this.maxAvailableHeight=i,this.lastViewportHeight=s,this.style.setProperty("height",`${i}px`),this.style.setProperty("min-width",`${r.width}px`),this.style.setProperty("left",`${r.left}px`),this.style.removeProperty("top"),this.style.removeProperty("bottom"),o>h?this.style.setProperty("bottom",`${s-r.top}px`):this.style.setProperty("top",`${r.bottom}px`)}this.classList.remove("visible"),this.matches(":popover-open")||this.showPopover();const l=this.pickerItems.find(o=>o.selected);this.highlightIndex=l?this.pickerItems.indexOf(l):0,this.openSessionGeneration+=1;const n=this.openSessionGeneration;this.setHighlightAsync(0).then(()=>{requestAnimationFrame(()=>{n!==this.openSessionGeneration||!this.isConnected||(this.fullscreenPresentation||(this.shrinkToFit(i),this.widenToFitContent(r)),this.classList.add("visible"))})})}async stableLayout(e){for(let t=0;t<20;t+=1){const r=e.layoutComplete;if(!r)return;const s=await Promise.race([r.then(()=>"settled",()=>"superseded"),new Promise(i=>setTimeout(()=>i("deadline"),250))]);if(s==="settled"||s==="deadline"||e.layoutComplete===r)return}}async settleMenuAfterUpdate(){if(this.settlerActive)return;this.settlerActive=!0;const e=this.openSessionGeneration,t=()=>e!==this.openSessionGeneration?!0:!this.isConnected||!this.matches(":popover-open")?(this.menuDirty=!1,this.preRenderScrollTop=null,this.pendingItemsChanged=!1,this.retargetingSequence=!1,this.internalPickScrollTop=null,!0):!1;try{for(let r=0;r<10&&this.menuDirty;r+=1){this.menuDirty=!1;try{await this.updateComplete}catch{this.menuDirty=!1;return}if(t())return;const s=this.virtualizerRef.value;if(!s){requestAnimationFrame(()=>{if(t()||this.fullscreenPresentation)return;const h=this.shadowRoot?.querySelector(".status-message");if(h){const m=Math.min(h.scrollHeight,this.maxAvailableHeight);this.style.setProperty("height",`${m}px`)}});continue}if(await this.stableLayout(s),t())return;if(this.menuDirty)continue;const i=this.preRenderScrollTop??0,l=i>0&&!this.pendingItemsChanged&&!this.retargetingSequence;if(s.scrollTop=0,this.sizeToContent(this.maxAvailableHeight),l&&s.scrollTop<i){if(s.scrollTop=i,await this.stableLayout(s),t())return;if(this.menuDirty)continue}const n=this.virtualizedItemsPool;if(n.length===0)continue;if(this.pendingItemsChanged){this.pendingItemsChanged=!1,this.retargetingSequence=!0,this.preRenderScrollTop=null;const h=n.findIndex(m=>m.selected);h>=0?this.highlightIndex=h:this.highlightIndex>=n.length?this.highlightIndex=n.length-1:this.highlightIndex<0&&(this.highlightIndex=0)}if(this.retargetingSequence){try{s.scrollToIndex(this.highlightIndex,"nearest")}catch{}if(await this.stableLayout(s),t())return;if(this.menuDirty)continue}this.applyHighlightWithRetry(3);const o=Math.max(l?i:0,this.internalPickScrollTop??0);if(o>0){if(s.scrollTop<o&&(s.scrollTop=o),await this.stableLayout(s),t())return;if(this.menuDirty)continue;if(await new Promise(h=>requestAnimationFrame(()=>h())),t())return;if(this.menuDirty)continue;s.scrollTop<o&&(s.scrollTop=o)}this.internalPickScrollTop=null,this.preRenderScrollTop=null,this.retargetingSequence=!1}}finally{this.settlerActive=!1,this.menuDirty&&this.settleMenuAfterUpdate()}}sizeToContent(e){if(this.fullscreenPresentation)return;const t=this.measureContentHeight();t>0&&this.style.setProperty("height",`${Math.min(t,e)}px`)}shrinkToFit(e){if(this.fullscreenPresentation)return;const t=this.measureContentHeight();t>2&&t<e&&this.style.setProperty("height",`${t}px`)}measureContentHeight(){const e=this.virtualizerRef.value;if(!e)return 0;const t=e.querySelectorAll("esp-picker-item");if(t.length===0)return 0;const r=getComputedStyle(this),s=(parseFloat(r.borderTopWidth)||0)+(parseFloat(r.borderBottomWidth)||0),i=this.virtualizedItemsPool.length;if(t.length<i)return e.scrollHeight+s;const l=e.scrollTop;e.scrollTop=0;const n=e.getBoundingClientRect(),o=t[t.length-1].getBoundingClientRect();return l>0&&(e.scrollTop=l),o.bottom-n.top+s}widenToFitContent(e){if(this.fullscreenPresentation)return;const t=this.virtualizerRef.value;if(!t)return;const r=t.querySelectorAll("esp-picker-item");let s=e.width;for(const i of r)s=Math.max(s,i.scrollWidth);if(s+=2,s>e.width){const{width:i}=g(),l=Math.min(s,i);this.style.setProperty("width",`${l}px`),this.style.setProperty("left",`${Math.max(0,Math.min(e.left,i-l))}px`)}}updatePosition(e){const t=w(e);if(t&&!t.pickerMenuIsOpen())return;const r=this.fullscreenPresentation,{fullscreen:s,rect:i}=this.syncPresentation(e),l=r!==s;if(l){const p=this.virtualizerRef.value?.scrollTop??0;p>0&&this.preRenderScrollTop===null&&!this.pendingItemsChanged&&!this.retargetingSequence&&(this.preRenderScrollTop=p),this.openSessionGeneration+=1,this.menuDirty=!0}if(!this.matches(":popover-open")){if(!t?.pickerMenuIsOpen())return;try{this.showPopover()}catch{this.menuDirty=!1,this.clearFullscreenTarget(e),this.removeAttribute("data-fullscreen"),this.clearFullscreenGeometry(),this.requestDismiss();return}this.classList.add("visible")}if(l&&this.settleMenuAfterUpdate(),s){this.applyFullscreenGeometry(i),l&&this.classList.add("visible");return}if(r){this.clearFullscreenGeometry(),this.style.setProperty("min-width",`${i.width}px`);const{height:p}=g(),{spaceAbove:I,spaceBelow:d}=x(i,p),P=Math.max(Math.max(I,d)-75,0);this.maxAvailableHeight=P,this.lastViewportHeight=p,this.style.setProperty("height",`${P}px`),this.sizeToContent(P)}const{height:n}=g();if(n!==this.lastViewportHeight){const{spaceAbove:p,spaceBelow:I}=x(i,n),d=Math.max(Math.max(p,I)-75,0);this.maxAvailableHeight=d,this.lastViewportHeight=n,(parseFloat(this.style.getPropertyValue("height"))||0)>d&&this.style.setProperty("height",`${d}px`),this.sizeToContent(d)}const{width:o}=g(),h=this.getBoundingClientRect().width;this.style.setProperty("left",`${Math.max(0,Math.min(i.left,o-h))}px`);const m=i.top,k=n-i.bottom;m>k?(this.style.removeProperty("top"),this.style.setProperty("bottom",`${n-i.top}px`)):(this.style.removeProperty("bottom"),this.style.setProperty("top",`${i.bottom}px`)),l&&this.classList.add("visible")}hideMenu(){this.openSessionGeneration+=1,this.classList.remove("visible"),this.resetSettleState(),this.clearFullscreenTarget(),this.positionTarget=null,this.removeAttribute("data-fullscreen"),this.clearFullscreenGeometry();try{this.hidePopover()}catch{}}resetSettleState(){this.preRenderScrollTop=null,this.pendingItemsChanged=!1,this.retargetingSequence=!1,this.internalPickScrollTop=null,this.menuDirty=!1}disconnectedCallback(){this.hideMenu(),super.disconnectedCallback()}doKeyboardNav(e){const t=this.virtualizedItemsPool;if(t.length!==0)switch(e){case"ArrowDown":this.highlightIndex+=1,this.setHighlight(0);break;case"ArrowUp":this.highlightIndex-=1,this.setHighlight(t.length-1);break;case"Home":this.highlightIndex=0,this.setHighlight(0);break;case"End":this.highlightIndex=t.length-1,this.setHighlight(t.length-1);break;case"Enter":if(this.highlightIndex===-1)return;this.pickItem(t[this.highlightIndex]);break}}render(){let e;return this.loading?e=f`<div class="status-message">Searching…</div>`:this.virtualizedItemsPool.length===0&&this.emptyMessage?e=f`<div class="status-message">${this.emptyMessage}</div>`:e=f`<lit-virtualizer
13
+ ${R(this.virtualizerRef)}
14
14
  scroller
15
15
  .items=${this.virtualizedItemsPool}
16
16
  .renderItem=${this.renderPickerItem}
17
17
  @pointerdown=${this.handleItemPointerDown}
18
- @rangeChanged=${t=>{this.dispatchEvent(new CustomEvent(f.PICKER_MENU_RANGE_CHANGED,{detail:{first:t.first,last:t.last,items:this.virtualizedItemsPool},bubbles:!0,composed:!0}))}}
19
- ></lit-virtualizer>`,g`<div class="menu-content" @click=${t=>t.stopPropagation()}>
18
+ @rangeChanged=${t=>{this.dispatchEvent(new CustomEvent(y.PICKER_MENU_RANGE_CHANGED,{detail:{first:t.first,last:t.last,items:this.virtualizedItemsPool},bubbles:!0,composed:!0}))}}
19
+ ></lit-virtualizer>`,f`<div class="menu-content" @click=${t=>t.stopPropagation()}>
20
20
  ${e}
21
- </div>`}};p.styles=k`
21
+ </div>`}};c.styles=T`
22
22
  :host {
23
23
  position: fixed;
24
24
  inset: unset;
@@ -63,7 +63,7 @@ var u=function(a,e,t,r){var s=arguments.length,i=s<3?e:r===null?r=Object.getOwnP
63
63
  background: var(--esp-color-layer-2);
64
64
  }
65
65
 
66
- @media ${C(R)} {
66
+ @media ${E(z)} {
67
67
  :host([data-fullscreen]) {
68
68
  display: grid;
69
69
  grid-template-rows: var(--_esp-picker-menu-input-bottom, 2.75rem) minmax(0, 1fr);
@@ -89,4 +89,4 @@ var u=function(a,e,t,r){var s=arguments.length,i=s<3?e:r===null?r=Object.getOwnP
89
89
  overscroll-behavior: contain;
90
90
  }
91
91
  }
92
- `,u([P({type:String})],p.prototype,"label",void 0),u([w()],p.prototype,"virtualizedItemsPool",void 0),u([w()],p.prototype,"highlightIndex",void 0),u([P({attribute:"multi-select",type:Boolean})],p.prototype,"multiSelect",void 0),u([P({type:Boolean})],p.prototype,"loading",void 0),u([P({type:String,attribute:"empty-message"})],p.prototype,"emptyMessage",void 0),p=u([T("esp-picker-menu")],p);export{p as EspalierPickerMenu};
92
+ `,u([b({type:String})],c.prototype,"label",void 0),u([S()],c.prototype,"virtualizedItemsPool",void 0),u([S()],c.prototype,"highlightIndex",void 0),u([b({attribute:"multi-select",type:Boolean})],c.prototype,"multiSelect",void 0),u([b({type:Boolean})],c.prototype,"loading",void 0),u([b({type:String,attribute:"empty-message"})],c.prototype,"emptyMessage",void 0),c=u([H("esp-picker-menu")],c);export{c as EspalierPickerMenu};
@@ -269,6 +269,11 @@ export interface EspalierColorPickerEventMap {
269
269
  export interface EspalierFontPickerEventMap {
270
270
  [ESP_EVENTS.VALUE_CHANGED]: CustomEvent<FontPickerValueChangedDetail>;
271
271
  }
272
+ /** Events fired by `<esp-image-picker>`. */
273
+ export interface EspalierImagePickerEventMap {
274
+ [ESP_EVENTS.VALUE_CHANGED]: CustomEvent<string>;
275
+ [ESP_EVENTS.VALIDITY_CHANGED]: CustomEvent<ValidityChangedDetail>;
276
+ }
272
277
  /** Events fired by `<esp-date-picker>`. */
273
278
  export interface EspalierDatePickerEventMap {
274
279
  [ESP_EVENTS.VALUE_CHANGED]: CustomEvent<string>;
@@ -17,6 +17,49 @@ export interface PhotoRow<T extends LayoutImage = LayoutImage> {
17
17
  images: T[];
18
18
  height: number;
19
19
  }
20
+ /** One image's explicit cell geometry in an album row. */
21
+ export interface AlbumLayoutItem<T extends LayoutImage = LayoutImage> {
22
+ /** The source image, retained by reference. */
23
+ image: T;
24
+ /** The rendered cell width in CSS pixels. */
25
+ width: number;
26
+ }
27
+ /**
28
+ * A row in a bounded album layout.
29
+ *
30
+ * `fillsContainer` is true for completed rows, including rows whose cells
31
+ * widen proportionally at a height ceiling and therefore crop their images.
32
+ * `isPartial` identifies the final, under-filled max-count row, which keeps
33
+ * its image proportions and intentionally leaves its trailing space empty.
34
+ */
35
+ export interface AlbumLayoutRow<T extends LayoutImage = LayoutImage> {
36
+ items: AlbumLayoutItem<T>[];
37
+ height: number;
38
+ isPartial: boolean;
39
+ fillsContainer: boolean;
40
+ }
41
+ /** Options for {@link calculateAlbumLayout}. */
42
+ export interface AlbumLayoutOptions {
43
+ /** Available row width in CSS pixels, before gaps. */
44
+ containerWidth: number;
45
+ /** Preferred row height used while grouping images. Defaults to 220. */
46
+ targetRowHeight?: number;
47
+ /** Horizontal gap between cells. Defaults to 8. */
48
+ gap?: number;
49
+ /** Maximum rendered row height in CSS pixels. Defaults to no ceiling. */
50
+ maxRowHeight?: number;
51
+ /** Positive-integer image count that makes a completed row. */
52
+ maxImagesPerRow?: number;
53
+ }
54
+ /** The default viewport-height ceiling used by bounded album consumers. */
55
+ export declare const DEFAULT_ALBUM_MAX_ROW_HEIGHT_VH = 90;
56
+ /**
57
+ * Normalize the public album viewport-height ceiling.
58
+ *
59
+ * The value is deliberately a percentage rather than an arbitrary pixel
60
+ * count, so a consumer can apply the same policy across responsive layouts.
61
+ */
62
+ export declare function normalizeAlbumMaxRowHeightVh(value: unknown): number;
20
63
  /**
21
64
  * Resolve a consumer-provided image-row ceiling to a usable positive integer.
22
65
  * Values outside `1…maximum`, including non-numbers and non-finite values,
@@ -55,3 +98,20 @@ export declare function normalizeMaxImagesPerRow(value: unknown, fallback?: numb
55
98
  * length.
56
99
  */
57
100
  export declare function calculatePhotoLayout<T extends LayoutImage>(images: T[], containerWidth: number, targetRowHeight?: number, gap?: number, maxRowHeight?: number, maxImagesPerRow?: number): PhotoRow<T>[];
101
+ /**
102
+ * Compute bounded album geometry with explicit cell widths.
103
+ *
104
+ * This is the opt-in counterpart to {@link calculatePhotoLayout}. Completed
105
+ * rows always span the available width. When their justified height exceeds
106
+ * `maxRowHeight`, their cells retain their relative widths while expanding to
107
+ * the row width at the ceiling; a renderer can use `object-fit: cover` to crop
108
+ * the resulting cells. A final row below a finite `maxImagesPerRow` instead
109
+ * remains partial and preserves its image proportions. Its height is capped by
110
+ * the tallest preceding row (or the target height when it is the only row) and
111
+ * by `maxRowHeight`.
112
+ *
113
+ * With an omitted or invalid `maxImagesPerRow`, every row remains completed.
114
+ * That preserves the legacy unlimited-row distribution for callers that have
115
+ * not opted into bounded albums.
116
+ */
117
+ export declare function calculateAlbumLayout<T extends LayoutImage>(images: T[], options: AlbumLayoutOptions): AlbumLayoutRow<T>[];
@@ -1 +1 @@
1
- function w(n,I=Number.POSITIVE_INFINITY,o=Number.POSITIVE_INFINITY){return typeof n=="number"&&Number.isInteger(n)&&n>0&&n<=o?n:I}function b(n,I,o=220,i=8,m=Number.POSITIVE_INFINITY,p=Number.POSITIVE_INFINITY){if(n.length===0)return[];const d=w(p),u=e=>e.reduce((r,h)=>r+h.width/h.height,0),s=e=>{const r=(e.length-1)*i;return(I-r)/u(e)},N=e=>e>o?e/o:o/e,l=[];let t=[];const c=(e,r)=>{l.push({images:[...e],height:Math.min(r,m)})};for(let e=0;e<n.length;e++){t.push(n[e]);const h=u(t)*o+(t.length-1)*i>I,g=e===n.length-1;if(h&&t.length>1){const T=s(t),f=s(t.slice(0,-1));N(T)<=N(f)?c(t,T):(t.pop(),e--,c(t,f)),t=[]}else t.length>=d?(c(t,s(t)),t=[]):g&&(c(t,s(t)),t=[])}return l}export{b as calculatePhotoLayout,w as normalizeMaxImagesPerRow};
1
+ const E=90;function H(t){return typeof t=="number"&&Number.isInteger(t)&&t>=1&&t<=100?t:90}function R(t,r=Number.POSITIVE_INFINITY,u=Number.POSITIVE_INFINITY){return typeof t=="number"&&Number.isInteger(t)&&t>0&&t<=u?t:r}function M(t,r,u=220,a=8,w=Number.POSITIVE_INFINITY,d=Number.POSITIVE_INFINITY){if(t.length===0)return[];const f=R(d),N=o=>o.reduce((c,l)=>c+l.width/l.height,0),I=o=>{const c=(o.length-1)*a;return(r-c)/N(o)},p=o=>o>u?o/u:u/o,m=[];let n=[];const g=(o,c)=>{m.push({images:[...o],height:Math.min(c,w)})};for(let o=0;o<t.length;o++){n.push(t[o]);const l=N(n)*u+(n.length-1)*a>r,b=o===t.length-1;if(l&&n.length>1){const i=I(n),e=I(n.slice(0,-1));p(i)<=p(e)?g(n,i):(n.pop(),o--,g(n,e)),n=[]}else n.length>=f?(g(n,I(n)),n=[]):b&&(g(n,I(n)),n=[])}return m}function P(t,r){if(t.length===0)return[];const u=A(r.containerWidth,0),a=W(r.targetRowHeight,220),w=A(r.gap,8),d=W(r.maxRowHeight,Number.POSITIVE_INFINITY),f=R(r.maxImagesPerRow),N=Number.isFinite(f),I=e=>{const s=e.width/e.height;return Number.isFinite(s)&&s>0?s:1},p=e=>e.reduce((s,h)=>s+I(h),0),m=e=>Math.max(u-(e.length-1)*w,0),n=e=>m(e)/p(e),g=e=>e>a?e/a:a/e,o=[];let c=0;const l=e=>{const s=n(e),h=Math.min(s,d),T=m(e),F=h<s?T/p(e):h;o.push({items:e.map(x=>({image:x,width:I(x)*F})),height:h,isPartial:!1,fillsContainer:!0}),c=Math.max(c,h)},b=e=>{const s=Math.min(n(e),d,c||a);o.push({items:e.map(h=>({image:h,width:I(h)*s})),height:s,isPartial:!0,fillsContainer:!1})};let i=[];for(let e=0;e<t.length;e++){i.push(t[e]);const h=p(i)*a+(i.length-1)*w>u,T=e===t.length-1;if(h&&i.length>1){const _=n(i),F=n(i.slice(0,-1));g(_)<=g(F)||(i.pop(),e--),l(i),i=[]}else i.length>=f?(l(i),i=[]):T&&(N&&i.length<f?b(i):l(i),i=[])}return o}function A(t,r){return typeof t=="number"&&Number.isFinite(t)&&t>=0?t:r}function W(t,r){return typeof t=="number"&&t>0&&(Number.isFinite(t)||t===1/0)?t:r}export{E as DEFAULT_ALBUM_MAX_ROW_HEIGHT_VH,P as calculateAlbumLayout,M as calculatePhotoLayout,H as normalizeAlbumMaxRowHeightVh,R as normalizeMaxImagesPerRow};
@@ -1009,6 +1009,18 @@
1009
1009
  "name": "--esp-image-overlay-text-shadow",
1010
1010
  "description": "Overlay text shadow; defaults to a soft polarity-matched halo. Set to `none` to disable."
1011
1011
  },
1012
+ {
1013
+ "name": "--esp-image-picker-option-height",
1014
+ "description": "Height of dropdown images. Images retain their aspect ratio. Default 8rem."
1015
+ },
1016
+ {
1017
+ "name": "--esp-image-picker-option-width",
1018
+ "description": "Width of dropdown images, capped at 40vw on narrow screens. Default 12rem."
1019
+ },
1020
+ {
1021
+ "name": "--esp-image-picker-preview-height",
1022
+ "description": "Height of the large preview above the control. Default 16rem."
1023
+ },
1012
1024
  {
1013
1025
  "name": "--esp-image-preview-border-color",
1014
1026
  "description": "The border color of the preview."
@@ -1428,6 +1428,24 @@
1428
1428
  "component": "esp-image",
1429
1429
  "description": "Overlay text shadow; defaults to a soft polarity-matched halo. Set to `none` to disable."
1430
1430
  },
1431
+ {
1432
+ "name": "--esp-image-picker-option-height",
1433
+ "category": "component",
1434
+ "component": "esp-image-picker",
1435
+ "description": "Height of dropdown images. Images retain their aspect ratio. Default 8rem."
1436
+ },
1437
+ {
1438
+ "name": "--esp-image-picker-option-width",
1439
+ "category": "component",
1440
+ "component": "esp-image-picker",
1441
+ "description": "Width of dropdown images, capped at 40vw on narrow screens. Default 12rem."
1442
+ },
1443
+ {
1444
+ "name": "--esp-image-picker-preview-height",
1445
+ "category": "component",
1446
+ "component": "esp-image-picker",
1447
+ "description": "Height of the large preview above the control. Default 16rem."
1448
+ },
1431
1449
  {
1432
1450
  "name": "--esp-image-preview-border-color",
1433
1451
  "category": "component",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taprootio/espalier",
3
- "version": "4.10.0",
3
+ "version": "4.12.0",
4
4
  "packageManager": "bun@1.3.12",
5
5
  "description": "Espalier — a themeable, accessible, framework-agnostic, enterprise-grade design system built on web standards and love.",
6
6
  "customElements": "custom-elements.json",
@@ -157,6 +157,10 @@
157
157
  "types": "./dist/image-upload/esp-image-upload.d.ts",
158
158
  "import": "./dist/image-upload/esp-image-upload.js"
159
159
  },
160
+ "./image-picker": {
161
+ "types": "./dist/image-picker/esp-image-picker.d.ts",
162
+ "import": "./dist/image-picker/esp-image-picker.js"
163
+ },
160
164
  "./image-upload/helpers": {
161
165
  "types": "./dist/image-upload/image-helpers.d.ts",
162
166
  "import": "./dist/image-upload/image-helpers.js"