@taprootio/espalier 4.13.0 → 4.14.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.
- package/CHANGELOG.md +26 -0
- package/custom-elements.json +7966 -7738
- package/dist/header/esp-header.js +6 -6
- package/dist/repeater/esp-repeater.d.ts +88 -9
- package/dist/repeater/esp-repeater.js +67 -17
- package/espalier.css-data.json +3 -3
- package/espalier.token-manifest.json +3 -3
- package/package.json +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
var a=function(h,e,t,s){var n=arguments.length,l=n<3?e:s===null?s=Object.getOwnPropertyDescriptor(e,t):s,r;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")l=Reflect.decorate(h,e,t,s);else for(var d=h.length-1;d>=0;d--)(r=h[d])&&(l=(n<3?r(l):n>3?r(e,t,l):r(e,t))||l);return n>3&&l&&Object.defineProperty(e,t,l),l};import{css as B,html as x,nothing as T}from"lit";import{customElement as k,property as i,state as c}from"lit/decorators.js";import{classMap as A}from"lit/directives/class-map.js";import{styleMap as O}from"lit/directives/style-map.js";import"../burger/esp-burger.js";import{createRef as C,ref as D}from"lit/directives/ref.js";import{EspalierMenu as p}from"../menu/esp-menu.js";import{RafThrottle as _}from"../shared/raf-throttle.js";import{renderConfiguredBrand as R,resolveConfiguredBrand as E}from"../shared/configured-brand.js";import{EspalierElementBase as M}from"../shared/esp-element-base.js";import{ESP_EVENTS as z}from"../shared/events.js";const H="(max-width: 36rem)";function u(h,e){const t=new Set(h);return{allowedValues:t,converter:{fromAttribute(n){return n??e},toAttribute(n){return t.has(n)?n:e}},defaultValue:e}}const j=["standard","centered-brand","centered-menu","extended","extended-centered","minimal"],q=["start","center","end"],V=["truncate","wrap","nowrap"],N=["auto","inline","drawer"],U=["hidden","visible"],g=u(j,"standard"),b=u(q,"start"),f=u(V,"truncate"),v=u(N,"auto"),w=u(U,"hidden");let o=class extends M{constructor(){super(...arguments),this.menuOpen=!1,this.menuTooLarge=!1,this.mobileMenu=!1,this.scrolled=!1,this.hiddenByScroll=!1,this.scrollProgress=0,this.showBurger=!1,this.layout=g.defaultValue,this.brandText="",this.brandLogo="",this.lightBrandLogo="",this.darkBrandLogo="",this.brandHref="",this.brandAlt="",this.brandColor="",this.lightBrandColor="",this.darkBrandColor="",this.brandAlign=b.defaultValue,this.brandWrap=f.defaultValue,this.menuDisplay=v.defaultValue,this.themeToggle=w.defaultValue,this.scrollBehavior="none",this.scrollThreshold=16,this.dockOffset=0,this.drawerTarget="",this.previewCollapseRequested=!1,this.fullBleedContent=!1,this.menuContainer=C(),this.menuButton=C(),this.menu=void 0,this.externalDrawerTarget=null,this.lastScrollY=0,this.lastInlineMenuWidth=0,this.mobileMenuQuery=null,this.menuDrawerListenersAttached=!1,this.observingMenuContainer=!1,this.scrollListenersAttached=!1,this.scrollFrame=new _(()=>this.runScrollStateUpdate()),this.resizeObserver=new ResizeObserver(()=>this.syncMenuLayout()),this.menuChildObserver=null,this.updateScrollState=()=>this.scrollFrame.schedule(),this.handleMobileMenuQueryChange=e=>{this.mobileMenu=e.matches,this.syncMenuLayout(),this.syncExternalDrawerControl()},this.toggleTheme=()=>{const e=this.getThemeRoot();if(!e)return;e.scheme=e.scheme==="dark"?"light":"dark";const t=e.scheme==="dark"?"dark":"light";this.dispatchEvent(new CustomEvent(z.HEADER_THEME_TOGGLE,{detail:{scheme:t},bubbles:!0,composed:!0}))},this.handleMenuToggleClicked=()=>{if(this.menuOpen){this.closeNav();return}this.openNav()},this.onMenuDrawerOpened=()=>{this.menuOpen=!0,document.body.classList.add("menu-open"),this.burger&&(this.burger.menuOpen=!0)},this.onMenuDrawerClosed=()=>{this.menuOpen=!1,document.body.classList.remove("menu-open"),this.burger&&(this.burger.menuOpen=!1),this.demoteMenuToggle()},this.onMenuDrawerPresented=e=>{e.target!==this.menu||!this.menu?.isFullScreenDrawer||this.promoteMenuToggle()},this.menuTogglePromoted=!1,this.lastDrawerBrandKey="",this.inertedHeaderChrome=[]}syncMenuLayout(){if(!this.menuContainer.value||!this.menu||!this.menu.getWidth)return;this.positionPromotedToggle();const e=this.menu.getWidth();e>0&&(this.lastInlineMenuWidth=e);const t=this.lastInlineMenuWidth||e,s=this.getExternalDrawerTarget(),n=this.menuDisplay!=="inline",l=this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal"||this.previewCollapseRequested,r=n&&this.menuDisplay==="auto",d=r?this.layout==="centered-menu"?this.centeredMenuCapacity():this.menuContainer.value.clientWidth:0;this.menuTooLarge=r&&t>d,this.menu.sliding=n&&!s&&this.hasDrawerableContent()&&(this.menuTooLarge||l||this.mobileMenu)}centeredMenuCapacity(){const e=this.menuContainer.value?.parentElement;if(!(e instanceof HTMLElement))return 0;const t=d=>d?d.getBoundingClientRect().width:0,s=getComputedStyle(e),n=e.clientWidth-(Number.parseFloat(s.paddingLeft)||0)-(Number.parseFloat(s.paddingRight)||0),l=e.querySelector(":scope > section.brand"),r=e.querySelector(":scope > section.buttons");return n-t(l)-t(r)+t(r?.querySelector("esp-header-button.menu-toggle"))}menuHasContent(){return!!(this.menu??this.querySelector(':scope > [slot="menu"]'))?.querySelector("esp-menu-item, esp-menu-group")}hasDrawerableContent(){return this.showBurger||!!this.getExternalDrawerTarget()||this.menuHasContent()}getExternalDrawerTarget(){if(!this.drawerTarget)return null;const e=document.getElementById(this.drawerTarget);return e===this.menu?null:e&&"openDrawer"in e&&typeof e.openDrawer=="function"&&"closeDrawer"in e&&typeof e.closeDrawer=="function"?e:null}getBurgerFocusTarget(){const t=this.shadowRoot?.querySelector("esp-header-button.menu-toggle")?.shadowRoot?.querySelector("button"),s=this.menuButton.value?.shadowRoot?.querySelector("button");return t??s??null}getScrollTokens(){const e=this.scrollBehavior.split(/\s+/).map(t=>t.trim().toLowerCase()).filter(Boolean);return new Set(e.filter(t=>t!=="none"))}getEffectiveScrollThreshold(){return Number.isFinite(this.scrollThreshold)?Math.max(0,this.scrollThreshold):0}clearScrollState(){this.scrolled=!1,this.hiddenByScroll=!1,this.scrollProgress=0}runScrollStateUpdate(){const e=this.getScrollTokens();if(!e.size){this.clearScrollState();return}const t=Math.max(0,window.scrollY||document.documentElement.scrollTop||0),s=this.getEffectiveScrollThreshold(),n=Number.isFinite(this.dockOffset)?Math.max(0,this.dockOffset):s,l=t>(e.has("dock")?n:s),r=t>this.lastScrollY,d=e.has("reveal")&&r&&t>s&&!this.menuOpen;if(this.scrolled=l,this.hiddenByScroll=d,e.has("progress")){const m=document.documentElement,y=Math.max(1,m.scrollHeight-window.innerHeight);this.scrollProgress=Math.min(1,t/y)}else this.scrollProgress=0;this.lastScrollY=t}cancelScrollUpdate(){this.scrollFrame.cancel()}syncScrollListeners(){const e=this.getScrollTokens().size>0;if(e&&!this.scrollListenersAttached?(window.addEventListener("scroll",this.updateScrollState,{passive:!0}),window.addEventListener("resize",this.updateScrollState,{passive:!0}),this.scrollListenersAttached=!0):!e&&this.scrollListenersAttached&&this.removeScrollListeners(),e){this.updateScrollState();return}this.cancelScrollUpdate(),this.clearScrollState()}removeScrollListeners(){this.scrollListenersAttached&&(window.removeEventListener("scroll",this.updateScrollState),window.removeEventListener("resize",this.updateScrollState),this.scrollListenersAttached=!1)}addMenuDrawerListeners(){!this.menu||this.menuDrawerListenersAttached||(this.menu.addEventListener("esp-menu-drawer-opened",this.onMenuDrawerOpened),this.menu.addEventListener("esp-menu-drawer-presented",this.onMenuDrawerPresented),this.menu.addEventListener("esp-menu-drawer-closed",this.onMenuDrawerClosed),this.menuDrawerListenersAttached=!0)}removeMenuDrawerListeners(){!this.menu||!this.menuDrawerListenersAttached||(this.menu.removeEventListener("esp-menu-drawer-opened",this.onMenuDrawerOpened),this.menu.removeEventListener("esp-menu-drawer-presented",this.onMenuDrawerPresented),this.menu.removeEventListener("esp-menu-drawer-closed",this.onMenuDrawerClosed),this.menuDrawerListenersAttached=!1)}observeMenuContainer(){if(!this.menuContainer.value||this.observingMenuContainer)return;this.resizeObserver.observe(this.menuContainer.value);const e=this.menuContainer.value.parentElement;if(e){this.resizeObserver.observe(e);for(const t of e.querySelectorAll(":scope > section.brand, :scope > section.buttons"))this.resizeObserver.observe(t)}this.observingMenuContainer=!0}disconnectResizeObserver(){this.observingMenuContainer&&(this.resizeObserver.disconnect(),this.observingMenuContainer=!1)}observeMenuChildren(){!this.menu||this.menuChildObserver||(this.menuChildObserver=new MutationObserver(()=>{this.syncMenuLayout(),this.requestUpdate()}),this.menuChildObserver.observe(this.menu,{childList:!0,subtree:!0}))}syncMobileMenuQuery(){if("matchMedia"in window){if(!this.mobileMenuQuery){this.mobileMenuQuery=window.matchMedia(H),this.mobileMenu=this.mobileMenuQuery.matches,this.mobileMenuQuery.addEventListener("change",this.handleMobileMenuQueryChange);return}this.mobileMenu=this.mobileMenuQuery.matches}}getThemeRoot(){return this.traverseToClosest("esp-root")}syncExternalDrawerTarget(){const e=this.getExternalDrawerTarget(),t=e===this.menu?null:e;t!==this.externalDrawerTarget&&(this.externalDrawerTarget?.removeEventListener("esp-menu-drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.removeEventListener("esp-menu-drawer-closed",this.onMenuDrawerClosed),this.externalDrawerTarget instanceof p&&(this.externalDrawerTarget.hasExternalDrawerControl=!1),this.externalDrawerTarget=t,this.externalDrawerTarget?.addEventListener("esp-menu-drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.addEventListener("esp-menu-drawer-closed",this.onMenuDrawerClosed)),this.syncExternalDrawerControl()}burgerVisibleForTarget(){if(this.menuDisplay==="inline")return!1;const e=this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal"||this.previewCollapseRequested;return this.menuTooLarge||this.mobileMenu||e}syncExternalDrawerControl(){this.externalDrawerTarget instanceof p&&(this.externalDrawerTarget.hasExternalDrawerControl=this.burgerVisibleForTarget())}openNav(){const e=this.getBurgerFocusTarget(),t=this.getExternalDrawerTarget();if(this.burger&&(this.burger.menuOpen=!0),t){this.menuOpen=!0,t.openDrawer(e),document.body.classList.add("menu-open");return}if(this.menu){this.menu.sliding=!0,this.menuOpen=!0,this.menu.isFullScreenDrawer&&this.canPromoteMenuToggle()&&(this.menu.liftedCloseControl=this.getMenuToggleElement()),this.menu.openDrawer(e),document.body.classList.add("menu-open");return}this.burger&&(this.burger.menuOpen=!1)}closeNav(){this.menuOpen=!1,this.burger&&(this.burger.menuOpen=!1),this.demoteMenuToggle();const e=this.getExternalDrawerTarget();if(e){e.closeDrawer(),document.body.classList.remove("menu-open");return}this.menu&&(this.menu.closeDrawer(),document.body.classList.remove("menu-open"))}getMenuToggleElement(){return this.shadowRoot?.querySelector("esp-header-button.menu-toggle")??null}canPromoteMenuToggle(){const e=this.getMenuToggleElement();return!!e&&typeof e?.showPopover=="function"}setHeaderChromeInert(e){if(!e){for(const r of this.inertedHeaderChrome)r.inert=!1;this.inertedHeaderChrome=[];return}const t=this.menuContainer.value?.parentElement,s=this.getMenuToggleElement();if(!t||!s)return;const n=[];for(const r of t.querySelectorAll(":scope > section.brand, :scope > section.topbar"))n.push(r);const l=t.querySelector(":scope > section.buttons");for(const r of l?.children??[])if(!(!(r instanceof HTMLElement)||r===s)){if(r instanceof HTMLSlotElement){for(const d of r.assignedElements())d instanceof HTMLElement&&n.push(d);continue}n.push(r)}for(const r of n)r.inert||(r.inert=!0,this.inertedHeaderChrome.push(r))}promoteMenuToggle(){const e=this.getMenuToggleElement();if(!e||this.menuTogglePromoted||typeof e.showPopover!="function")return;const t=e.getBoundingClientRect();e.setAttribute("popover","manual"),Object.assign(e.style,{position:"fixed",inset:"auto",top:`${t.top}px`,left:`${t.left}px`,margin:"0",padding:"0",border:"0",background:"transparent",overflow:"visible"});try{e.showPopover()}catch{e.removeAttribute("popover"),e.removeAttribute("style"),this.menu&&(this.menu.liftedCloseControl=null);return}this.menuTogglePromoted=!0,this.menu&&(this.menu.liftedCloseControl=e),this.setHeaderChromeInert(!0)}positionPromotedToggle(){if(!this.menuTogglePromoted)return;const e=this.getMenuToggleElement(),t=this.shadowRoot?.querySelector("section.buttons");if(!e||!t)return;const s=t.getBoundingClientRect(),n=e.getBoundingClientRect(),l=getComputedStyle(t).direction==="rtl";e.style.top=`${s.top+(s.height-n.height)/2}px`,e.style.left=`${l?s.left:s.right-n.width}px`}demoteMenuToggle(){if(this.menu?.liftedCloseControl&&(this.menu.liftedCloseControl=null),!this.menuTogglePromoted)return;this.menuTogglePromoted=!1,this.setHeaderChromeInert(!1);const e=this.getMenuToggleElement();if(e){try{e.hidePopover()}catch{}e.removeAttribute("popover"),e.removeAttribute("style")}}syncDrawerBrand(){if(!this.menu)return;const e=E({scheme:this.scheme,brandLogo:this.brandLogo,brandColor:this.brandColor,lightBrandLogo:this.lightBrandLogo,darkBrandLogo:this.darkBrandLogo,lightBrandColor:this.lightBrandColor,darkBrandColor:this.darkBrandColor}),t=e.brandLogo||this.brandText?{brandLogo:e.brandLogo,brandText:this.brandText,brandHref:this.brandHref,brandAlt:this.brandAlt,brandColor:e.brandColor}:null,s=JSON.stringify(t);s!==this.lastDrawerBrandKey&&(this.lastDrawerBrandKey=s,this.menu.drawerBrand=t)}get burger(){return this.menuButton.value??void 0}willUpdate(e){super.willUpdate(e),e.has("layout")&&!g.allowedValues.has(this.layout)&&(this.layout=g.defaultValue),e.has("brandAlign")&&!b.allowedValues.has(this.brandAlign)&&(this.brandAlign=b.defaultValue),e.has("brandWrap")&&!f.allowedValues.has(this.brandWrap)&&(this.brandWrap=f.defaultValue),e.has("menuDisplay")&&!v.allowedValues.has(this.menuDisplay)&&(this.menuDisplay=v.defaultValue),e.has("themeToggle")&&!w.allowedValues.has(this.themeToggle)&&(this.themeToggle=w.defaultValue)}firstUpdated(e){if(super.firstUpdated(e),!this.menuContainer.value)return;const n=(this.menuContainer.value.firstElementChild?.assignedElements()??[])[0];n instanceof p?(this.menu=n,this.addMenuDrawerListeners(),this.observeMenuChildren(),this.syncDrawerBrand()):n&&console.warn("<esp-header>: the menu slot expects an <esp-menu> element, received",n),this.observeMenuContainer(),this.syncExternalDrawerTarget(),this.syncMobileMenuQuery(),this.syncScrollListeners(),this.syncMenuLayout()}updated(e){super.updated(e),this.syncDrawerBrand(),(e.has("showBurger")||e.has("drawerTarget")||e.has("menuDisplay")||e.has("layout")||e.has("previewCollapseRequested"))&&(this.syncExternalDrawerTarget(),this.syncMenuLayout()),(e.has("mobileMenu")||e.has("menuTooLarge"))&&this.syncExternalDrawerControl(),e.has("scrollBehavior")?this.syncScrollListeners():(e.has("scrollThreshold")||e.has("dockOffset"))&&this.updateScrollState()}connectedCallback(){super.connectedCallback(),this.syncScrollListeners(),this.syncMobileMenuQuery(),this.addMenuDrawerListeners(),this.syncExternalDrawerTarget(),this.observeMenuContainer(),this.observeMenuChildren()}disconnectedCallback(){this.removeMenuDrawerListeners(),this.externalDrawerTarget?.removeEventListener("esp-menu-drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.removeEventListener("esp-menu-drawer-closed",this.onMenuDrawerClosed),this.externalDrawerTarget instanceof p&&(this.externalDrawerTarget.hasExternalDrawerControl=!1),this.externalDrawerTarget=null,this.mobileMenuQuery?.removeEventListener("change",this.handleMobileMenuQueryChange),this.mobileMenuQuery=null,this.removeScrollListeners(),this.cancelScrollUpdate(),this.disconnectResizeObserver(),this.menuChildObserver?.disconnect(),this.menuChildObserver=null,this.demoteMenuToggle(),super.disconnectedCallback()}render(){const{menuOpen:e,menuTooLarge:t,mobileMenu:s}=this,n=this.menuDisplay!=="inline",l=n&&(this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal"||this.previewCollapseRequested),r=this.getScrollTokens(),d=r.has("progress"),m=E({scheme:this.scheme,brandLogo:this.brandLogo,brandColor:this.brandColor,lightBrandLogo:this.lightBrandLogo,darkBrandLogo:this.darkBrandLogo,lightBrandColor:this.lightBrandColor,darkBrandColor:this.darkBrandColor}),y={"--_esp-header-brand-color":m.brandColor||null,"--_esp-header-scroll-progress":String(this.scrollProgress)},L={"menu-open":e,"too-wide":n&&this.hasDrawerableContent()&&(t||s||l),[`layout-${this.layout}`]:!0,"is-scrolled":this.scrolled,"hide-on-scroll":this.hiddenByScroll,"scroll-compact":r.has("compact"),"scroll-elevate":r.has("elevate"),"scroll-transparent":r.has("transparent")||r.has("transparent-to-solid"),"scroll-collapse-topbar":r.has("collapse-topbar")},S=this.scheme==="dark"?"light":"dark";return x`
|
|
2
|
-
<header class=${
|
|
1
|
+
var a=function(h,e,t,o){var r=arguments.length,i=r<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(h,e,t,o);else for(var d=h.length-1;d>=0;d--)(n=h[d])&&(i=(r<3?n(i):r>3?n(e,t,i):n(e,t))||i);return r>3&&i&&Object.defineProperty(e,t,i),i};import{css as k,html as x,nothing as T}from"lit";import{customElement as A,property as l,state as c}from"lit/decorators.js";import{classMap as O}from"lit/directives/class-map.js";import{styleMap as _}from"lit/directives/style-map.js";import"../burger/esp-burger.js";import{createRef as C,ref as D}from"lit/directives/ref.js";import{EspalierMenu as p}from"../menu/esp-menu.js";import{RafThrottle as E}from"../shared/raf-throttle.js";import{viewportSize as R}from"../shared/viewport.js";import{renderConfiguredBrand as z,resolveConfiguredBrand as M}from"../shared/configured-brand.js";import{EspalierElementBase as L}from"../shared/esp-element-base.js";import{ESP_EVENTS as H}from"../shared/events.js";const P="(max-width: 36rem)";function u(h,e){const t=new Set(h);return{allowedValues:t,converter:{fromAttribute(r){return r??e},toAttribute(r){return t.has(r)?r:e}},defaultValue:e}}const j=["standard","centered-brand","centered-menu","extended","extended-centered","minimal"],V=["start","center","end"],q=["truncate","wrap","nowrap"],N=["auto","inline","drawer"],U=["hidden","visible"],g=u(j,"standard"),b=u(V,"start"),f=u(q,"truncate"),v=u(N,"auto"),w=u(U,"hidden");let s=class extends L{constructor(){super(...arguments),this.menuOpen=!1,this.menuTooLarge=!1,this.mobileMenu=!1,this.scrolled=!1,this.hiddenByScroll=!1,this.scrollProgress=0,this.showBurger=!1,this.layout=g.defaultValue,this.brandText="",this.brandLogo="",this.lightBrandLogo="",this.darkBrandLogo="",this.brandHref="",this.brandAlt="",this.brandColor="",this.lightBrandColor="",this.darkBrandColor="",this.brandAlign=b.defaultValue,this.brandWrap=f.defaultValue,this.menuDisplay=v.defaultValue,this.themeToggle=w.defaultValue,this.scrollBehavior="none",this.scrollThreshold=16,this.dockOffset=0,this.drawerTarget="",this.previewCollapseRequested=!1,this.fullBleedContent=!1,this.menuContainer=C(),this.menuButton=C(),this.menu=void 0,this.externalDrawerTarget=null,this.lastScrollY=0,this.lastInlineMenuWidth=0,this.mobileMenuQuery=null,this.menuDrawerListenersAttached=!1,this.observingMenuContainer=!1,this.scrollListenersAttached=!1,this.scrollFrame=new E(()=>this.runScrollStateUpdate()),this.resizeObserver=new ResizeObserver(()=>this.syncMenuLayout()),this.menuChildObserver=null,this.updateScrollState=()=>this.scrollFrame.schedule(),this.handleMobileMenuQueryChange=e=>{this.mobileMenu=e.matches,this.syncMenuLayout(),this.syncExternalDrawerControl()},this.toggleTheme=()=>{const e=this.getThemeRoot();if(!e)return;e.scheme=e.scheme==="dark"?"light":"dark";const t=e.scheme==="dark"?"dark":"light";this.dispatchEvent(new CustomEvent(H.HEADER_THEME_TOGGLE,{detail:{scheme:t},bubbles:!0,composed:!0}))},this.handleMenuToggleClicked=()=>{if(this.menuOpen){this.closeNav();return}this.openNav()},this.onMenuDrawerOpened=()=>{this.menuOpen=!0,document.body.classList.add("menu-open"),this.burger&&(this.burger.menuOpen=!0)},this.onMenuDrawerClosed=()=>{this.menuOpen=!1,document.body.classList.remove("menu-open"),this.burger&&(this.burger.menuOpen=!1),this.demoteMenuToggle()},this.onMenuDrawerPresented=e=>{e.target!==this.menu||!this.menu?.isFullScreenDrawer||this.promoteMenuToggle()},this.menuTogglePromoted=!1,this.promotedToggleFrame=new E(()=>this.positionPromotedToggle()),this.handlePromotedViewportResize=()=>this.promotedToggleFrame.schedule(),this.lastDrawerBrandKey="",this.inertedHeaderChrome=[]}syncMenuLayout(){if(!this.menuContainer.value||!this.menu||!this.menu.getWidth)return;this.positionPromotedToggle();const e=this.menu.getWidth();e>0&&(this.lastInlineMenuWidth=e);const t=this.lastInlineMenuWidth||e,o=this.getExternalDrawerTarget(),r=this.menuDisplay!=="inline",i=this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal"||this.previewCollapseRequested,n=r&&this.menuDisplay==="auto",d=n?this.layout==="centered-menu"?this.centeredMenuCapacity():this.menuContainer.value.clientWidth:0;this.menuTooLarge=n&&t>d,this.menu.sliding=r&&!o&&this.hasDrawerableContent()&&(this.menuTooLarge||i||this.mobileMenu)}centeredMenuCapacity(){const e=this.menuContainer.value?.parentElement;if(!(e instanceof HTMLElement))return 0;const t=d=>d?d.getBoundingClientRect().width:0,o=getComputedStyle(e),r=e.clientWidth-(Number.parseFloat(o.paddingLeft)||0)-(Number.parseFloat(o.paddingRight)||0),i=e.querySelector(":scope > section.brand"),n=e.querySelector(":scope > section.buttons");return r-t(i)-t(n)+t(n?.querySelector("esp-header-button.menu-toggle"))}menuHasContent(){return!!(this.menu??this.querySelector(':scope > [slot="menu"]'))?.querySelector("esp-menu-item, esp-menu-group")}hasDrawerableContent(){return this.showBurger||!!this.getExternalDrawerTarget()||this.menuHasContent()}getExternalDrawerTarget(){if(!this.drawerTarget)return null;const e=document.getElementById(this.drawerTarget);return e===this.menu?null:e&&"openDrawer"in e&&typeof e.openDrawer=="function"&&"closeDrawer"in e&&typeof e.closeDrawer=="function"?e:null}getBurgerFocusTarget(){const t=this.shadowRoot?.querySelector("esp-header-button.menu-toggle")?.shadowRoot?.querySelector("button"),o=this.menuButton.value?.shadowRoot?.querySelector("button");return t??o??null}getScrollTokens(){const e=this.scrollBehavior.split(/\s+/).map(t=>t.trim().toLowerCase()).filter(Boolean);return new Set(e.filter(t=>t!=="none"))}getEffectiveScrollThreshold(){return Number.isFinite(this.scrollThreshold)?Math.max(0,this.scrollThreshold):0}clearScrollState(){this.scrolled=!1,this.hiddenByScroll=!1,this.scrollProgress=0}runScrollStateUpdate(){const e=this.getScrollTokens();if(!e.size){this.clearScrollState();return}const t=Math.max(0,window.scrollY||document.documentElement.scrollTop||0),o=this.getEffectiveScrollThreshold(),r=Number.isFinite(this.dockOffset)?Math.max(0,this.dockOffset):o,i=t>(e.has("dock")?r:o),n=t>this.lastScrollY,d=e.has("reveal")&&n&&t>o&&!this.menuOpen;if(this.scrolled=i,this.hiddenByScroll=d,e.has("progress")){const m=document.documentElement,y=Math.max(1,m.scrollHeight-window.innerHeight);this.scrollProgress=Math.min(1,t/y)}else this.scrollProgress=0;this.lastScrollY=t}cancelScrollUpdate(){this.scrollFrame.cancel()}syncScrollListeners(){const e=this.getScrollTokens().size>0;if(e&&!this.scrollListenersAttached?(window.addEventListener("scroll",this.updateScrollState,{passive:!0}),window.addEventListener("resize",this.updateScrollState,{passive:!0}),this.scrollListenersAttached=!0):!e&&this.scrollListenersAttached&&this.removeScrollListeners(),e){this.updateScrollState();return}this.cancelScrollUpdate(),this.clearScrollState()}removeScrollListeners(){this.scrollListenersAttached&&(window.removeEventListener("scroll",this.updateScrollState),window.removeEventListener("resize",this.updateScrollState),this.scrollListenersAttached=!1)}addMenuDrawerListeners(){!this.menu||this.menuDrawerListenersAttached||(this.menu.addEventListener("esp-menu-drawer-opened",this.onMenuDrawerOpened),this.menu.addEventListener("esp-menu-drawer-presented",this.onMenuDrawerPresented),this.menu.addEventListener("esp-menu-drawer-closed",this.onMenuDrawerClosed),this.menuDrawerListenersAttached=!0)}removeMenuDrawerListeners(){!this.menu||!this.menuDrawerListenersAttached||(this.menu.removeEventListener("esp-menu-drawer-opened",this.onMenuDrawerOpened),this.menu.removeEventListener("esp-menu-drawer-presented",this.onMenuDrawerPresented),this.menu.removeEventListener("esp-menu-drawer-closed",this.onMenuDrawerClosed),this.menuDrawerListenersAttached=!1)}observeMenuContainer(){if(!this.menuContainer.value||this.observingMenuContainer)return;this.resizeObserver.observe(this.menuContainer.value);const e=this.menuContainer.value.parentElement;if(e){this.resizeObserver.observe(e);for(const t of e.querySelectorAll(":scope > section.brand, :scope > section.buttons"))this.resizeObserver.observe(t)}this.observingMenuContainer=!0}disconnectResizeObserver(){this.observingMenuContainer&&(this.resizeObserver.disconnect(),this.observingMenuContainer=!1)}observeMenuChildren(){!this.menu||this.menuChildObserver||(this.menuChildObserver=new MutationObserver(()=>{this.syncMenuLayout(),this.requestUpdate()}),this.menuChildObserver.observe(this.menu,{childList:!0,subtree:!0}))}syncMobileMenuQuery(){if("matchMedia"in window){if(!this.mobileMenuQuery){this.mobileMenuQuery=window.matchMedia(P),this.mobileMenu=this.mobileMenuQuery.matches,this.mobileMenuQuery.addEventListener("change",this.handleMobileMenuQueryChange);return}this.mobileMenu=this.mobileMenuQuery.matches}}getThemeRoot(){return this.traverseToClosest("esp-root")}syncExternalDrawerTarget(){const e=this.getExternalDrawerTarget(),t=e===this.menu?null:e;t!==this.externalDrawerTarget&&(this.externalDrawerTarget?.removeEventListener("esp-menu-drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.removeEventListener("esp-menu-drawer-closed",this.onMenuDrawerClosed),this.externalDrawerTarget instanceof p&&(this.externalDrawerTarget.hasExternalDrawerControl=!1),this.externalDrawerTarget=t,this.externalDrawerTarget?.addEventListener("esp-menu-drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.addEventListener("esp-menu-drawer-closed",this.onMenuDrawerClosed)),this.syncExternalDrawerControl()}burgerVisibleForTarget(){if(this.menuDisplay==="inline")return!1;const e=this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal"||this.previewCollapseRequested;return this.menuTooLarge||this.mobileMenu||e}syncExternalDrawerControl(){this.externalDrawerTarget instanceof p&&(this.externalDrawerTarget.hasExternalDrawerControl=this.burgerVisibleForTarget())}openNav(){const e=this.getBurgerFocusTarget(),t=this.getExternalDrawerTarget();if(this.burger&&(this.burger.menuOpen=!0),t){this.menuOpen=!0,t.openDrawer(e),document.body.classList.add("menu-open");return}if(this.menu){this.menu.sliding=!0,this.menuOpen=!0,this.menu.isFullScreenDrawer&&this.canPromoteMenuToggle()&&(this.menu.liftedCloseControl=this.getMenuToggleElement()),this.menu.openDrawer(e),document.body.classList.add("menu-open");return}this.burger&&(this.burger.menuOpen=!1)}closeNav(){this.menuOpen=!1,this.burger&&(this.burger.menuOpen=!1),this.demoteMenuToggle();const e=this.getExternalDrawerTarget();if(e){e.closeDrawer(),document.body.classList.remove("menu-open");return}this.menu&&(this.menu.closeDrawer(),document.body.classList.remove("menu-open"))}getMenuToggleElement(){return this.shadowRoot?.querySelector("esp-header-button.menu-toggle")??null}canPromoteMenuToggle(){const e=this.getMenuToggleElement();return!!e&&typeof e?.showPopover=="function"}setHeaderChromeInert(e){if(!e){for(const n of this.inertedHeaderChrome)n.inert=!1;this.inertedHeaderChrome=[];return}const t=this.menuContainer.value?.parentElement,o=this.getMenuToggleElement();if(!t||!o)return;const r=[];for(const n of t.querySelectorAll(":scope > section.brand, :scope > section.topbar"))r.push(n);const i=t.querySelector(":scope > section.buttons");for(const n of i?.children??[])if(!(!(n instanceof HTMLElement)||n===o)){if(n instanceof HTMLSlotElement){for(const d of n.assignedElements())d instanceof HTMLElement&&r.push(d);continue}r.push(n)}for(const n of r)n.inert||(n.inert=!0,this.inertedHeaderChrome.push(n))}promoteMenuToggle(){const e=this.getMenuToggleElement();if(!e||this.menuTogglePromoted||typeof e.showPopover!="function")return;const t=e.getBoundingClientRect();e.setAttribute("popover","manual"),Object.assign(e.style,{position:"fixed",inset:"auto",margin:"0",padding:"0",border:"0",background:"transparent",overflow:"visible"}),this.setPromotedTogglePosition(e,t.left,t.top,t.width,t.height);try{e.showPopover()}catch{e.removeAttribute("popover"),e.removeAttribute("style"),this.menu&&(this.menu.liftedCloseControl=null);return}this.menuTogglePromoted=!0,window.addEventListener("resize",this.handlePromotedViewportResize),this.menu&&(this.menu.liftedCloseControl=e),this.setHeaderChromeInert(!0)}positionPromotedToggle(){if(!this.menuTogglePromoted)return;const e=this.getMenuToggleElement(),t=this.shadowRoot?.querySelector("section.buttons");if(!e||!t)return;const o=t.getBoundingClientRect(),r=e.getBoundingClientRect(),i=getComputedStyle(t).direction==="rtl";this.setPromotedTogglePosition(e,i?o.left:o.right-r.width,o.top+(o.height-r.height)/2,r.width,r.height)}setPromotedTogglePosition(e,t,o,r,i){const n=R();e.style.left=`${Math.max(0,Math.min(t,n.width-r))}px`,e.style.top=`${Math.max(0,Math.min(o,n.height-i))}px`}demoteMenuToggle(){if(window.removeEventListener("resize",this.handlePromotedViewportResize),this.promotedToggleFrame.cancel(),this.menu?.liftedCloseControl&&(this.menu.liftedCloseControl=null),!this.menuTogglePromoted)return;this.menuTogglePromoted=!1,this.setHeaderChromeInert(!1);const e=this.getMenuToggleElement();if(e){try{e.hidePopover()}catch{}e.removeAttribute("popover"),e.removeAttribute("style")}}syncDrawerBrand(){if(!this.menu)return;const e=M({scheme:this.scheme,brandLogo:this.brandLogo,brandColor:this.brandColor,lightBrandLogo:this.lightBrandLogo,darkBrandLogo:this.darkBrandLogo,lightBrandColor:this.lightBrandColor,darkBrandColor:this.darkBrandColor}),t=e.brandLogo||this.brandText?{brandLogo:e.brandLogo,brandText:this.brandText,brandHref:this.brandHref,brandAlt:this.brandAlt,brandColor:e.brandColor}:null,o=JSON.stringify(t);o!==this.lastDrawerBrandKey&&(this.lastDrawerBrandKey=o,this.menu.drawerBrand=t)}get burger(){return this.menuButton.value??void 0}willUpdate(e){super.willUpdate(e),e.has("layout")&&!g.allowedValues.has(this.layout)&&(this.layout=g.defaultValue),e.has("brandAlign")&&!b.allowedValues.has(this.brandAlign)&&(this.brandAlign=b.defaultValue),e.has("brandWrap")&&!f.allowedValues.has(this.brandWrap)&&(this.brandWrap=f.defaultValue),e.has("menuDisplay")&&!v.allowedValues.has(this.menuDisplay)&&(this.menuDisplay=v.defaultValue),e.has("themeToggle")&&!w.allowedValues.has(this.themeToggle)&&(this.themeToggle=w.defaultValue)}firstUpdated(e){if(super.firstUpdated(e),!this.menuContainer.value)return;const r=(this.menuContainer.value.firstElementChild?.assignedElements()??[])[0];r instanceof p?(this.menu=r,this.addMenuDrawerListeners(),this.observeMenuChildren(),this.syncDrawerBrand()):r&&console.warn("<esp-header>: the menu slot expects an <esp-menu> element, received",r),this.observeMenuContainer(),this.syncExternalDrawerTarget(),this.syncMobileMenuQuery(),this.syncScrollListeners(),this.syncMenuLayout()}updated(e){super.updated(e),this.syncDrawerBrand(),(e.has("showBurger")||e.has("drawerTarget")||e.has("menuDisplay")||e.has("layout")||e.has("previewCollapseRequested"))&&(this.syncExternalDrawerTarget(),this.syncMenuLayout()),(e.has("mobileMenu")||e.has("menuTooLarge"))&&this.syncExternalDrawerControl(),e.has("scrollBehavior")?this.syncScrollListeners():(e.has("scrollThreshold")||e.has("dockOffset"))&&this.updateScrollState()}connectedCallback(){super.connectedCallback(),this.syncScrollListeners(),this.syncMobileMenuQuery(),this.addMenuDrawerListeners(),this.syncExternalDrawerTarget(),this.observeMenuContainer(),this.observeMenuChildren()}disconnectedCallback(){this.removeMenuDrawerListeners(),this.externalDrawerTarget?.removeEventListener("esp-menu-drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.removeEventListener("esp-menu-drawer-closed",this.onMenuDrawerClosed),this.externalDrawerTarget instanceof p&&(this.externalDrawerTarget.hasExternalDrawerControl=!1),this.externalDrawerTarget=null,this.mobileMenuQuery?.removeEventListener("change",this.handleMobileMenuQueryChange),this.mobileMenuQuery=null,this.removeScrollListeners(),this.cancelScrollUpdate(),this.disconnectResizeObserver(),this.menuChildObserver?.disconnect(),this.menuChildObserver=null,this.demoteMenuToggle(),super.disconnectedCallback()}render(){const{menuOpen:e,menuTooLarge:t,mobileMenu:o}=this,r=this.menuDisplay!=="inline",i=r&&(this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal"||this.previewCollapseRequested),n=this.getScrollTokens(),d=n.has("progress"),m=M({scheme:this.scheme,brandLogo:this.brandLogo,brandColor:this.brandColor,lightBrandLogo:this.lightBrandLogo,darkBrandLogo:this.darkBrandLogo,lightBrandColor:this.lightBrandColor,darkBrandColor:this.darkBrandColor}),y={"--_esp-header-brand-color":m.brandColor||null,"--_esp-header-scroll-progress":String(this.scrollProgress)},S={"menu-open":e,"too-wide":r&&this.hasDrawerableContent()&&(t||o||i),[`layout-${this.layout}`]:!0,"is-scrolled":this.scrolled,"hide-on-scroll":this.hiddenByScroll,"scroll-compact":n.has("compact"),"scroll-elevate":n.has("elevate"),"scroll-transparent":n.has("transparent")||n.has("transparent-to-solid"),"scroll-collapse-topbar":n.has("collapse-topbar")},B=this.scheme==="dark"?"light":"dark";return x`
|
|
2
|
+
<header class=${O(S)} style=${_(y)}>
|
|
3
3
|
<section class="topbar">
|
|
4
4
|
<slot name="topbar"></slot>
|
|
5
5
|
</section>
|
|
6
6
|
|
|
7
7
|
<section class="brand">
|
|
8
8
|
<slot name="brand"
|
|
9
|
-
>${
|
|
9
|
+
>${z({brandLogo:m.brandLogo,brandText:this.brandText,brandHref:this.brandHref,brandAlt:this.brandAlt})}</slot
|
|
10
10
|
>
|
|
11
11
|
</section>
|
|
12
12
|
|
|
@@ -19,7 +19,7 @@ var a=function(h,e,t,s){var n=arguments.length,l=n<3?e:s===null?s=Object.getOwnP
|
|
|
19
19
|
${this.themeToggle==="visible"?x`<esp-header-button
|
|
20
20
|
class="theme-toggle"
|
|
21
21
|
icon=${this.scheme==="dark"?"sun":"moon"}
|
|
22
|
-
aria-label=${`Switch to ${
|
|
22
|
+
aria-label=${`Switch to ${B} mode`}
|
|
23
23
|
@esp-clicked=${this.toggleTheme}
|
|
24
24
|
></esp-header-button>`:T}
|
|
25
25
|
<esp-header-button
|
|
@@ -35,7 +35,7 @@ var a=function(h,e,t,s){var n=arguments.length,l=n<3?e:s===null?s=Object.getOwnP
|
|
|
35
35
|
</section>
|
|
36
36
|
${d?x`<div class="scroll-progress" aria-hidden="true"></div>`:T}
|
|
37
37
|
</header>
|
|
38
|
-
`}};
|
|
38
|
+
`}};s.styles=[...L.styles,k`
|
|
39
39
|
:host {
|
|
40
40
|
--_esp-header-current-height: var(--esp-header-height, calc(4.5 * var(--esp-size-small)));
|
|
41
41
|
|
|
@@ -492,4 +492,4 @@ var a=function(h,e,t,s){var n=arguments.length,l=n<3?e:s===null?s=Object.getOwnP
|
|
|
492
492
|
transition: none;
|
|
493
493
|
}
|
|
494
494
|
}
|
|
495
|
-
`],a([c()],
|
|
495
|
+
`],a([c()],s.prototype,"menuOpen",void 0),a([c()],s.prototype,"menuTooLarge",void 0),a([c()],s.prototype,"mobileMenu",void 0),a([c()],s.prototype,"scrolled",void 0),a([c()],s.prototype,"hiddenByScroll",void 0),a([c()],s.prototype,"scrollProgress",void 0),a([l({attribute:"show-burger",type:Boolean})],s.prototype,"showBurger",void 0),a([l({converter:g.converter,reflect:!0})],s.prototype,"layout",void 0),a([l({attribute:"brand-text",type:String})],s.prototype,"brandText",void 0),a([l({attribute:"brand-logo",type:String})],s.prototype,"brandLogo",void 0),a([l({attribute:"light-brand-logo",type:String})],s.prototype,"lightBrandLogo",void 0),a([l({attribute:"dark-brand-logo",type:String})],s.prototype,"darkBrandLogo",void 0),a([l({attribute:"brand-href",type:String})],s.prototype,"brandHref",void 0),a([l({attribute:"brand-alt",type:String})],s.prototype,"brandAlt",void 0),a([l({attribute:"brand-color",type:String})],s.prototype,"brandColor",void 0),a([l({attribute:"light-brand-color",type:String})],s.prototype,"lightBrandColor",void 0),a([l({attribute:"dark-brand-color",type:String})],s.prototype,"darkBrandColor",void 0),a([l({attribute:"brand-align",converter:b.converter,reflect:!0})],s.prototype,"brandAlign",void 0),a([l({attribute:"brand-wrap",converter:f.converter,reflect:!0})],s.prototype,"brandWrap",void 0),a([l({attribute:"menu-display",converter:v.converter,reflect:!0})],s.prototype,"menuDisplay",void 0),a([l({attribute:"theme-toggle",converter:w.converter,reflect:!0})],s.prototype,"themeToggle",void 0),a([l({attribute:"scroll-behavior",type:String})],s.prototype,"scrollBehavior",void 0),a([l({attribute:"scroll-threshold",type:Number})],s.prototype,"scrollThreshold",void 0),a([l({attribute:"dock-offset",type:Number})],s.prototype,"dockOffset",void 0),a([l({attribute:"drawer-target",type:String})],s.prototype,"drawerTarget",void 0),a([l({attribute:!1})],s.prototype,"previewCollapseRequested",void 0),a([l({attribute:"full-bleed-content",type:Boolean,reflect:!0})],s.prototype,"fullBleedContent",void 0),s=a([A("esp-header")],s);export{s as EspalierHeader};
|
|
@@ -2,7 +2,7 @@ import { nothing, type PropertyValues, type TemplateResult } from "lit";
|
|
|
2
2
|
import { EspalierElementBase } from "../shared/esp-element-base.js";
|
|
3
3
|
import { type CursorPageRequest, type CursorPageResult } from "../shared/cursor-pagination.js";
|
|
4
4
|
import "../shared/virtualizer/lit-virtualizer.js";
|
|
5
|
-
export type RepeaterLayout = "list" | "grid";
|
|
5
|
+
export type RepeaterLayout = "list" | "grid" | "masonry";
|
|
6
6
|
export type RepeaterScrollModel = "contained" | "page";
|
|
7
7
|
export type RepeaterRenderValue = TemplateResult | Node | string | number | boolean | typeof nothing | null | undefined;
|
|
8
8
|
export type RepeaterRenderItem<T = unknown> = (item: T, index: number) => RepeaterRenderValue;
|
|
@@ -19,6 +19,15 @@ export type RepeaterRenderItem<T = unknown> = (item: T, index: number) => Repeat
|
|
|
19
19
|
* provide a fixed fallback with `grid-columns` and override the live column
|
|
20
20
|
* count with `--esp-repeater-grid-columns` in media queries.
|
|
21
21
|
*
|
|
22
|
+
* Use `layout="masonry"` for cards of uneven height, such as an image library
|
|
23
|
+
* mixing portrait and landscape photos. Items keep their document order and
|
|
24
|
+
* flow into the same responsive column count as `grid`, but each card takes
|
|
25
|
+
* only the height it needs and the next card starts directly below it, so
|
|
26
|
+
* columns pack tightly instead of leaving blank space under shorter cards.
|
|
27
|
+
* Masonry measures every card, so it keeps all loaded items in the DOM
|
|
28
|
+
* instead of virtualizing them; pair it with cursor paging for large
|
|
29
|
+
* collections.
|
|
30
|
+
*
|
|
22
31
|
* Use `scroll-model="page"` when the repeater should participate in the
|
|
23
32
|
* document's natural page scroll instead of owning a nested scrolling
|
|
24
33
|
* viewport. In page mode, `list-height` is ignored.
|
|
@@ -35,9 +44,9 @@ export type RepeaterRenderItem<T = unknown> = (item: T, index: number) => Repeat
|
|
|
35
44
|
* @cssprop --esp-repeater-gap - Space between repeated items.
|
|
36
45
|
* @cssprop --esp-repeater-padding - Padding used by repeater state panels and the loading/error footer.
|
|
37
46
|
* @cssprop --esp-repeater-content-padding - Padding inside the virtualized content region. Defaults to `0`.
|
|
38
|
-
* @cssprop --esp-repeater-grid-columns -
|
|
39
|
-
* @cssprop --esp-repeater-grid-column-gap - Horizontal gap between grid columns.
|
|
40
|
-
* @cssprop --esp-repeater-grid-row-gap - Vertical gap between grid rows.
|
|
47
|
+
* @cssprop --esp-repeater-grid-columns - Column count when `layout="grid"` or `layout="masonry"`. Supports media-query overrides.
|
|
48
|
+
* @cssprop --esp-repeater-grid-column-gap - Horizontal gap between grid or masonry columns.
|
|
49
|
+
* @cssprop --esp-repeater-grid-row-gap - Vertical gap between grid rows or stacked masonry cards.
|
|
41
50
|
*
|
|
42
51
|
* @docPageTitle Repeater
|
|
43
52
|
* @docUrl /components/repeater
|
|
@@ -268,6 +277,74 @@ export type RepeaterRenderItem<T = unknown> = (item: T, index: number) => Repeat
|
|
|
268
277
|
* };
|
|
269
278
|
* </script>
|
|
270
279
|
* ```
|
|
280
|
+
*
|
|
281
|
+
* @example Masonry gallery with mixed portrait and landscape cards
|
|
282
|
+
* ```html
|
|
283
|
+
* <style>
|
|
284
|
+
* esp-repeater[layout="masonry"] {
|
|
285
|
+
* --esp-repeater-grid-columns: 1;
|
|
286
|
+
* --esp-repeater-grid-column-gap: var(--esp-size-padding);
|
|
287
|
+
* --esp-repeater-grid-row-gap: var(--esp-size-padding);
|
|
288
|
+
* }
|
|
289
|
+
*
|
|
290
|
+
* @media (min-width: 48rem) {
|
|
291
|
+
* esp-repeater[layout="masonry"] {
|
|
292
|
+
* --esp-repeater-grid-columns: 2;
|
|
293
|
+
* }
|
|
294
|
+
* }
|
|
295
|
+
*
|
|
296
|
+
* @media (min-width: 72rem) {
|
|
297
|
+
* esp-repeater[layout="masonry"] {
|
|
298
|
+
* --esp-repeater-grid-columns: 3;
|
|
299
|
+
* }
|
|
300
|
+
* }
|
|
301
|
+
* </style>
|
|
302
|
+
*
|
|
303
|
+
* <esp-repeater
|
|
304
|
+
* id="masonry-gallery"
|
|
305
|
+
* layout="masonry"
|
|
306
|
+
* scroll-model="page"
|
|
307
|
+
* grid-columns="1"
|
|
308
|
+
* page-size="9"
|
|
309
|
+
* aria-label="Masonry image gallery"
|
|
310
|
+
* ></esp-repeater>
|
|
311
|
+
* <script>
|
|
312
|
+
* const repeater = findByTagName("esp-repeater")[0];
|
|
313
|
+
* const allImages = Array.from({ length: 30 }, (_, index) => {
|
|
314
|
+
* const portrait = index % 3 === 1;
|
|
315
|
+
* return {
|
|
316
|
+
* id: index + 1,
|
|
317
|
+
* title: `Image ${index + 1}`,
|
|
318
|
+
* ratio: portrait ? "2 / 3" : "3 / 2",
|
|
319
|
+
* thumbnail: portrait
|
|
320
|
+
* ? `https://picsum.photos/seed/masonry-${index + 1}/320/480`
|
|
321
|
+
* : `https://picsum.photos/seed/masonry-${index + 1}/480/320`,
|
|
322
|
+
* };
|
|
323
|
+
* });
|
|
324
|
+
*
|
|
325
|
+
* repeater.renderItem = (image) => {
|
|
326
|
+
* const card = document.createElement("esp-box");
|
|
327
|
+
* card.innerHTML = `
|
|
328
|
+
* <article style="display:grid; gap:var(--esp-size-small);">
|
|
329
|
+
* <img src="${image.thumbnail}" alt="" style="width:100%; aspect-ratio:${image.ratio}; object-fit:cover; border-radius:var(--esp-size-border-radius);" />
|
|
330
|
+
* <h3 style="margin:0;">${image.title}</h3>
|
|
331
|
+
* </article>
|
|
332
|
+
* `;
|
|
333
|
+
* return card;
|
|
334
|
+
* };
|
|
335
|
+
*
|
|
336
|
+
* repeater.fetchPage = async ({ cursor, limit }) => {
|
|
337
|
+
* const start = cursor ? Number(cursor) : 0;
|
|
338
|
+
* const items = allImages.slice(start, start + limit);
|
|
339
|
+
* const nextStart = start + limit;
|
|
340
|
+
*
|
|
341
|
+
* return {
|
|
342
|
+
* items,
|
|
343
|
+
* nextCursor: nextStart < allImages.length ? String(nextStart) : null,
|
|
344
|
+
* };
|
|
345
|
+
* };
|
|
346
|
+
* </script>
|
|
347
|
+
* ```
|
|
271
348
|
*/
|
|
272
349
|
export declare class EspalierRepeater extends EspalierElementBase {
|
|
273
350
|
/**
|
|
@@ -288,9 +365,11 @@ export declare class EspalierRepeater extends EspalierElementBase {
|
|
|
288
365
|
* Visual layout mode for the rendered content.
|
|
289
366
|
*
|
|
290
367
|
* Use `grid` to opt into responsive card-style rows while
|
|
291
|
-
* preserving virtualization and paging behavior.
|
|
368
|
+
* preserving virtualization and paging behavior. Use `masonry` to
|
|
369
|
+
* pack cards of uneven height into the same responsive columns;
|
|
370
|
+
* masonry keeps every loaded item in the DOM rather than virtualizing.
|
|
292
371
|
*
|
|
293
|
-
* @type {"list" | "grid"}
|
|
372
|
+
* @type {"list" | "grid" | "masonry"}
|
|
294
373
|
*/
|
|
295
374
|
layout: RepeaterLayout;
|
|
296
375
|
/**
|
|
@@ -304,9 +383,9 @@ export declare class EspalierRepeater extends EspalierElementBase {
|
|
|
304
383
|
*/
|
|
305
384
|
scrollModel: RepeaterScrollModel;
|
|
306
385
|
/**
|
|
307
|
-
* Fixed
|
|
308
|
-
* and no `--esp-repeater-grid-columns` custom
|
|
309
|
-
* is applied.
|
|
386
|
+
* Fixed column count fallback used when `layout="grid"` or
|
|
387
|
+
* `layout="masonry"` and no `--esp-repeater-grid-columns` custom
|
|
388
|
+
* property override is applied.
|
|
310
389
|
*
|
|
311
390
|
* @type {number}
|
|
312
391
|
*/
|
|
@@ -1,28 +1,44 @@
|
|
|
1
|
-
var
|
|
2
|
-
${
|
|
3
|
-
</div>`},this.renderVirtualRow=e=>{if(e===void 0)return
|
|
1
|
+
var n=function(f,e,t,s){var r=arguments.length,o=r<3?e:s===null?s=Object.getOwnPropertyDescriptor(e,t):s,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(f,e,t,s);else for(var c=f.length-1;c>=0;c--)(i=f[c])&&(o=(r<3?i(o):r>3?i(e,t,o):i(e,t))||o);return r>3&&o&&Object.defineProperty(e,t,o),o};import{css as B,html as h,nothing as S}from"lit";import{customElement as N,property as d,state as g}from"lit/decorators.js";import{keyed as q}from"lit/directives/keyed.js";import{ifDefined as M}from"lit/directives/if-defined.js";import{createRef as R,ref as w}from"lit/directives/ref.js";import{repeat as T}from"lit/directives/repeat.js";import{styleMap as p}from"lit/directives/style-map.js";import{EspalierElementBase as I}from"../shared/esp-element-base.js";import{accumulatePage as V,RequestVersionGuard as j}from"../shared/cursor-pagination.js";import"../shared/virtualizer/lit-virtualizer.js";const P=4;let a=class extends I{constructor(){super(...arguments),this.virtualizerRef=R(),this.containerRef=R(),this.pageLoads=new j,this.nextCursor=null,this.lastRangeEnd=-1,this.lastObservedWidth=0,this.observersAttached=!1,this.gridObserversAttached=!1,this.resolvedGridColumns=1,this.memoizedGridRowsSource=null,this.memoizedGridRowsColumns=0,this.memoizedGridRows=[],this.hostAttributeObserver=null,this.resizeObserver=null,this.viewportResizeListener=null,this.masonryRef=R(),this.masonryCellObserver=null,this.masonryObservedCells=new Set,this.masonryPrefetchObserver=null,this.footerHoldScrollListener=null,this.isAdjustingHeight=!1,this.pendingHeightRetry=!1,this.heightRetryObserver=null,this.isLoadingPage=!1,this.loadedItems=[],this.hasMoreData=!1,this.effectiveListHeight="60vh",this.loadError="",this.footerHoldHeight=0,this.items=[],this.renderItem=null,this.layout="list",this.scrollModel="contained",this.gridColumns=1,this.ariaLabel=null,this.listHeight="60vh",this.pageSize=25,this.prefetchThreshold=5,this.loading=!1,this.loadingMessage="Loading items\u2026",this.emptyMessage="No items found",this.errorMessage="",this.fetchPageBacker=null,this.renderVirtualItem=(e,t)=>{if(e===void 0)return h``;const s=this.renderItem??(r=>this.renderFallbackItem(r));return h`<div class="repeater-item" part="item" role="listitem">
|
|
2
|
+
${s(e,t)}
|
|
3
|
+
</div>`},this.renderVirtualRow=e=>{if(e===void 0)return h``;const t=this.renderItem??(r=>this.renderFallbackItem(r)),s={gridTemplateColumns:`repeat(${this.effectiveGridColumns}, minmax(0, 1fr))`};return h`<div
|
|
4
4
|
class="repeater-row"
|
|
5
5
|
part="row"
|
|
6
6
|
role="presentation"
|
|
7
|
-
style=${
|
|
7
|
+
style=${p(s)}
|
|
8
8
|
>
|
|
9
|
-
${e.items.map((r,
|
|
10
|
-
${t(r,e.startIndex+
|
|
9
|
+
${e.items.map((r,o)=>h`<div class="repeater-item repeater-grid-cell" part="item" role="listitem">
|
|
10
|
+
${t(r,e.startIndex+o)}
|
|
11
11
|
</div>`)}
|
|
12
|
-
</div>`},this.renderGridVirtualItem=(e,t)=>this.isGridRow(e)?this.renderVirtualRow(e,t):d``}get fetchPage(){return this.fetchPageBacker}set fetchPage(e){const t=this.fetchPageBacker;t!==e&&(this.fetchPageBacker=e,this.requestUpdate("fetchPage",t),this.resetPagedState(),e&&this.hasUpdated&&this.startPagedLoad(null))}get isPagedMode(){return this.fetchPage!==null}get isGridLayout(){return this.layout==="grid"}get isPageScrollModel(){return this.scrollModel==="page"}get isContainedScrollModel(){return!this.isPageScrollModel}get renderedItems(){return this.isPagedMode?this.loadedItems:this.items}get virtualizerItems(){return this.isGridLayout?this.buildGridRows(this.renderedItems,this.effectiveGridColumns):this.renderedItems}get isBusy(){return this.loading||this.isLoadingPage}get activeErrorMessage(){return this.errorMessage||this.loadError}get normalizedPageSize(){const e=Number(this.pageSize);return Number.isFinite(e)&&e>0?Math.floor(e):25}get normalizedPrefetchThreshold(){const e=Number(this.prefetchThreshold);return Number.isFinite(e)&&e>0?Math.floor(e):1}get normalizedGridColumns(){const e=Number(this.gridColumns);return Number.isFinite(e)&&e>0?Math.floor(e):1}get effectiveGridColumns(){return this.isGridLayout?this.resolvedGridColumns:1}connectedCallback(){super.connectedCallback(),this.attachObservers(),this.lastObservedWidth=this.clientWidth,this.syncResolvedGridColumns(),this.hasUpdated&&this.isContainedScrollModel&&this.adjustListHeight()}firstUpdated(e){if(super.firstUpdated(e),this.lastObservedWidth=this.clientWidth,this.fetchPage){this.startPagedLoad(null);return}this.adjustListHeight()}disconnectedCallback(){this.releaseActivePageScrollStabilizer(),this.heightRetryObserver?.disconnect(),this.heightRetryObserver=null,this.pendingHeightRetry=!1,this.detachObservers(),super.disconnectedCallback()}willUpdate(e){super.willUpdate(e),(e.has("layout")||e.has("gridColumns"))&&this.syncResolvedGridColumns()}updated(e){super.updated(e),e.has("layout")&&this.syncGridObservers(),(e.has("items")||e.has("loadedItems")||e.has("listHeight")||e.has("layout")||e.has("gridColumns")||e.has("scrollModel"))&&this.adjustListHeight()}parsePositiveIntegerToken(e){const t=Number(e.trim());return Number.isFinite(t)&&t>0?Math.floor(t):null}attachObservers(){this.observersAttached||(this.observersAttached=!0,this.getResizeObserver().observe(this),this.syncGridObservers())}detachObservers(){this.observersAttached&&(this.observersAttached=!1,this.detachGridObservers(),this.resizeObserver?.disconnect())}syncGridObservers(){if(this.observersAttached){if(!this.isGridLayout){this.detachGridObservers();return}this.gridObserversAttached||(this.gridObserversAttached=!0,this.getHostAttributeObserver().observe(this,{attributes:!0,attributeFilter:["class","style"]}),window.addEventListener("resize",this.getViewportResizeListener()))}}detachGridObservers(){if(!this.gridObserversAttached)return;this.gridObserversAttached=!1,this.hostAttributeObserver?.disconnect();const e=this.viewportResizeListener;e&&window.removeEventListener("resize",e)}getHostAttributeObserver(){return this.hostAttributeObserver||(this.hostAttributeObserver=new MutationObserver(()=>{this.refreshResolvedGridColumns()})),this.hostAttributeObserver}getResizeObserver(){return this.resizeObserver||(this.resizeObserver=new ResizeObserver(()=>{const e=this.clientWidth,t=e!==this.lastObservedWidth;this.lastObservedWidth=e;const i=this.isGridLayout?this.refreshResolvedGridColumns():!1;t&&!i&&this.isContainedScrollModel&&this.adjustListHeight()})),this.resizeObserver}getViewportResizeListener(){return this.viewportResizeListener||(this.viewportResizeListener=()=>{this.refreshResolvedGridColumns()}),this.viewportResizeListener}syncResolvedGridColumns(){this.resolvedGridColumns=this.isGridLayout?this.readResolvedGridColumns():1}readResolvedGridColumns(){return!this.isGridLayout||!this.isConnected?this.normalizedGridColumns:this.parsePositiveIntegerToken(getComputedStyle(this).getPropertyValue("--esp-repeater-grid-columns"))??this.normalizedGridColumns}refreshResolvedGridColumns(){if(!this.isGridLayout)return!1;const e=this.readResolvedGridColumns();return e===this.resolvedGridColumns?!1:(this.resolvedGridColumns=e,this.hasUpdated&&(this.requestUpdate(),this.adjustListHeight()),!0)}buildGridRows(e,t){if(this.memoizedGridRowsSource===e&&this.memoizedGridRowsColumns===t)return this.memoizedGridRows;const i=[];for(let r=0;r<e.length;r+=t)i.push({items:e.slice(r,r+t),startIndex:r});return this.memoizedGridRowsSource=e,this.memoizedGridRowsColumns=t,this.memoizedGridRows=i,i}isGridRow(e){return e!==null&&typeof e=="object"&&Array.isArray(e.items)&&typeof e.startIndex=="number"}renderFallbackItem(e){if(typeof e=="string"||typeof e=="number"||typeof e=="boolean")return String(e);let t="";try{t=JSON.stringify(e,null,2)??this.describeFallbackItem(e)}catch{t=this.describeFallbackItem(e)}return d`<pre>${t}</pre>`}describeFallbackItem(e){try{return String(e)}catch{return"Unrenderable item"}}async startPagedLoad(e){if(!this.fetchPage||this.isLoadingPage)return;const t=this.capturePageScrollTop(e);this.isLoadingPage=!0,await this.loadPage(e,t)}async loadPage(e,t){const i=this.fetchPage;if(!i)return;const r=this.pageLoads.begin(),s=this.activatePageScrollStabilizer(t,r);this.activePageScrollStabilizer=s;try{const a=await i({cursor:e,limit:this.normalizedPageSize});if(!this.pageLoads.isCurrent(r))return;this.loadedItems=N(this.loadedItems,a.items,e),this.nextCursor=a.nextCursor,this.hasMoreData=a.nextCursor!==null,this.loadError=""}catch(a){if(!this.pageLoads.isCurrent(r))return;this.nextCursor=null,this.hasMoreData=!1,this.loadError=a instanceof Error&&a.message.length>0?a.message:"Unable to load items."}finally{try{this.pageLoads.isCurrent(r)&&(this.isLoadingPage=!1),this.pageLoads.isCurrent(r)&&await this.restorePageScrollPositionIfNeeded(s.getRestoreScrollTop(),r)}finally{this.activePageScrollStabilizer===s&&this.releaseActivePageScrollStabilizer()}}}capturePageScrollTop(e){return!this.isPageScrollModel||e===null?null:window.scrollY}activatePageScrollStabilizer(e,t){if(e===null||!this.isPageScrollModel||!this.pageLoads.isCurrent(t))return{release:()=>{},getRestoreScrollTop:()=>e};this.pageScrollStabilizerActive=!0;const i=this.getVirtualizerElement(),r=i?.getBoundingClientRect().height??0,s=this.activePageScrollStabilizer;s&&(this.activePageScrollStabilizer=null,s.release(),this.pageScrollStabilizerActive=!0),i&&r>0&&(i.style.minHeight=`${r}px`);const a="",g=r>0?Math.max(64,r*.5):Number.POSITIVE_INFINITY;let u=e,p=window.scrollY;const m=()=>{if(!this.pageLoads.isCurrent(t))return;const c=window.scrollY;if(c>u+1){u=c,p=c;return}if(c+1>=u){p=c;return}const z=c<=1,v=p+1>=u&&p-c>=g;if(!z&&!v){u=c,p=c;return}window.scrollTo({top:u,left:window.scrollX,behavior:"auto"}),p=u};return window.addEventListener("scroll",m,{passive:!0}),{getRestoreScrollTop:()=>u,release:()=>{window.removeEventListener("scroll",m),this.pageScrollStabilizerActive=!1,i&&(i.style.minHeight=a)}}}async restorePageScrollPositionIfNeeded(e,t){if(e===null||!this.isPageScrollModel||!this.pageLoads.isCurrent(t))return;await this.updateComplete;const i=this.getVirtualizerElement();i?.updateComplete&&await i.updateComplete,await new Promise(r=>requestAnimationFrame(r)),i?.layoutComplete&&await i.layoutComplete,this.pageLoads.isCurrent(t)&&window.scrollY+1<e&&window.scrollTo({top:e,left:window.scrollX,behavior:"auto"})}onRangeChanged(e){if(!this.isPagedMode||this.activeErrorMessage.length>0||!this.hasMoreData||this.isLoadingPage||this.nextCursor===null)return;const t=this.normalizedPrefetchThreshold;this.getLastVisibleItemIndex(e.last)>=this.loadedItems.length-t&&this.startPagedLoad(this.nextCursor)}getLastVisibleItemIndex(e){return this.isGridLayout?Math.min((e+1)*this.effectiveGridColumns-1,this.renderedItems.length-1):e}resetPagedState(){this.releaseActivePageScrollStabilizer(),this.pageLoads.invalidate(),this.isLoadingPage=!1,this.loadedItems=[],this.nextCursor=null,this.hasMoreData=!1,this.loadError=""}releaseActivePageScrollStabilizer(){const e=this.activePageScrollStabilizer;if(this.activePageScrollStabilizer=null,!e){this.pageScrollStabilizerActive=!1;return}e.release(),this.adjustListHeight()}async adjustListHeight(){if(!this.isContainedScrollModel){const e=this.getVirtualizerElement();e&&!this.pageScrollStabilizerActive&&(e.style.minHeight="");return}if(!this.isAdjustingHeight){this.isAdjustingHeight=!0;try{this.effectiveListHeight=this.listHeight;const e=this.getVirtualizerElement();e&&(e.style.minHeight=""),await this.updateComplete;const t=this.containerRef.value,i=this.getVirtualizerElement();if(!t)return;if(this.renderedItems.length===0||!i){let n=0;t.querySelectorAll(":scope > *").forEach(w=>{n+=w.offsetHeight});const f=t.offsetHeight;n>0&&n<f&&(this.effectiveListHeight=`${n}px`);return}if(this.hasMoreData||this.isBusy||this.activeErrorMessage.length>0)return;const r=this.isGridLayout?".repeater-row":".repeater-item",s=i.querySelectorAll(r);let a=0,g=!1;if(s.forEach(n=>{const f=n.offsetHeight;f===0&&(g=!0),a+=f}),s.length===0||g||a===0){this.pendingHeightRetry||(this.pendingHeightRetry=!0,this.observeForHeightRetry(i));return}const u=this.isGridLayout?".repeater-row :defined":".repeater-item :defined",p=i.querySelectorAll(u),m=[];p.forEach(n=>{"updateComplete"in n&&m.push(n.updateComplete)}),m.length>0&&(await Promise.all(m),a=0,s.forEach(n=>{a+=n.offsetHeight}));const z=t.querySelector(":scope > .status-footer")?.offsetHeight??0,v=a+z,x=t.offsetHeight,$=this.virtualizerItems.length;let R=!1;v>0&&v<x&&s.length>=$&&(i.style.minHeight=`${a}px`,this.effectiveListHeight=`${v}px`,R=!0),R&&!this.hasMoreData&&!this.pendingHeightRetry&&(this.pendingHeightRetry=!0,setTimeout(()=>{if(this.pendingHeightRetry=!1,!this.isContainedScrollModel||this.isBusy||this.activeErrorMessage.length>0)return;const n=this.containerRef.value,f=this.getVirtualizerElement();if(!n||!f||this.hasMoreData)return;const w=this.isGridLayout?".repeater-row":".repeater-item",C=f.querySelectorAll(w);let S=0,L=!1;if(C.forEach(T=>{const H=T.offsetHeight;H===0&&(L=!0),S+=H}),C.length===0||L||S===0)return;const k=n.querySelector(":scope > .status-footer")?.offsetHeight??0,P=S+k;P<n.offsetHeight&&C.length>=this.virtualizerItems.length&&(f.style.minHeight=`${S}px`,this.effectiveListHeight=`${P}px`)},100))}finally{this.isAdjustingHeight=!1}}}observeForHeightRetry(e){this.heightRetryObserver?.disconnect(),this.heightRetryObserver=new IntersectionObserver(t=>{if(!t.some(a=>a.isIntersecting))return;if(this.heightRetryObserver?.disconnect(),this.heightRetryObserver=null,!this.isContainedScrollModel){this.pendingHeightRetry=!1;return}let r=0;const s=()=>{this.pendingHeightRetry=!1,this.adjustListHeight(),this.pendingHeightRetry&&++r<5&&setTimeout(s,100)};requestAnimationFrame(()=>setTimeout(s,50))},{threshold:0}),this.heightRetryObserver.observe(e)}clear(){if(this.isPagedMode){this.resetPagedState(),this.adjustListHeight();return}this.items=[]}async reload(){this.isPagedMode&&(this.resetPagedState(),await this.startPagedLoad(null))}async scrollToIndex(e,t="center"){await this.updateComplete;const i=this.getVirtualizerElement();!i||!i.scrollToIndex||(await i.updateComplete,await new Promise(r=>requestAnimationFrame(r)),await i.layoutComplete,i.scrollToIndex(this.isGridLayout?Math.floor(e/this.effectiveGridColumns):e,t))}getVirtualizerElement(){return this.virtualizerRef.value}renderBlockingState(e,t,i){return d`<div class="state-panel" part="state" role=${i} aria-live=${M(i==="alert"?void 0:"polite")}>
|
|
12
|
+
</div>`},this.renderGridVirtualItem=(e,t)=>this.isGridRow(e)?this.renderVirtualRow(e,t):h``}get fetchPage(){return this.fetchPageBacker}set fetchPage(e){const t=this.fetchPageBacker;t!==e&&(this.fetchPageBacker=e,this.requestUpdate("fetchPage",t),this.resetPagedState(),e&&this.hasUpdated&&this.startPagedLoad(null))}get isPagedMode(){return this.fetchPage!==null}get isGridLayout(){return this.layout==="grid"}get isMasonryLayout(){return this.layout==="masonry"}get usesColumns(){return this.isGridLayout||this.isMasonryLayout}get isPageScrollModel(){return this.scrollModel==="page"}get isContainedScrollModel(){return!this.isPageScrollModel}get renderedItems(){return this.isPagedMode?this.loadedItems:this.items}get virtualizerItems(){return this.isGridLayout?this.buildGridRows(this.renderedItems,this.effectiveGridColumns):this.renderedItems}get isBusy(){return this.loading||this.isLoadingPage}get activeErrorMessage(){return this.errorMessage||this.loadError}get normalizedPageSize(){const e=Number(this.pageSize);return Number.isFinite(e)&&e>0?Math.floor(e):25}get normalizedPrefetchThreshold(){const e=Number(this.prefetchThreshold);return Number.isFinite(e)&&e>0?Math.floor(e):1}get normalizedGridColumns(){const e=Number(this.gridColumns);return Number.isFinite(e)&&e>0?Math.floor(e):1}get effectiveGridColumns(){return this.usesColumns?this.resolvedGridColumns:1}connectedCallback(){super.connectedCallback(),this.attachObservers(),this.lastObservedWidth=this.clientWidth,this.syncResolvedGridColumns(),this.hasUpdated&&this.isContainedScrollModel&&this.adjustListHeight(),this.hasUpdated&&this.isMasonryLayout&&this.syncMasonryObservers()}firstUpdated(e){if(super.firstUpdated(e),this.lastObservedWidth=this.clientWidth,this.fetchPage){this.startPagedLoad(null);return}this.adjustListHeight()}disconnectedCallback(){this.disconnectMasonryObservers(),this.releaseFooterHold(),this.heightRetryObserver?.disconnect(),this.heightRetryObserver=null,this.pendingHeightRetry=!1,this.detachObservers(),super.disconnectedCallback()}willUpdate(e){super.willUpdate(e),(e.has("layout")||e.has("gridColumns"))&&this.syncResolvedGridColumns()}updated(e){if(super.updated(e),e.has("layout")&&(this.syncGridObservers(),this.isMasonryLayout||this.disconnectMasonryObservers()),this.isMasonryLayout&&(e.has("items")||e.has("loadedItems")||e.has("layout")||e.has("fetchPage")||e.has("prefetchThreshold")||e.has("scrollModel")))this.syncMasonryObservers();else if(this.isMasonryLayout&&e.has("isLoadingPage")){const t=this.masonryRef.value;t&&this.syncMasonryPrefetchTarget(t)}(e.has("items")||e.has("loadedItems")||e.has("listHeight")||e.has("layout")||e.has("gridColumns")||e.has("scrollModel"))&&this.adjustListHeight()}syncMasonryObservers(){for(const t of this.masonryObservedCells)t.isConnected||(this.masonryCellObserver?.unobserve(t),this.masonryObservedCells.delete(t));const e=this.masonryRef.value;if(!e){this.disconnectMasonryPrefetchObserver();return}this.masonryCellObserver||(this.masonryCellObserver=new ResizeObserver(t=>{this.applyMasonrySpans(t)}));for(const t of e.querySelectorAll(":scope > .repeater-masonry-cell"))this.masonryObservedCells.has(t)||(this.masonryObservedCells.add(t),this.masonryCellObserver.observe(t,{box:"border-box"}));this.syncMasonryPrefetchTarget(e)}applyMasonrySpans(e){for(const t of e){const s=t.target,r=t.borderBoxSize?.[0]?.blockSize??s.getBoundingClientRect().height,i=`span ${Math.max(1,Math.ceil(r/P))}`;s.style.gridRowEnd!==i&&(s.style.gridRowEnd=i)}this.isContainedScrollModel&&this.adjustListHeight()}syncMasonryPrefetchTarget(e){if(!this.isPagedMode){this.disconnectMasonryPrefetchObserver();return}const t=e.querySelectorAll(":scope > .repeater-masonry-cell"),s=t[Math.max(0,t.length-this.normalizedPrefetchThreshold)]??null;this.disconnectMasonryPrefetchObserver(),s&&(this.masonryPrefetchObserver=new IntersectionObserver(r=>{r.some(o=>o.isIntersecting)&&this.requestNextPageIfNeeded()},{root:this.isContainedScrollModel?e:null}),this.masonryPrefetchObserver.observe(s))}disconnectMasonryPrefetchObserver(){this.masonryPrefetchObserver?.disconnect(),this.masonryPrefetchObserver=null}disconnectMasonryObservers(){this.masonryCellObserver?.disconnect(),this.masonryCellObserver=null,this.masonryObservedCells.clear(),this.disconnectMasonryPrefetchObserver()}parsePositiveIntegerToken(e){const t=Number(e.trim());return Number.isFinite(t)&&t>0?Math.floor(t):null}attachObservers(){this.observersAttached||(this.observersAttached=!0,this.getResizeObserver().observe(this),this.syncGridObservers())}detachObservers(){this.observersAttached&&(this.observersAttached=!1,this.detachGridObservers(),this.resizeObserver?.disconnect())}syncGridObservers(){if(this.observersAttached){if(!this.usesColumns){this.detachGridObservers();return}this.gridObserversAttached||(this.gridObserversAttached=!0,this.getHostAttributeObserver().observe(this,{attributes:!0,attributeFilter:["class","style"]}),window.addEventListener("resize",this.getViewportResizeListener()))}}detachGridObservers(){if(!this.gridObserversAttached)return;this.gridObserversAttached=!1,this.hostAttributeObserver?.disconnect();const e=this.viewportResizeListener;e&&window.removeEventListener("resize",e)}getHostAttributeObserver(){return this.hostAttributeObserver||(this.hostAttributeObserver=new MutationObserver(()=>{this.refreshResolvedGridColumns()})),this.hostAttributeObserver}getResizeObserver(){return this.resizeObserver||(this.resizeObserver=new ResizeObserver(()=>{const e=this.clientWidth,t=e!==this.lastObservedWidth;this.lastObservedWidth=e;const s=this.usesColumns?this.refreshResolvedGridColumns():!1;t&&!s&&this.isContainedScrollModel&&this.adjustListHeight()})),this.resizeObserver}getViewportResizeListener(){return this.viewportResizeListener||(this.viewportResizeListener=()=>{this.refreshResolvedGridColumns()}),this.viewportResizeListener}syncResolvedGridColumns(){this.resolvedGridColumns=this.usesColumns?this.readResolvedGridColumns():1}readResolvedGridColumns(){return!this.usesColumns||!this.isConnected?this.normalizedGridColumns:this.parsePositiveIntegerToken(getComputedStyle(this).getPropertyValue("--esp-repeater-grid-columns"))??this.normalizedGridColumns}refreshResolvedGridColumns(){if(!this.usesColumns)return!1;const e=this.readResolvedGridColumns();return e===this.resolvedGridColumns?!1:(this.resolvedGridColumns=e,this.hasUpdated&&(this.requestUpdate(),this.adjustListHeight()),!0)}buildGridRows(e,t){if(this.memoizedGridRowsSource===e&&this.memoizedGridRowsColumns===t)return this.memoizedGridRows;const s=[];for(let r=0;r<e.length;r+=t)s.push({items:e.slice(r,r+t),startIndex:r});return this.memoizedGridRowsSource=e,this.memoizedGridRowsColumns=t,this.memoizedGridRows=s,s}isGridRow(e){return e!==null&&typeof e=="object"&&Array.isArray(e.items)&&typeof e.startIndex=="number"}renderFallbackItem(e){if(typeof e=="string"||typeof e=="number"||typeof e=="boolean")return String(e);let t="";try{t=JSON.stringify(e,null,2)??this.describeFallbackItem(e)}catch{t=this.describeFallbackItem(e)}return h`<pre>${t}</pre>`}describeFallbackItem(e){try{return String(e)}catch{return"Unrenderable item"}}async startPagedLoad(e){!this.fetchPage||this.isLoadingPage||(this.releaseFooterHold(),this.isLoadingPage=!0,await this.loadPage(e))}async loadPage(e){const t=this.fetchPage;if(!t)return;const s=this.pageLoads.begin();let r=0,o=!1;try{const i=await t({cursor:e,limit:this.normalizedPageSize});if(!this.pageLoads.isCurrent(s))return;r=this.measureContentHeight(),this.loadedItems=V(this.loadedItems,i.items,e),o=e!==null&&i.items.length>0,this.nextCursor=i.nextCursor,this.hasMoreData=i.nextCursor!==null,this.loadError=""}catch(i){if(!this.pageLoads.isCurrent(s))return;this.nextCursor=null,this.hasMoreData=!1,this.loadError=i instanceof Error&&i.message.length>0?i.message:"Unable to load items."}finally{this.pageLoads.isCurrent(s)&&o&&this.isPageScrollModel&&await this.waitForContentGrowth(r,s),this.pageLoads.isCurrent(s)&&(this.isPageScrollModel&&this.holdFooterSpace(),this.isLoadingPage=!1,this.isMasonryLayout||this.requestNextPageForRange())}}footerHoldFor(e,t,s,r){return e<=0?0:t+s>r-e?e:0}holdFooterSpace(){const e=this.containerRef.value?.querySelector(":scope > .status-footer"),t=this.footerHoldFor(e?.getBoundingClientRect().height??0,window.scrollY,window.innerHeight,document.documentElement.scrollHeight);t<=0||(this.footerHoldHeight=t,this.footerHoldScrollListener||(this.footerHoldScrollListener=()=>this.releaseFooterHoldIfSafe(),window.addEventListener("scroll",this.footerHoldScrollListener,{passive:!0})))}releaseFooterHoldIfSafe(){const e=document.documentElement.scrollHeight;window.scrollY+window.innerHeight<=e-this.footerHoldHeight&&this.releaseFooterHold()}releaseFooterHold(){this.footerHoldScrollListener&&(window.removeEventListener("scroll",this.footerHoldScrollListener),this.footerHoldScrollListener=null),this.footerHoldHeight=0}measureContentHeight(){return(this.masonryRef.value??this.getVirtualizerElement())?.getBoundingClientRect().height??0}async waitForContentGrowth(e,t){await this.updateComplete;for(let s=0;s<12&&this.pageLoads.isCurrent(t);s+=1){if(this.measureContentHeight()>e)return;await new Promise(r=>requestAnimationFrame(r))}}requestNextPageIfNeeded(){!this.isPagedMode||this.activeErrorMessage.length>0||!this.hasMoreData||this.isLoadingPage||this.nextCursor===null||this.startPagedLoad(this.nextCursor)}onRangeChanged(e){this.lastRangeEnd=e.last,!(!this.isPagedMode||this.isLoadingPage)&&this.requestNextPageForRange()}requestNextPageForRange(){if(this.lastRangeEnd<0)return;const e=this.normalizedPrefetchThreshold;this.getLastVisibleItemIndex(this.lastRangeEnd)>=this.loadedItems.length-e&&this.requestNextPageIfNeeded()}getLastVisibleItemIndex(e){return this.isGridLayout?Math.min((e+1)*this.effectiveGridColumns-1,this.renderedItems.length-1):e}resetPagedState(){this.releaseFooterHold(),this.pageLoads.invalidate(),this.lastRangeEnd=-1,this.isLoadingPage=!1,this.loadedItems=[],this.nextCursor=null,this.hasMoreData=!1,this.loadError=""}async adjustListHeight(){if(this.isContainedScrollModel&&!this.isAdjustingHeight){this.isAdjustingHeight=!0;try{this.effectiveListHeight=this.listHeight;const e=this.getVirtualizerElement();e&&(e.style.minHeight=""),await this.updateComplete;const t=this.containerRef.value,s=this.getVirtualizerElement();if(!t)return;if(this.renderedItems.length===0||!s){if(this.isMasonryLayout&&(this.hasMoreData||this.isBusy))return;let l=0;t.querySelectorAll(":scope > *").forEach(b=>{l+=b.offsetHeight});const u=t.offsetHeight;l>0&&l<u&&(this.effectiveListHeight=`${l}px`);return}if(this.hasMoreData||this.isBusy||this.activeErrorMessage.length>0)return;const r=this.isGridLayout?".repeater-row":".repeater-item",o=s.querySelectorAll(r);let i=0,c=!1;if(o.forEach(l=>{const u=l.offsetHeight;u===0&&(c=!0),i+=u}),o.length===0||c||i===0){this.pendingHeightRetry||(this.pendingHeightRetry=!0,this.observeForHeightRetry(s));return}const G=this.isGridLayout?".repeater-row :defined":".repeater-item :defined",x=s.querySelectorAll(G),v=[];x.forEach(l=>{"updateComplete"in l&&v.push(l.updateComplete)}),v.length>0&&(await Promise.all(v),i=0,o.forEach(l=>{i+=l.offsetHeight}));const E=t.querySelector(":scope > .status-footer")?.offsetHeight??0,y=i+E,$=t.offsetHeight,A=this.virtualizerItems.length;let H=!1;y>0&&y<$&&o.length>=A&&(s.style.minHeight=`${i}px`,this.effectiveListHeight=`${y}px`,H=!0),H&&!this.hasMoreData&&!this.pendingHeightRetry&&(this.pendingHeightRetry=!0,setTimeout(()=>{if(this.pendingHeightRetry=!1,!this.isContainedScrollModel||this.isBusy||this.activeErrorMessage.length>0)return;const l=this.containerRef.value,u=this.getVirtualizerElement();if(!l||!u||this.hasMoreData)return;const b=this.isGridLayout?".repeater-row":".repeater-item",C=u.querySelectorAll(b);let m=0,L=!1;if(C.forEach(k=>{const z=k.offsetHeight;z===0&&(L=!0),m+=z}),C.length===0||L||m===0)return;const F=l.querySelector(":scope > .status-footer")?.offsetHeight??0,O=m+F;O<l.offsetHeight&&C.length>=this.virtualizerItems.length&&(u.style.minHeight=`${m}px`,this.effectiveListHeight=`${O}px`)},100))}finally{this.isAdjustingHeight=!1}}}observeForHeightRetry(e){this.heightRetryObserver?.disconnect(),this.heightRetryObserver=new IntersectionObserver(t=>{if(!t.some(i=>i.isIntersecting))return;if(this.heightRetryObserver?.disconnect(),this.heightRetryObserver=null,!this.isContainedScrollModel){this.pendingHeightRetry=!1;return}let r=0;const o=()=>{this.pendingHeightRetry=!1,this.adjustListHeight(),this.pendingHeightRetry&&++r<5&&setTimeout(o,100)};requestAnimationFrame(()=>setTimeout(o,50))},{threshold:0}),this.heightRetryObserver.observe(e)}clear(){if(this.isPagedMode){this.resetPagedState(),this.adjustListHeight();return}this.items=[]}async reload(){this.isPagedMode&&(this.resetPagedState(),await this.startPagedLoad(null))}async scrollToIndex(e,t="center"){if(await this.updateComplete,this.isMasonryLayout){this.masonryRef.value?.querySelectorAll(":scope > .repeater-masonry-cell")?.[e]?.scrollIntoView({block:t});return}const s=this.getVirtualizerElement();!s||!s.scrollToIndex||(await s.updateComplete,await new Promise(r=>requestAnimationFrame(r)),await s.layoutComplete,s.scrollToIndex(this.isGridLayout?Math.floor(e/this.effectiveGridColumns):e,t))}getVirtualizerElement(){return this.virtualizerRef.value}renderBlockingState(e,t,s){return h`<div class="state-panel" part="state" role=${s} aria-live=${M(s==="alert"?void 0:"polite")}>
|
|
13
13
|
<slot name=${e}>
|
|
14
14
|
<div class="state-message">${t}</div>
|
|
15
15
|
</slot>
|
|
16
|
-
</div>`}renderFooterState(){return this.renderedItems.length===0?
|
|
16
|
+
</div>`}renderFooterState(){return this.renderedItems.length===0?S:this.activeErrorMessage.length>0?h`<div class="status-footer" part="footer" role="alert">
|
|
17
17
|
<slot name="error">
|
|
18
18
|
<div class="state-message">${this.activeErrorMessage}</div>
|
|
19
19
|
</slot>
|
|
20
|
-
</div>`:this.isBusy?
|
|
20
|
+
</div>`:this.isBusy?h`<div class="status-footer" part="footer" role="status" aria-live="polite">
|
|
21
21
|
<slot name="loading">
|
|
22
22
|
<div class="state-message">${this.loadingMessage}</div>
|
|
23
23
|
</slot>
|
|
24
|
-
</div>`:
|
|
25
|
-
|
|
24
|
+
</div>`:this.footerHoldHeight>0?h`<div
|
|
25
|
+
class="status-footer-hold"
|
|
26
|
+
aria-hidden="true"
|
|
27
|
+
style=${p({height:`${this.footerHoldHeight}px`})}
|
|
28
|
+
></div>`:S}renderMasonry(){const e=this.renderItem??(s=>this.renderFallbackItem(s)),t={gridTemplateColumns:`repeat(${this.effectiveGridColumns}, minmax(0, 1fr))`,gridAutoRows:`${P}px`};return h`<div
|
|
29
|
+
${w(this.masonryRef)}
|
|
30
|
+
class="repeater-masonry"
|
|
31
|
+
part="scroller"
|
|
32
|
+
role="list"
|
|
33
|
+
aria-busy=${this.isBusy?"true":"false"}
|
|
34
|
+
aria-label=${M(this.ariaLabel??void 0)}
|
|
35
|
+
style=${p(t)}
|
|
36
|
+
>
|
|
37
|
+
${T(this.renderedItems,(s,r)=>r,(s,r)=>h`<div class="repeater-item repeater-masonry-cell" part="item" role="listitem">
|
|
38
|
+
${e(s,r)}
|
|
39
|
+
</div>`)}
|
|
40
|
+
</div>`}render(){const e=this.isContainedScrollModel?{height:this.effectiveListHeight}:{},t=this.isGridLayout?this.renderGridVirtualItem:this.renderVirtualItem,s=q(this.scrollModel,h`<lit-virtualizer
|
|
41
|
+
${w(this.virtualizerRef)}
|
|
26
42
|
class="repeater-virtualizer"
|
|
27
43
|
part="scroller"
|
|
28
44
|
?scroller=${this.isContainedScrollModel}
|
|
@@ -33,15 +49,15 @@ var l=function(y,e,t,i){var r=arguments.length,s=r<3?e:i===null?i=Object.getOwnP
|
|
|
33
49
|
.items=${this.virtualizerItems}
|
|
34
50
|
.renderItem=${t}
|
|
35
51
|
@rangeChanged=${r=>this.onRangeChanged(r)}
|
|
36
|
-
></lit-virtualizer>`);return
|
|
52
|
+
></lit-virtualizer>`);return h`<div
|
|
37
53
|
class="repeater-container"
|
|
38
54
|
part="container"
|
|
39
|
-
${
|
|
40
|
-
style=${
|
|
55
|
+
${w(this.containerRef)}
|
|
56
|
+
style=${p(e)}
|
|
41
57
|
>
|
|
42
|
-
${this.renderedItems.length===0?this.activeErrorMessage.length>0?this.renderBlockingState("error",this.activeErrorMessage,"alert"):this.isBusy?this.renderBlockingState("skeleton",this.loadingMessage,"status"):this.renderBlockingState("empty",this.emptyMessage,"status"):
|
|
58
|
+
${this.renderedItems.length===0?this.activeErrorMessage.length>0?this.renderBlockingState("error",this.activeErrorMessage,"alert"):this.isBusy?this.renderBlockingState("skeleton",this.loadingMessage,"status"):this.renderBlockingState("empty",this.emptyMessage,"status"):this.isMasonryLayout?this.renderMasonry():s}
|
|
43
59
|
${this.renderFooterState()}
|
|
44
|
-
</div>`}};
|
|
60
|
+
</div>`}};a.styles=[...I.styles,B`
|
|
45
61
|
.repeater-container {
|
|
46
62
|
display: flex;
|
|
47
63
|
flex-direction: column;
|
|
@@ -73,6 +89,10 @@ var l=function(y,e,t,i){var r=arguments.length,s=r<3?e:i===null?i=Object.getOwnP
|
|
|
73
89
|
flex-shrink: 0;
|
|
74
90
|
}
|
|
75
91
|
|
|
92
|
+
.status-footer-hold {
|
|
93
|
+
flex-shrink: 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
76
96
|
.state-message {
|
|
77
97
|
color: var(--esp-color-text);
|
|
78
98
|
font-style: italic;
|
|
@@ -115,8 +135,38 @@ var l=function(y,e,t,i){var r=arguments.length,s=r<3?e:i===null?i=Object.getOwnP
|
|
|
115
135
|
padding-bottom: 0;
|
|
116
136
|
}
|
|
117
137
|
|
|
138
|
+
|
|
139
|
+
.repeater-masonry {
|
|
140
|
+
display: grid;
|
|
141
|
+
grid-auto-flow: row dense;
|
|
142
|
+
align-items: start;
|
|
143
|
+
column-gap: var(
|
|
144
|
+
--esp-repeater-grid-column-gap,
|
|
145
|
+
var(--esp-repeater-gap, var(--esp-size-small))
|
|
146
|
+
);
|
|
147
|
+
min-height: 0;
|
|
148
|
+
padding: var(--esp-repeater-content-padding, 0);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
:host([scroll-model="contained"]) .repeater-masonry {
|
|
152
|
+
flex: 0 1 auto;
|
|
153
|
+
overflow: auto;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
:host([scroll-model="page"]) .repeater-masonry {
|
|
157
|
+
overflow: visible;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.repeater-masonry-cell {
|
|
161
|
+
min-width: 0;
|
|
162
|
+
padding-bottom: var(
|
|
163
|
+
--esp-repeater-grid-row-gap,
|
|
164
|
+
var(--esp-repeater-gap, var(--esp-size-small))
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
118
168
|
pre {
|
|
119
169
|
margin: 0;
|
|
120
170
|
white-space: pre-wrap;
|
|
121
171
|
}
|
|
122
|
-
`],
|
|
172
|
+
`],n([g()],a.prototype,"isLoadingPage",void 0),n([g()],a.prototype,"loadedItems",void 0),n([g()],a.prototype,"hasMoreData",void 0),n([g()],a.prototype,"effectiveListHeight",void 0),n([g()],a.prototype,"loadError",void 0),n([g()],a.prototype,"footerHoldHeight",void 0),n([d({type:Array})],a.prototype,"items",void 0),n([d({attribute:!1})],a.prototype,"renderItem",void 0),n([d({type:String,reflect:!0})],a.prototype,"layout",void 0),n([d({attribute:"scroll-model",type:String,reflect:!0})],a.prototype,"scrollModel",void 0),n([d({attribute:"grid-columns",type:Number})],a.prototype,"gridColumns",void 0),n([d({attribute:"aria-label",type:String})],a.prototype,"ariaLabel",void 0),n([d({attribute:"list-height",type:String})],a.prototype,"listHeight",void 0),n([d({attribute:"page-size",type:Number})],a.prototype,"pageSize",void 0),n([d({attribute:"prefetch-threshold",type:Number})],a.prototype,"prefetchThreshold",void 0),n([d({type:Boolean})],a.prototype,"loading",void 0),n([d({attribute:"loading-message",type:String})],a.prototype,"loadingMessage",void 0),n([d({attribute:"empty-message",type:String})],a.prototype,"emptyMessage",void 0),n([d({attribute:"error-message",type:String})],a.prototype,"errorMessage",void 0),n([d({attribute:!1})],a.prototype,"fetchPage",null),a=n([N("esp-repeater")],a);export{a as EspalierRepeater};
|
package/espalier.css-data.json
CHANGED
|
@@ -1523,15 +1523,15 @@
|
|
|
1523
1523
|
},
|
|
1524
1524
|
{
|
|
1525
1525
|
"name": "--esp-repeater-grid-column-gap",
|
|
1526
|
-
"description": "Horizontal gap between grid columns."
|
|
1526
|
+
"description": "Horizontal gap between grid or masonry columns."
|
|
1527
1527
|
},
|
|
1528
1528
|
{
|
|
1529
1529
|
"name": "--esp-repeater-grid-columns",
|
|
1530
|
-
"description": "
|
|
1530
|
+
"description": "Column count when `layout=\"grid\"` or `layout=\"masonry\"`. Supports media-query overrides."
|
|
1531
1531
|
},
|
|
1532
1532
|
{
|
|
1533
1533
|
"name": "--esp-repeater-grid-row-gap",
|
|
1534
|
-
"description": "Vertical gap between grid rows."
|
|
1534
|
+
"description": "Vertical gap between grid rows or stacked masonry cards."
|
|
1535
1535
|
},
|
|
1536
1536
|
{
|
|
1537
1537
|
"name": "--esp-repeater-padding",
|
|
@@ -2185,19 +2185,19 @@
|
|
|
2185
2185
|
"name": "--esp-repeater-grid-column-gap",
|
|
2186
2186
|
"category": "component",
|
|
2187
2187
|
"component": "esp-repeater",
|
|
2188
|
-
"description": "Horizontal gap between grid columns."
|
|
2188
|
+
"description": "Horizontal gap between grid or masonry columns."
|
|
2189
2189
|
},
|
|
2190
2190
|
{
|
|
2191
2191
|
"name": "--esp-repeater-grid-columns",
|
|
2192
2192
|
"category": "component",
|
|
2193
2193
|
"component": "esp-repeater",
|
|
2194
|
-
"description": "
|
|
2194
|
+
"description": "Column count when `layout=\"grid\"` or `layout=\"masonry\"`. Supports media-query overrides."
|
|
2195
2195
|
},
|
|
2196
2196
|
{
|
|
2197
2197
|
"name": "--esp-repeater-grid-row-gap",
|
|
2198
2198
|
"category": "component",
|
|
2199
2199
|
"component": "esp-repeater",
|
|
2200
|
-
"description": "Vertical gap between grid rows."
|
|
2200
|
+
"description": "Vertical gap between grid rows or stacked masonry cards."
|
|
2201
2201
|
},
|
|
2202
2202
|
{
|
|
2203
2203
|
"name": "--esp-repeater-padding",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taprootio/espalier",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.14.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",
|