@taprootio/espalier 4.5.0 → 4.7.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/custom-elements.json +7248 -5653
  3. package/dist/date-picker/esp-date-picker.js +17 -17
  4. package/dist/flyout/esp-flyout.d.ts +4 -4
  5. package/dist/flyout/esp-flyout.js +14 -27
  6. package/dist/form-item/esp-form-item.d.ts +11 -0
  7. package/dist/form-item/esp-form-item.js +11 -11
  8. package/dist/header/esp-header.d.ts +4 -1
  9. package/dist/header/esp-header.js +56 -11
  10. package/dist/menu/esp-menu-group.d.ts +7 -0
  11. package/dist/menu/esp-menu-group.js +46 -11
  12. package/dist/menu/esp-menu-item.d.ts +7 -0
  13. package/dist/menu/esp-menu-item.js +49 -9
  14. package/dist/menu/esp-menu.d.ts +74 -0
  15. package/dist/menu/esp-menu.js +179 -18
  16. package/dist/menu/swipe-reveal-controller.js +1 -1
  17. package/dist/page/esp-page.js +1 -1
  18. package/dist/page/esp-page.styles.js +4 -4
  19. package/dist/pickers/esp-pick-one.js +14 -11
  20. package/dist/pickers/esp-pick-some.js +12 -9
  21. package/dist/pickers/esp-picker-base.d.ts +11 -2
  22. package/dist/pickers/esp-picker-base.js +82 -26
  23. package/dist/pickers/esp-picker-menu.d.ts +10 -1
  24. package/dist/pickers/esp-picker-menu.js +53 -18
  25. package/dist/root/esp-root.d.ts +2 -0
  26. package/dist/root/esp-root.js +2 -2
  27. package/dist/root/helpers/compute-theme-properties.js +1 -1
  28. package/dist/shared/aria-describedby.js +1 -0
  29. package/dist/shared/configured-brand.d.ts +33 -0
  30. package/dist/shared/events.d.ts +4 -0
  31. package/dist/shared/events.js +1 -1
  32. package/dist/shared/font-plan.d.ts +13 -3
  33. package/dist/shared/font-plan.js +5 -5
  34. package/dist/shared/form-field-description-controller.js +1 -1
  35. package/dist/shared/overlay-controller.js +1 -1
  36. package/dist/shared/popover-controller.js +1 -1
  37. package/dist/shared/responsive.js +1 -0
  38. package/dist/shared/style-fragments.js +24 -8
  39. package/dist/shared/theme.d.ts +18 -0
  40. package/dist/shared/theme.js +1 -1
  41. package/dist/shared/viewport.d.ts +2 -1
  42. package/dist/shared/viewport.js +1 -1
  43. package/dist/tooltip/esp-tooltip.js +3 -3
  44. package/espalier.css-data.json +52 -0
  45. package/espalier.token-manifest.json +76 -0
  46. package/package.json +1 -1
@@ -1,16 +1,16 @@
1
- var n=function(h,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,l;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--)(l=h[d])&&(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{css as S,html as x,nothing as D}from"lit";import{customElement as k,property as a,state as c}from"lit/decorators.js";import{classMap as _}from"lit/directives/class-map.js";import{styleMap as A}from"lit/directives/style-map.js";import"../burger/esp-burger.js";import{createRef as E,ref as T}from"lit/directives/ref.js";import{EspalierMenu as m}from"../menu/esp-menu.js";import{RafThrottle as B}from"../shared/raf-throttle.js";import{renderConfiguredBrand as O,resolveConfiguredBrand as R}from"../shared/configured-brand.js";import{EspalierElementBase as L}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(s){return s??e},toAttribute(s){return t.has(s)?s:e}},defaultValue:e}}const V=["standard","centered-brand","extended","extended-centered","minimal"],U=["start","center","end"],N=["truncate","wrap","nowrap"],W=["auto","inline","drawer"],$=["hidden","visible"],g=u(V,"standard"),b=u(U,"start"),v=u(N,"truncate"),f=u(W,"auto"),w=u($,"hidden");let r=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=v.defaultValue,this.menuDisplay=f.defaultValue,this.themeToggle=w.defaultValue,this.scrollBehavior="none",this.scrollThreshold=16,this.dockOffset=0,this.drawerTarget="",this.previewCollapseRequested=!1,this.fullBleedContent=!1,this.menuContainer=E(),this.menuButton=E(),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 B(()=>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)}}syncMenuLayout(){if(!this.menuContainer.value||!this.menu||!this.menu.getWidth)return;const e=this.menuContainer.value.clientWidth,t=this.menu.getWidth();t>0&&(this.lastInlineMenuWidth=t);const o=this.lastInlineMenuWidth||t,s=this.getExternalDrawerTarget(),i=this.menuDisplay!=="inline",l=this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal"||this.previewCollapseRequested;this.menuTooLarge=i&&this.menuDisplay==="auto"&&o>e,this.menu.sliding=i&&!s&&this.hasDrawerableContent()&&(this.menuTooLarge||l||this.mobileMenu)}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(),s=Number.isFinite(this.dockOffset)?Math.max(0,this.dockOffset):o,i=t>(e.has("dock")?s:o),l=t>this.lastScrollY,d=e.has("reveal")&&l&&t>o&&!this.menuOpen;if(this.scrolled=i,this.hiddenByScroll=d,e.has("progress")){const p=document.documentElement,y=Math.max(1,p.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-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-closed",this.onMenuDrawerClosed),this.menuDrawerListenersAttached=!1)}observeMenuContainer(){!this.menuContainer.value||this.observingMenuContainer||(this.resizeObserver.observe(this.menuContainer.value),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 m&&(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 m&&(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.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);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"))}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")&&!v.allowedValues.has(this.brandWrap)&&(this.brandWrap=v.defaultValue),e.has("menuDisplay")&&!f.allowedValues.has(this.menuDisplay)&&(this.menuDisplay=f.defaultValue),e.has("themeToggle")&&!w.allowedValues.has(this.themeToggle)&&(this.themeToggle=w.defaultValue)}firstUpdated(e){if(super.firstUpdated(e),!this.menuContainer.value)return;const s=(this.menuContainer.value.firstElementChild?.assignedElements()??[])[0];s instanceof m?(this.menu=s,this.addMenuDrawerListeners(),this.observeMenuChildren()):s&&console.warn("<esp-header>: the menu slot expects an <esp-menu> element, received",s),this.observeMenuContainer(),this.syncExternalDrawerTarget(),this.syncMobileMenuQuery(),this.syncScrollListeners(),this.syncMenuLayout()}updated(e){super.updated(e),(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 m&&(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,super.disconnectedCallback()}render(){const{menuOpen:e,menuTooLarge:t,mobileMenu:o}=this,s=this.menuDisplay!=="inline",i=s&&(this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal"||this.previewCollapseRequested),l=this.getScrollTokens(),d=l.has("progress"),p=R({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":p.brandColor||null,"--_esp-header-scroll-progress":String(this.scrollProgress)},M={"menu-open":e,"too-wide":s&&this.hasDrawerableContent()&&(t||o||i),[`layout-${this.layout}`]:!0,"is-scrolled":this.scrolled,"hide-on-scroll":this.hiddenByScroll,"scroll-compact":l.has("compact"),"scroll-elevate":l.has("elevate"),"scroll-transparent":l.has("transparent")||l.has("transparent-to-solid"),"scroll-collapse-topbar":l.has("collapse-topbar")},C=this.scheme==="dark"?"light":"dark";return x`
2
- <header class=${_(M)} style=${A(y)}>
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=${A(L)} style=${O(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
- >${O({brandLogo:p.brandLogo,brandText:this.brandText,brandHref:this.brandHref,brandAlt:this.brandAlt})}</slot
9
+ >${R({brandLogo:m.brandLogo,brandText:this.brandText,brandHref:this.brandHref,brandAlt:this.brandAlt})}</slot
10
10
  >
11
11
  </section>
12
12
 
13
- <section ${T(this.menuContainer)} class="menu-container">
13
+ <section ${D(this.menuContainer)} class="menu-container">
14
14
  <slot name="menu"></slot>
15
15
  </section>
16
16
 
@@ -19,23 +19,23 @@ var n=function(h,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=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 ${C} mode`}
22
+ aria-label=${`Switch to ${S} mode`}
23
23
  @esp-clicked=${this.toggleTheme}
24
- ></esp-header-button>`:D}
24
+ ></esp-header-button>`:T}
25
25
  <esp-header-button
26
26
  class="menu-toggle"
27
27
  role="button"
28
28
  aria-label=${e?"Close navigation":"Open navigation"}
29
- aria-controls=${this.drawerTarget||D}
29
+ aria-controls=${this.drawerTarget||T}
30
30
  aria-expanded=${e?"true":"false"}
31
31
  @esp-clicked=${this.handleMenuToggleClicked}
32
32
  >
33
- <esp-burger ${T(this.menuButton)} presentation-only></esp-burger>
33
+ <esp-burger ${D(this.menuButton)} presentation-only></esp-burger>
34
34
  </esp-header-button>
35
35
  </section>
36
- ${d?x`<div class="scroll-progress" aria-hidden="true"></div>`:D}
36
+ ${d?x`<div class="scroll-progress" aria-hidden="true"></div>`:T}
37
37
  </header>
38
- `}};r.styles=[...L.styles,S`
38
+ `}};o.styles=[...M.styles,B`
39
39
  :host {
40
40
  --_esp-header-current-height: var(--esp-header-height, calc(4.5 * var(--esp-size-small)));
41
41
 
@@ -245,6 +245,33 @@ var n=function(h,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=Object.getOwnP
245
245
  }
246
246
  }
247
247
 
248
+
249
+ &.layout-centered-menu {
250
+ grid-template-columns:
251
+ minmax(max-content, 1fr) minmax(0, max-content)
252
+ minmax(max-content, 1fr);
253
+
254
+ section.brand {
255
+ grid-column: 1;
256
+
257
+ justify-self: start;
258
+ justify-content: var(--esp-header-brand-inline-placement, start);
259
+ }
260
+
261
+ section.menu-container {
262
+ grid-column: 2;
263
+ }
264
+
265
+ section.menu-container ::slotted(esp-menu) {
266
+ --esp-menu-horizontal-justify-content: center;
267
+ }
268
+
269
+ section.buttons {
270
+ grid-column: 3;
271
+ justify-self: end;
272
+ }
273
+ }
274
+
248
275
  &.layout-extended,
249
276
  &.layout-extended-centered {
250
277
  grid-template-columns: minmax(0, 1fr) max-content;
@@ -387,6 +414,15 @@ var n=function(h,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=Object.getOwnP
387
414
  text-align: end;
388
415
  }
389
416
 
417
+
418
+ :host([brand-align="center"]) header.layout-centered-menu section.brand {
419
+ justify-self: center;
420
+ }
421
+
422
+ :host([brand-align="end"]) header.layout-centered-menu section.brand {
423
+ justify-self: end;
424
+ }
425
+
390
426
  :host([brand-wrap="truncate"]) .brand-text {
391
427
  overflow: hidden;
392
428
  text-overflow: ellipsis;
@@ -405,6 +441,7 @@ var n=function(h,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=Object.getOwnP
405
441
  @media (max-width: 36rem) {
406
442
  header,
407
443
  header.layout-centered-brand,
444
+ header.layout-centered-menu,
408
445
  header.layout-extended,
409
446
  header.layout-extended-centered,
410
447
  header.layout-minimal {
@@ -414,6 +451,8 @@ var n=function(h,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=Object.getOwnP
414
451
  section.brand {
415
452
  grid-column: 1;
416
453
  grid-row: 2;
454
+
455
+ justify-self: stretch;
417
456
  justify-content: start;
418
457
  text-align: start;
419
458
  }
@@ -429,6 +468,12 @@ var n=function(h,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=Object.getOwnP
429
468
  }
430
469
 
431
470
 
471
+ :host([brand-align="center"]) header.layout-centered-menu section.brand,
472
+ :host([brand-align="end"]) header.layout-centered-menu section.brand {
473
+ justify-self: stretch;
474
+ }
475
+
476
+
432
477
  header.too-wide section.menu-container,
433
478
  header.layout-minimal section.menu-container {
434
479
  display: block;
@@ -447,4 +492,4 @@ var n=function(h,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=Object.getOwnP
447
492
  transition: none;
448
493
  }
449
494
  }
450
- `],n([c()],r.prototype,"menuOpen",void 0),n([c()],r.prototype,"menuTooLarge",void 0),n([c()],r.prototype,"mobileMenu",void 0),n([c()],r.prototype,"scrolled",void 0),n([c()],r.prototype,"hiddenByScroll",void 0),n([c()],r.prototype,"scrollProgress",void 0),n([a({attribute:"show-burger",type:Boolean})],r.prototype,"showBurger",void 0),n([a({converter:g.converter,reflect:!0})],r.prototype,"layout",void 0),n([a({attribute:"brand-text",type:String})],r.prototype,"brandText",void 0),n([a({attribute:"brand-logo",type:String})],r.prototype,"brandLogo",void 0),n([a({attribute:"light-brand-logo",type:String})],r.prototype,"lightBrandLogo",void 0),n([a({attribute:"dark-brand-logo",type:String})],r.prototype,"darkBrandLogo",void 0),n([a({attribute:"brand-href",type:String})],r.prototype,"brandHref",void 0),n([a({attribute:"brand-alt",type:String})],r.prototype,"brandAlt",void 0),n([a({attribute:"brand-color",type:String})],r.prototype,"brandColor",void 0),n([a({attribute:"light-brand-color",type:String})],r.prototype,"lightBrandColor",void 0),n([a({attribute:"dark-brand-color",type:String})],r.prototype,"darkBrandColor",void 0),n([a({attribute:"brand-align",converter:b.converter,reflect:!0})],r.prototype,"brandAlign",void 0),n([a({attribute:"brand-wrap",converter:v.converter,reflect:!0})],r.prototype,"brandWrap",void 0),n([a({attribute:"menu-display",converter:f.converter,reflect:!0})],r.prototype,"menuDisplay",void 0),n([a({attribute:"theme-toggle",converter:w.converter,reflect:!0})],r.prototype,"themeToggle",void 0),n([a({attribute:"scroll-behavior",type:String})],r.prototype,"scrollBehavior",void 0),n([a({attribute:"scroll-threshold",type:Number})],r.prototype,"scrollThreshold",void 0),n([a({attribute:"dock-offset",type:Number})],r.prototype,"dockOffset",void 0),n([a({attribute:"drawer-target",type:String})],r.prototype,"drawerTarget",void 0),n([a({attribute:!1})],r.prototype,"previewCollapseRequested",void 0),n([a({attribute:"full-bleed-content",type:Boolean,reflect:!0})],r.prototype,"fullBleedContent",void 0),r=n([k("esp-header")],r);export{r as EspalierHeader};
495
+ `],a([c()],o.prototype,"menuOpen",void 0),a([c()],o.prototype,"menuTooLarge",void 0),a([c()],o.prototype,"mobileMenu",void 0),a([c()],o.prototype,"scrolled",void 0),a([c()],o.prototype,"hiddenByScroll",void 0),a([c()],o.prototype,"scrollProgress",void 0),a([i({attribute:"show-burger",type:Boolean})],o.prototype,"showBurger",void 0),a([i({converter:g.converter,reflect:!0})],o.prototype,"layout",void 0),a([i({attribute:"brand-text",type:String})],o.prototype,"brandText",void 0),a([i({attribute:"brand-logo",type:String})],o.prototype,"brandLogo",void 0),a([i({attribute:"light-brand-logo",type:String})],o.prototype,"lightBrandLogo",void 0),a([i({attribute:"dark-brand-logo",type:String})],o.prototype,"darkBrandLogo",void 0),a([i({attribute:"brand-href",type:String})],o.prototype,"brandHref",void 0),a([i({attribute:"brand-alt",type:String})],o.prototype,"brandAlt",void 0),a([i({attribute:"brand-color",type:String})],o.prototype,"brandColor",void 0),a([i({attribute:"light-brand-color",type:String})],o.prototype,"lightBrandColor",void 0),a([i({attribute:"dark-brand-color",type:String})],o.prototype,"darkBrandColor",void 0),a([i({attribute:"brand-align",converter:b.converter,reflect:!0})],o.prototype,"brandAlign",void 0),a([i({attribute:"brand-wrap",converter:f.converter,reflect:!0})],o.prototype,"brandWrap",void 0),a([i({attribute:"menu-display",converter:v.converter,reflect:!0})],o.prototype,"menuDisplay",void 0),a([i({attribute:"theme-toggle",converter:w.converter,reflect:!0})],o.prototype,"themeToggle",void 0),a([i({attribute:"scroll-behavior",type:String})],o.prototype,"scrollBehavior",void 0),a([i({attribute:"scroll-threshold",type:Number})],o.prototype,"scrollThreshold",void 0),a([i({attribute:"dock-offset",type:Number})],o.prototype,"dockOffset",void 0),a([i({attribute:"drawer-target",type:String})],o.prototype,"drawerTarget",void 0),a([i({attribute:!1})],o.prototype,"previewCollapseRequested",void 0),a([i({attribute:"full-bleed-content",type:Boolean,reflect:!0})],o.prototype,"fullBleedContent",void 0),o=a([k("esp-header")],o);export{o as EspalierHeader};
@@ -26,6 +26,7 @@ import type { EspalierMenuMode } from "./esp-menu.js";
26
26
  * @cssprop --esp-menu-group-icon-padding - Padding inside the icon rail.
27
27
  * @cssprop --esp-menu-group-icon-background - Background color of the icon rail.
28
28
  * @cssprop --esp-menu-group-icon-size - Size of generated and slotted group icons.
29
+ * @cssprop --esp-menu-item-font-family - Font family of the group label, shared with menu items. Defaults to the theme's `--esp-font-menu`, then `--esp-font-body`.
29
30
  * @docPageTitle Menu Group
30
31
  * @docUrl /components/menu/group
31
32
  * @menuGroup Navigation
@@ -46,6 +47,12 @@ export declare class EspalierMenuGroup extends EspalierElementBase {
46
47
  depth: number;
47
48
  /** Whether the device uses a coarse pointer. Supplied by the parent. */
48
49
  touchDevice: boolean;
50
+ /**
51
+ * Set by `esp-menu` for groups rendered in its full-screen drawer: the
52
+ * label centers across the row and the disclosure control keeps the
53
+ * inline end, so a linked group reads like the centered items around it.
54
+ */
55
+ fullScreenPresentation: boolean;
49
56
  /**
50
57
  * URL prefix for automatic expansion. If `location.pathname`
51
58
  * starts with this value, the group opens on connect.
@@ -1,11 +1,11 @@
1
- var i=function(a,e,o,l){var p=arguments.length,r=p<3?e:l===null?l=Object.getOwnPropertyDescriptor(e,o):l,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(a,e,o,l);else for(var h=a.length-1;h>=0;h--)(d=a[h])&&(r=(p<3?d(r):p>3?d(e,o,r):d(e,o))||r);return p>3&&r&&Object.defineProperty(e,o,r),r},c;import{css as b,html as s,nothing as g}from"lit";import{customElement as y,property as n,state as x}from"lit/decorators.js";import{classMap as k}from"lit/directives/class-map.js";import{createRef as m,ref as u}from"lit/directives/ref.js";import{EspalierElementBase as f}from"../shared/esp-element-base.js";import{ESP_EVENTS as w}from"../shared/events.js";import{getIconHrefForHost as z}from"../shared/intent-values.js";import{pathStartsWithSegment as v,pathsMatch as S}from"../shared/path-matching.js";import{SlottedIconController as $}from"../shared/slotted-icon-controller.js";import{renderSpriteIcon as C}from"../shared/svgs/render-sprite-icon.js";import{EspalierMenuItem as E}from"./esp-menu-item.js";let t=c=class extends f{constructor(){super(...arguments),this.itemsSlot=m(),this.toggleButton=m(),this.iconSlot=new $(this),this.openedByUrlPrefix=!1,this.dismissedUrlPrefix=!1,this.label="",this.url="",this.icon="",this.open=!1,this.mode="vertical",this.depth=0,this.touchDevice=!1,this.active=!1,this.urlPrefix="",this.globalListenersActive=!1,this.handleDocumentClick=e=>{this.open&&(e.composedPath().includes(this)||this.setOpen(!1))},this.handleDocumentKeydown=e=>{!this.open||e.key!=="Escape"||(e.preventDefault(),this.setOpen(!1),this.toggleButton.value?.focus())}}connectedCallback(){super.connectedCallback(),this.checkActive()}disconnectedCallback(){super.disconnectedCallback(),this.removeGlobalDismissListeners()}firstUpdated(e){super.firstUpdated(e),this.propagateToChildren()}updated(e){super.updated(e),(e.has("mode")||e.has("depth")||e.has("touchDevice"))&&this.propagateToChildren(),(e.has("mode")||e.has("depth")||e.has("urlPrefix"))&&this.syncUrlPrefixExpansion(),e.has("url")&&this.checkActive(),e.has("open")&&!this.open&&(this.openedByUrlPrefix=!1),(e.has("open")||e.has("mode"))&&(this.open&&this.isHorizontalTopLevel?this.addGlobalDismissListeners():this.removeGlobalDismissListeners())}checkActive(){if(!this.url){this.active=!1;return}this.active=S(this.url)}get isHorizontalTopLevel(){return this.mode==="horizontal"&&this.depth===0}get childMode(){return this.mode==="horizontal"?"vertical":this.mode}syncUrlPrefixExpansion(){const e=v(location.pathname,this.urlPrefix);if(e||(this.dismissedUrlPrefix=!1),e&&!this.dismissedUrlPrefix&&!this.isHorizontalTopLevel){this.open||(this.open=!0,this.openedByUrlPrefix=!0);return}this.openedByUrlPrefix&&(this.open=!1,this.openedByUrlPrefix=!1)}getChildren(){return this.itemsSlot.value?Array.from(this.itemsSlot.value.assignedElements()):[]}propagateToChildren(){for(const e of this.getChildren())e instanceof E?(e.mode=this.childMode,e.depth=this.depth+1,e.touchDevice=this.touchDevice):e instanceof c&&(e.mode=this.childMode,e.depth=this.depth+1,e.touchDevice=this.touchDevice)}handleSlotChange(){this.propagateToChildren()}setOpen(e){this.open!==e&&(this.openedByUrlPrefix=!1,this.dismissedUrlPrefix=!e&&v(location.pathname,this.urlPrefix),this.open=e,this.dispatchEvent(new CustomEvent(w.MENU_GROUP_TOGGLE,{detail:{open:this.open},bubbles:!0,composed:!0})))}handleHeaderClick(){this.toggleOpen()}handleLinkClick(e){e.stopPropagation()}handleToggleClick(e){e.stopPropagation(),this.toggleOpen()}toggleOpen(){this.setOpen(!this.open)}handleToggleKeydown(e){e.key==="Escape"&&(e.preventDefault(),this.setOpen(!1),this.toggleButton.value?.focus())}addGlobalDismissListeners(){this.globalListenersActive||(document.addEventListener("click",this.handleDocumentClick,!0),document.addEventListener("keydown",this.handleDocumentKeydown),this.globalListenersActive=!0)}removeGlobalDismissListeners(){this.globalListenersActive&&(document.removeEventListener("click",this.handleDocumentClick,!0),document.removeEventListener("keydown",this.handleDocumentKeydown),this.globalListenersActive=!1)}renderIcon(){const e=z(this.icon,this),o=this.iconSlot.hasSlottedIcon();return s`
1
+ var i=function(l,e,o,a){var p=arguments.length,s=p<3?e:a===null?a=Object.getOwnPropertyDescriptor(e,o):a,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(l,e,o,a);else for(var h=l.length-1;h>=0;h--)(d=l[h])&&(s=(p<3?d(s):p>3?d(e,o,s):d(e,o))||s);return p>3&&s&&Object.defineProperty(e,o,s),s},c;import{css as b,html as n,nothing as g}from"lit";import{customElement as y,property as r,state as x}from"lit/decorators.js";import{classMap as k}from"lit/directives/class-map.js";import{createRef as f,ref as u}from"lit/directives/ref.js";import{EspalierElementBase as m}from"../shared/esp-element-base.js";import{ESP_EVENTS as w}from"../shared/events.js";import{getIconHrefForHost as z}from"../shared/intent-values.js";import{pathStartsWithSegment as v,pathsMatch as S}from"../shared/path-matching.js";import{SlottedIconController as $}from"../shared/slotted-icon-controller.js";import{renderSpriteIcon as C}from"../shared/svgs/render-sprite-icon.js";import{EspalierMenuItem as E}from"./esp-menu-item.js";let t=c=class extends m{constructor(){super(...arguments),this.itemsSlot=f(),this.toggleButton=f(),this.iconSlot=new $(this),this.openedByUrlPrefix=!1,this.dismissedUrlPrefix=!1,this.label="",this.url="",this.icon="",this.open=!1,this.mode="vertical",this.depth=0,this.touchDevice=!1,this.fullScreenPresentation=!1,this.active=!1,this.urlPrefix="",this.globalListenersActive=!1,this.handleDocumentClick=e=>{this.open&&(e.composedPath().includes(this)||this.setOpen(!1))},this.handleDocumentKeydown=e=>{!this.open||e.key!=="Escape"||(e.preventDefault(),this.setOpen(!1),this.toggleButton.value?.focus())}}connectedCallback(){super.connectedCallback(),this.checkActive()}disconnectedCallback(){super.disconnectedCallback(),this.removeGlobalDismissListeners()}firstUpdated(e){super.firstUpdated(e),this.propagateToChildren()}updated(e){super.updated(e),(e.has("mode")||e.has("depth")||e.has("touchDevice"))&&this.propagateToChildren(),(e.has("mode")||e.has("depth")||e.has("urlPrefix"))&&this.syncUrlPrefixExpansion(),e.has("url")&&this.checkActive(),e.has("open")&&!this.open&&(this.openedByUrlPrefix=!1),(e.has("open")||e.has("mode"))&&(this.open&&this.isHorizontalTopLevel?this.addGlobalDismissListeners():this.removeGlobalDismissListeners())}checkActive(){if(!this.url){this.active=!1;return}this.active=S(this.url)}get isHorizontalTopLevel(){return this.mode==="horizontal"&&this.depth===0}get childMode(){return this.mode==="horizontal"?"vertical":this.mode}syncUrlPrefixExpansion(){const e=v(location.pathname,this.urlPrefix);if(e||(this.dismissedUrlPrefix=!1),e&&!this.dismissedUrlPrefix&&!this.isHorizontalTopLevel){this.open||(this.open=!0,this.openedByUrlPrefix=!0);return}this.openedByUrlPrefix&&(this.open=!1,this.openedByUrlPrefix=!1)}getChildren(){return this.itemsSlot.value?Array.from(this.itemsSlot.value.assignedElements()):[]}propagateToChildren(){for(const e of this.getChildren())e instanceof E?(e.mode=this.childMode,e.depth=this.depth+1,e.touchDevice=this.touchDevice):e instanceof c&&(e.mode=this.childMode,e.depth=this.depth+1,e.touchDevice=this.touchDevice)}handleSlotChange(){this.propagateToChildren()}setOpen(e){this.open!==e&&(this.openedByUrlPrefix=!1,this.dismissedUrlPrefix=!e&&v(location.pathname,this.urlPrefix),this.open=e,this.dispatchEvent(new CustomEvent(w.MENU_GROUP_TOGGLE,{detail:{open:this.open},bubbles:!0,composed:!0})))}handleHeaderClick(){this.toggleOpen()}handleLinkClick(e){e.stopPropagation()}handleToggleClick(e){e.stopPropagation(),this.toggleOpen()}toggleOpen(){this.setOpen(!this.open)}handleToggleKeydown(e){e.key==="Escape"&&(e.preventDefault(),this.setOpen(!1),this.toggleButton.value?.focus())}addGlobalDismissListeners(){this.globalListenersActive||(document.addEventListener("click",this.handleDocumentClick,!0),document.addEventListener("keydown",this.handleDocumentKeydown),this.globalListenersActive=!0)}removeGlobalDismissListeners(){this.globalListenersActive&&(document.removeEventListener("click",this.handleDocumentClick,!0),document.removeEventListener("keydown",this.handleDocumentKeydown),this.globalListenersActive=!1)}renderIcon(){const e=z(this.icon,this),o=this.iconSlot.hasSlottedIcon();return n`
2
2
  <slot
3
3
  name="icon"
4
4
  ${u(this.iconSlot.slotRef)}
5
5
  @slotchange=${this.iconSlot.handleSlotChange}
6
6
  ></slot>
7
7
  ${!o&&e?C(e):g}
8
- `}renderToggle(e){return s`<button
8
+ `}renderToggle(e){return n`<button
9
9
  ${u(this.toggleButton)}
10
10
  class="group-toggle"
11
11
  type="button"
@@ -14,16 +14,16 @@ var i=function(a,e,o,l){var p=arguments.length,r=p<3?e:l===null?l=Object.getOwnP
14
14
  @keydown=${this.handleToggleKeydown}
15
15
  >
16
16
  ${e}<span class="indicator" aria-hidden="true"></span>
17
- </button>`}render(){const e={group:!0,"is-horizontal":this.isHorizontalTopLevel,"is-vertical":!this.isHorizontalTopLevel,"is-nested":this.depth>0,"is-drawer":this.mode==="drawer","is-open":this.open,"is-active":this.active,"has-icon":this.icon.length>0||this.iconSlot.hasSlottedIcon()},o=s`<span class="group-label-text">${this.label}</span>`,l=this.url?this.active?s`
17
+ </button>`}render(){const e={group:!0,"is-horizontal":this.isHorizontalTopLevel,"is-vertical":!this.isHorizontalTopLevel,"is-nested":this.depth>0,"is-drawer":this.mode==="drawer","is-open":this.open,"is-active":this.active,"has-icon":this.icon.length>0||this.iconSlot.hasSlottedIcon()},o=n`<span class="group-label-text" part="menu-text">${this.label}</span>`,a=this.url?this.active?n`
18
18
  <span class="current-page" aria-current="page">${o}</span>
19
- ${this.renderToggle(s`<span class="sr-only">Toggle ${this.label}</span>`)}
20
- `:s`
19
+ ${this.renderToggle(n`<span class="sr-only">Toggle ${this.label}</span>`)}
20
+ `:n`
21
21
  <a class="group-link" href=${this.url} @click=${this.handleLinkClick}>${o}</a>
22
- ${this.renderToggle(s`<span class="sr-only">Toggle ${this.label}</span>`)}
23
- `:this.renderToggle(o);return s`
22
+ ${this.renderToggle(n`<span class="sr-only">Toggle ${this.label}</span>`)}
23
+ `:this.renderToggle(o);return n`
24
24
  <div class=${k(e)}>
25
25
  <div class="group-header" @click=${this.handleHeaderClick}>
26
- <span class="group-label">${l}</span>
26
+ <span class="group-label">${a}</span>
27
27
  <span class="group-icon" aria-hidden="true">${this.renderIcon()}</span>
28
28
  </div>
29
29
  <div
@@ -37,7 +37,7 @@ var i=function(a,e,o,l){var p=arguments.length,r=p<3?e:l===null?l=Object.getOwnP
37
37
  </div>
38
38
  </div>
39
39
  </div>
40
- `}};t.styles=[...f.styles,b`
40
+ `}};t.styles=[...m.styles,b`
41
41
  :host {
42
42
  display: block;
43
43
  position: relative;
@@ -94,10 +94,22 @@ var i=function(a,e,o,l){var p=arguments.length,r=p<3?e:l===null?l=Object.getOwnP
94
94
  gap: var(--esp-size-tiny);
95
95
  min-width: 0;
96
96
  border: none;
97
- padding: var(--esp-size-small) var(--esp-size-padding);
97
+ padding: var(--esp-menu-item-padding, var(--esp-size-small) var(--esp-size-padding));
98
98
  color: inherit;
99
99
  background: none;
100
100
  font: inherit;
101
+
102
+ font-size: var(--esp-menu-item-font-size, inherit);
103
+ font-family: var(
104
+ --esp-menu-item-font-family,
105
+ var(
106
+ --_esp-font-menu-effective,
107
+ var(
108
+ --esp-font-menu,
109
+ var(--_esp-font-body-effective, var(--esp-font-body, var(--_esp-font-body-fallback)))
110
+ )
111
+ )
112
+ );
101
113
  font-weight: 600;
102
114
  text-align: left;
103
115
  text-decoration: none;
@@ -135,6 +147,29 @@ var i=function(a,e,o,l){var p=arguments.length,r=p<3?e:l===null?l=Object.getOwnP
135
147
  text-decoration: underline;
136
148
  }
137
149
 
150
+
151
+ :host([full-screen-presentation]) .group-label {
152
+ position: relative;
153
+ }
154
+
155
+ :host([full-screen-presentation]) .group-link,
156
+ :host([full-screen-presentation]) .current-page {
157
+ flex: 1 1 auto;
158
+ width: 100%;
159
+ justify-content: center;
160
+ padding: var(--esp-menu-item-padding, var(--esp-size-small) var(--esp-size-padding));
161
+ }
162
+
163
+ :host([full-screen-presentation]) .group-link + .group-toggle,
164
+ :host([full-screen-presentation]) .current-page + .group-toggle {
165
+ position: absolute;
166
+ inset-block: 0;
167
+ inset-inline-end: 0;
168
+ flex: none;
169
+ width: auto;
170
+ padding-inline: var(--esp-size-small);
171
+ }
172
+
138
173
  .group-toggle:focus-visible,
139
174
  .group-link:focus-visible {
140
175
  outline: 2px solid var(--esp-color-link);
@@ -235,4 +270,4 @@ var i=function(a,e,o,l){var p=arguments.length,r=p<3?e:l===null?l=Object.getOwnP
235
270
  transition: none;
236
271
  }
237
272
  }
238
- `],i([n({type:String})],t.prototype,"label",void 0),i([n({type:String})],t.prototype,"url",void 0),i([n({type:String})],t.prototype,"icon",void 0),i([n({type:Boolean,reflect:!0})],t.prototype,"open",void 0),i([n({attribute:!1,type:String})],t.prototype,"mode",void 0),i([n({attribute:!1,type:Number})],t.prototype,"depth",void 0),i([n({attribute:!1,type:Boolean})],t.prototype,"touchDevice",void 0),i([x()],t.prototype,"active",void 0),i([n({type:String,attribute:"url-prefix"})],t.prototype,"urlPrefix",void 0),t=c=i([y("esp-menu-group")],t);export{t as EspalierMenuGroup};
273
+ `],i([r({type:String})],t.prototype,"label",void 0),i([r({type:String})],t.prototype,"url",void 0),i([r({type:String})],t.prototype,"icon",void 0),i([r({type:Boolean,reflect:!0})],t.prototype,"open",void 0),i([r({attribute:!1,type:String})],t.prototype,"mode",void 0),i([r({attribute:!1,type:Number})],t.prototype,"depth",void 0),i([r({attribute:!1,type:Boolean})],t.prototype,"touchDevice",void 0),i([r({attribute:"full-screen-presentation",type:Boolean,reflect:!0})],t.prototype,"fullScreenPresentation",void 0),i([x()],t.prototype,"active",void 0),i([r({type:String,attribute:"url-prefix"})],t.prototype,"urlPrefix",void 0),t=c=i([y("esp-menu-group")],t);export{t as EspalierMenuGroup};
@@ -18,10 +18,17 @@ import type { EspalierMenuMode } from "./esp-menu.js";
18
18
  * @cssprop --esp-menu-item-border-color - Border color.
19
19
  * @cssprop --esp-menu-item-hover-color - Hover text color.
20
20
  * @cssprop --esp-menu-item-hover-background - Hover background color.
21
+ * @cssprop --esp-menu-item-hover-decoration - Text decoration of a hovered link item. Defaults to `none`; set `underline` to restore the former underline.
22
+ * @cssprop --esp-menu-item-hover-indicator-color - Color of the bar drawn under a hovered horizontal item. Defaults to `--esp-menu-item-hover-color`, then `var(--esp-color-headings-hover)`.
23
+ * @cssprop --esp-menu-item-transition-duration - Duration for color, background, and indicator changes. Defaults to `0.2s`; reduced motion disables the transition.
21
24
  * @cssprop --esp-menu-item-icon-background - Icon area background color.
22
25
  * @cssprop --esp-menu-item-active-color - Text color of the active item.
23
26
  * @cssprop --esp-menu-item-active-background - Background color of the active item.
27
+ * @cssprop --esp-menu-item-active-indicator-color - Color of the bar drawn under the active horizontal item. Defaults to `--esp-menu-item-active-color`, then `var(--esp-color-link)`.
24
28
  * @cssprop --esp-menu-item-active-font-weight - Font weight of the active item. Defaults to `var(--esp-font-weight-headings)`.
29
+ * @cssprop --esp-menu-item-font-family - Font family of item labels. Defaults to the theme's `--esp-font-menu`, then `--esp-font-body`.
30
+ * @cssprop --esp-menu-item-font-weight - Font weight of horizontal item labels. Defaults to `--esp-font-weight-menu`, then `700`.
31
+ * @cssprop --esp-menu-item-font-size - Font size of item labels. Defaults to `inherit`.
25
32
  * @cssprop --esp-menu-item-padding - Padding around the item label.
26
33
  * @cssprop --esp-menu-item-icon-min-width - Minimum width of the icon rail.
27
34
  * @cssprop --esp-menu-item-icon-padding - Padding inside the icon rail.
@@ -1,9 +1,9 @@
1
- var a=function(p,e,r,n){var s=arguments.length,t=s<3?e:n===null?n=Object.getOwnPropertyDescriptor(e,r):n,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")t=Reflect.decorate(p,e,r,n);else for(var d=p.length-1;d>=0;d--)(i=p[d])&&(t=(s<3?i(t):s>3?i(e,r,t):i(e,r))||t);return s>3&&t&&Object.defineProperty(e,r,t),t};import{css as v,html as c,nothing as h}from"lit";import{customElement as m,property as l,state as g}from"lit/decorators.js";import{classMap as b}from"lit/directives/class-map.js";import{ref as f}from"lit/directives/ref.js";import{getIconHrefForHost as k}from"../shared/intent-values.js";import{EspalierElementBase as u}from"../shared/esp-element-base.js";import{ESP_EVENTS as y}from"../shared/events.js";import{pathsMatch as z}from"../shared/path-matching.js";import{SlottedIconController as w}from"../shared/slotted-icon-controller.js";import{renderSpriteIcon as x}from"../shared/svgs/render-sprite-icon.js";let o=class extends u{constructor(){super(...arguments),this.iconSlot=new w(this),this.label="",this.url="",this.icon="",this.mode="vertical",this.depth=0,this.touchDevice=!1,this.active=!1}connectedCallback(){super.connectedCallback(),this.checkActive()}updated(e){super.updated(e),e.has("url")&&this.checkActive()}checkActive(){if(!this.url){this.active=!1;return}this.active=z(this.url)}handleButtonClick(){this.dispatchEvent(new CustomEvent(y.CLICKED,{detail:{},bubbles:!0,composed:!0}))}render(){const e=k(this.icon,this),r=this.iconSlot.hasSlottedIcon(":scope > *"),n=r||e.length>0,s={item:!0,"is-horizontal":this.mode==="horizontal"&&this.depth===0,"is-vertical":this.mode!=="horizontal"||this.depth>0,"is-drawer":this.mode==="drawer","is-nested":this.depth>0,"has-icon":n,"is-active":this.active},t=c`<span part="menu-text">${this.label}</span>`,i=c`<span class="icon-area" aria-hidden=${n?"true":h}>
2
- <slot ${f(this.iconSlot.slotRef)} @slotchange=${this.iconSlot.handleSlotChange}></slot>
1
+ var n=function(p,e,r,a){var s=arguments.length,t=s<3?e:a===null?a=Object.getOwnPropertyDescriptor(e,r):a,i;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")t=Reflect.decorate(p,e,r,a);else for(var d=p.length-1;d>=0;d--)(i=p[d])&&(t=(s<3?i(t):s>3?i(e,r,t):i(e,r))||t);return s>3&&t&&Object.defineProperty(e,r,t),t};import{css as u,html as c,nothing as h}from"lit";import{customElement as v,property as l,state as f}from"lit/decorators.js";import{classMap as b}from"lit/directives/class-map.js";import{ref as g}from"lit/directives/ref.js";import{getIconHrefForHost as y}from"../shared/intent-values.js";import{EspalierElementBase as m}from"../shared/esp-element-base.js";import{ESP_EVENTS as k}from"../shared/events.js";import{pathsMatch as w}from"../shared/path-matching.js";import{SlottedIconController as z}from"../shared/slotted-icon-controller.js";import{renderSpriteIcon as x}from"../shared/svgs/render-sprite-icon.js";let o=class extends m{constructor(){super(...arguments),this.iconSlot=new z(this),this.label="",this.url="",this.icon="",this.mode="vertical",this.depth=0,this.touchDevice=!1,this.active=!1}connectedCallback(){super.connectedCallback(),this.checkActive()}updated(e){super.updated(e),e.has("url")&&this.checkActive()}checkActive(){if(!this.url){this.active=!1;return}this.active=w(this.url)}handleButtonClick(){this.dispatchEvent(new CustomEvent(k.CLICKED,{detail:{},bubbles:!0,composed:!0}))}render(){const e=y(this.icon,this),r=this.iconSlot.hasSlottedIcon(":scope > *"),a=r||e.length>0,s={item:!0,"is-horizontal":this.mode==="horizontal"&&this.depth===0,"is-vertical":this.mode!=="horizontal"||this.depth>0,"is-drawer":this.mode==="drawer","is-nested":this.depth>0,"has-icon":a,"is-active":this.active},t=c`<span part="menu-text">${this.label}</span>`,i=c`<span class="icon-area" aria-hidden=${a?"true":h}>
2
+ <slot ${g(this.iconSlot.slotRef)} @slotchange=${this.iconSlot.handleSlotChange}></slot>
3
3
  ${!r&&e?x(e):h}
4
4
  </span>`;return c`<div class=${b(s)}>
5
5
  ${this.active?c`<span class="current-page" aria-current="page">${t}${i}</span>`:this.url?c`<a href=${this.url}>${t}${i}</a>`:c`<button type="button" @click=${this.handleButtonClick}>${t}${i}</button>`}
6
- </div>`}};o.styles=[...u.styles,v`
6
+ </div>`}};o.styles=[...m.styles,u`
7
7
  :host {
8
8
  display: block;
9
9
  }
@@ -11,6 +11,18 @@ var a=function(p,e,r,n){var s=arguments.length,t=s<3?e:n===null?n=Object.getOwnP
11
11
  .item {
12
12
  color: var(--esp-menu-item-color, var(--esp-color-text));
13
13
  background-color: var(--esp-menu-item-background, transparent);
14
+
15
+ font-family: var(
16
+ --esp-menu-item-font-family,
17
+ var(
18
+ --_esp-font-menu-effective,
19
+ var(
20
+ --esp-font-menu,
21
+ var(--_esp-font-body-effective, var(--esp-font-body, var(--_esp-font-body-fallback)))
22
+ )
23
+ )
24
+ );
25
+ font-size: var(--esp-menu-item-font-size, inherit);
14
26
  white-space: nowrap;
15
27
  }
16
28
 
@@ -40,10 +52,22 @@ var a=function(p,e,r,n){var s=arguments.length,t=s<3?e:n===null?n=Object.getOwnP
40
52
  cursor: default;
41
53
  }
42
54
 
55
+
56
+ a,
57
+ button,
58
+ .current-page,
59
+ .item {
60
+ transition:
61
+ color var(--esp-menu-item-transition-duration, 0.2s) ease,
62
+ background-color var(--esp-menu-item-transition-duration, 0.2s) ease,
63
+ box-shadow var(--esp-menu-item-transition-duration, 0.2s) ease;
64
+ }
65
+
43
66
  a:hover {
44
67
  background: var(--esp-menu-item-hover-background, var(--esp-color-link-hover-bg));
45
68
  color: var(--esp-menu-item-hover-color, var(--esp-color-link-hover));
46
- text-decoration: underline;
69
+
70
+ text-decoration: var(--esp-menu-item-hover-decoration, none);
47
71
  }
48
72
 
49
73
  a:focus-visible,
@@ -66,13 +90,17 @@ var a=function(p,e,r,n){var s=arguments.length,t=s<3?e:n===null?n=Object.getOwnP
66
90
  .is-horizontal > .current-page {
67
91
  justify-content: center;
68
92
  height: var(--esp-header-height, calc(4.5 * var(--esp-size-small)));
69
- font-weight: 700;
93
+ font-weight: var(--esp-menu-item-font-weight, var(--esp-font-weight-menu, 700));
70
94
  }
71
95
 
72
96
  .is-horizontal > a:hover,
73
97
  .is-horizontal > button:hover {
74
98
  background: var(--esp-menu-item-hover-background, transparent);
75
- box-shadow: inset 0 -2px 0 var(--esp-menu-item-hover-color, var(--esp-color-headings-hover));
99
+ box-shadow: inset 0 -2px 0
100
+ var(
101
+ --esp-menu-item-hover-indicator-color,
102
+ var(--esp-menu-item-hover-color, var(--esp-color-headings-hover))
103
+ );
76
104
  }
77
105
 
78
106
  .is-horizontal [part="menu-text"] {
@@ -83,7 +111,6 @@ var a=function(p,e,r,n){var s=arguments.length,t=s<3?e:n===null?n=Object.getOwnP
83
111
  border-right: 1px solid var(--esp-menu-item-border-color, var(--esp-color-border));
84
112
  border-bottom: 1px solid var(--esp-menu-item-border-color, var(--esp-color-border));
85
113
  background-color: var(--esp-menu-item-background, var(--esp-color-layer-1));
86
- transition: background-color 0.2s ease;
87
114
  }
88
115
 
89
116
  .is-vertical:hover,
@@ -116,7 +143,20 @@ var a=function(p,e,r,n){var s=arguments.length,t=s<3?e:n===null?n=Object.getOwnP
116
143
 
117
144
  .is-horizontal.is-active {
118
145
  background-color: var(--esp-menu-item-active-background, transparent);
119
- box-shadow: inset 0 -2px 0 var(--esp-menu-item-active-color, var(--esp-color-link));
146
+ box-shadow: inset 0 -2px 0
147
+ var(
148
+ --esp-menu-item-active-indicator-color,
149
+ var(--esp-menu-item-active-color, var(--esp-color-link))
150
+ );
151
+ }
152
+
153
+ @media (prefers-reduced-motion: reduce) {
154
+ a,
155
+ button,
156
+ .current-page,
157
+ .item {
158
+ transition: none;
159
+ }
120
160
  }
121
161
 
122
162
  .icon-area {
@@ -146,4 +186,4 @@ var a=function(p,e,r,n){var s=arguments.length,t=s<3?e:n===null?n=Object.getOwnP
146
186
  width: var(--esp-menu-item-icon-size, calc(1 * var(--esp-size-font)));
147
187
  object-fit: contain;
148
188
  }
149
- `],a([l({type:String})],o.prototype,"label",void 0),a([l({type:String})],o.prototype,"url",void 0),a([l({type:String})],o.prototype,"icon",void 0),a([l({attribute:!1,type:String})],o.prototype,"mode",void 0),a([l({attribute:!1,type:Number})],o.prototype,"depth",void 0),a([l({attribute:!1,type:Boolean})],o.prototype,"touchDevice",void 0),a([g()],o.prototype,"active",void 0),o=a([m("esp-menu-item")],o);export{o as EspalierMenuItem};
189
+ `],n([l({type:String})],o.prototype,"label",void 0),n([l({type:String})],o.prototype,"url",void 0),n([l({type:String})],o.prototype,"icon",void 0),n([l({attribute:!1,type:String})],o.prototype,"mode",void 0),n([l({attribute:!1,type:Number})],o.prototype,"depth",void 0),n([l({attribute:!1,type:Boolean})],o.prototype,"touchDevice",void 0),n([f()],o.prototype,"active",void 0),o=n([v("esp-menu-item")],o);export{o as EspalierMenuItem};
@@ -1,9 +1,21 @@
1
1
  import { type PropertyValues, type TemplateResult } from "lit";
2
2
  import { EspalierElementBase } from "../shared/esp-element-base.js";
3
+ import { type ConfiguredBrandOptions } from "../shared/configured-brand.js";
3
4
  import "./esp-menu-item.js";
4
5
  import "./esp-menu-group.js";
6
+ import "../burger/esp-burger.js";
5
7
  export type EspalierMenuMode = "horizontal" | "vertical" | "drawer";
6
8
  export type EspalierMenuOverflow = "auto" | "wrap" | "scroll" | "left-drawer" | "right-drawer";
9
+ export type EspalierMenuDrawerPresentation = "panel" | "full-screen";
10
+ export type EspalierMenuFullScreenTransition = "fade" | "slide-down" | "slide-up" | "slide-left" | "slide-right";
11
+ /**
12
+ * Brand an owning `esp-header` mirrors into a full-screen drawer. The same
13
+ * shape the header and footer resolve for their configured brand, plus the
14
+ * scheme-resolved color so the drawer paints it without re-resolving.
15
+ */
16
+ export interface EspalierMenuDrawerBrand extends ConfiguredBrandOptions {
17
+ brandColor: string;
18
+ }
7
19
  /**
8
20
  * Shared navigation primitive for top navigation, sidebar navigation,
9
21
  * and drawer navigation.
@@ -37,10 +49,34 @@ export type EspalierMenuOverflow = "auto" | "wrap" | "scroll" | "left-drawer" |
37
49
  * </esp-menu>
38
50
  * ```
39
51
  *
52
+ * A published site usually wants the other common mobile pattern: a panel
53
+ * that covers the whole viewport with the site's brand centered above large,
54
+ * centered items. Set `drawer-presentation="full-screen"` for that; the side
55
+ * panel stays the default for application menus. The panel is modal: the
56
+ * content beside it goes inert, scrolling locks, focus moves in, Tab cycles
57
+ * its controls, and Escape closes it. Any drawer sits on the top layer, so a
58
+ * dialog or lightbox opened from one of its items cannot stack above it: an
59
+ * open drawer closes when another overlay opens, and that overlay returns
60
+ * focus to the drawer's trigger when it closes. An owning `esp-header` mirrors its
61
+ * configured brand into the panel and keeps its own menu toggle on the top
62
+ * layer so the burger closes the panel it opened:
63
+ *
64
+ * ```html
65
+ * <esp-header brand-text="Espalier" brand-href="#" menu-display="drawer">
66
+ * <esp-menu slot="menu" mode="horizontal" drawer-presentation="full-screen" full-screen-transition="slide-down">
67
+ * <esp-menu-item label="Classes" url="#classes"></esp-menu-item>
68
+ * <esp-menu-item label="Schedule" url="#schedule"></esp-menu-item>
69
+ * <esp-menu-item label="About" url="#about"></esp-menu-item>
70
+ * </esp-menu>
71
+ * </esp-header>
72
+ * ```
73
+ *
40
74
  * @customElement esp-menu
41
75
  * @slot - `esp-menu-item` and `esp-menu-group` children.
76
+ * @slot drawer-brand - Custom brand markup for the full-screen drawer. When empty, the brand an owning `esp-header` mirrors in renders instead.
42
77
  *
43
78
  * @event {CustomEvent} esp-menu-drawer-opened - Fired when the drawer opens.
79
+ * @event {CustomEvent} esp-menu-drawer-presented - Fired once the drawer's popover is on the top layer, so an opener can stack its own control above it.
44
80
  * @event {CustomEvent} esp-menu-drawer-closed - Fired when the drawer closes.
45
81
  *
46
82
  * @cssprop --esp-menu-background - Background color of vertical and drawer menus.
@@ -49,6 +85,10 @@ export type EspalierMenuOverflow = "auto" | "wrap" | "scroll" | "left-drawer" |
49
85
  * @cssprop --esp-menu-scrim-color - Scrim color when the drawer is open.
50
86
  * @cssprop --esp-menu-drawer-shadow - Box shadow for the drawer overlay.
51
87
  * @cssprop --esp-menu-drawer-width - Drawer width. Defaults to `min(22rem, 86vw)`.
88
+ * @cssprop --esp-menu-drawer-item-font-size - Item label size in the full-screen drawer. Defaults to `var(--esp-type-large)`.
89
+ * @cssprop --esp-menu-drawer-transition-duration - Duration of the full-screen drawer's transition. Defaults to `0.3s`; reduced motion disables it.
90
+ * @cssprop --esp-menu-drawer-brand-logo-size - Logo height of the brand centered in the full-screen drawer. Defaults to `calc(3 * var(--esp-size-medium))`.
91
+ * @cssprop --esp-menu-drawer-brand-color - Text and logo color of the full-screen drawer's brand. Defaults to the mirrored brand color, then `var(--esp-color-headings)`.
52
92
  * @cssprop --esp-menu-top-offset - Top offset for drawers below fixed headers.
53
93
  * @docPageTitle Menu
54
94
  * @docUrl /components/menu
@@ -57,6 +97,8 @@ export type EspalierMenuOverflow = "auto" | "wrap" | "scroll" | "left-drawer" |
57
97
  * @menuIcon menu-deep
58
98
  */
59
99
  export declare class EspalierMenu extends EspalierElementBase {
100
+ /** Host hook for the swipe controller: a full-screen open is modal-managed here. */
101
+ ownsDrawerLock(): boolean;
60
102
  constructor();
61
103
  /**
62
104
  * Rendering mode: horizontal top navigation, vertical sidebar
@@ -74,6 +116,38 @@ export declare class EspalierMenu extends EspalierElementBase {
74
116
  overflow: EspalierMenuOverflow;
75
117
  /** Which side the drawer is attached to. */
76
118
  side: "left" | "right";
119
+ /**
120
+ * How the drawer presents: `panel` slides a side panel in beside a scrim
121
+ * (the default, suited to application menus); `full-screen` covers the
122
+ * viewport from its top edge with the brand centered above large,
123
+ * centered items and no scrim. Unsupported values read as `panel`.
124
+ */
125
+ drawerPresentation: EspalierMenuDrawerPresentation;
126
+ /**
127
+ * Motion the full-screen drawer enters and leaves with: `fade` (default),
128
+ * `slide-down` from above, `slide-up` from below, `slide-left` from the
129
+ * right edge, or `slide-right` from the left edge. Timed by
130
+ * `--esp-menu-drawer-transition-duration` and disabled under reduced
131
+ * motion. The side panel keeps its own slide.
132
+ */
133
+ fullScreenTransition: EspalierMenuFullScreenTransition;
134
+ /**
135
+ * Brand rendered above the items of a full-screen drawer when the
136
+ * `drawer-brand` slot is empty. An owning `esp-header` keeps this in step
137
+ * with its configured brand; set it directly for a standalone menu.
138
+ */
139
+ drawerBrand: EspalierMenuDrawerBrand | null;
140
+ /**
141
+ * A close control the opener keeps visible above a full-screen panel —
142
+ * `esp-header` sets its lifted menu toggle here. While set, the panel
143
+ * renders no close button of its own and includes the control in its
144
+ * Tab cycle; otherwise the panel renders its own close button, so a
145
+ * standalone menu, a `drawer-target` header, or a swipe-opened panel is
146
+ * never left without one.
147
+ */
148
+ liftedCloseControl: HTMLElement | null;
149
+ /** Whether the drawer presents full-screen rather than as a side panel. */
150
+ get isFullScreenDrawer(): boolean;
77
151
  /** Accessible label for the navigation landmark. */
78
152
  ariaLabel: string | null;
79
153
  /** Automatically expand groups to reveal the current page. */