@taprootio/espalier 2.3.1 → 2.5.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.
@@ -2,11 +2,19 @@ import { type PropertyValues } from "lit";
2
2
  import "../burger/esp-burger.js";
3
3
  import { type EspalierBurger } from "../burger/esp-burger.js";
4
4
  import { EspalierElementBase } from "../shared/esp-element-base.js";
5
- type HeaderLayout = "standard" | "centered-brand" | "extended" | "extended-centered" | "minimal";
6
- type HeaderBrandAlign = "start" | "center" | "end";
7
- type HeaderBrandWrap = "truncate" | "wrap" | "nowrap";
8
- type HeaderMenuDisplay = "auto" | "inline" | "drawer";
9
- type HeaderThemeToggle = "hidden" | "visible";
5
+ declare const HEADER_LAYOUT_VALUES: readonly ["standard", "centered-brand", "extended", "extended-centered", "minimal"];
6
+ declare const HEADER_BRAND_ALIGN_VALUES: readonly ["start", "center", "end"];
7
+ declare const HEADER_BRAND_WRAP_VALUES: readonly ["truncate", "wrap", "nowrap"];
8
+ declare const HEADER_MENU_DISPLAY_VALUES: readonly ["auto", "inline", "drawer"];
9
+ declare const HEADER_THEME_TOGGLE_VALUES: readonly ["hidden", "visible"];
10
+ export type HeaderLayout = (typeof HEADER_LAYOUT_VALUES)[number];
11
+ export type HeaderBrandAlign = (typeof HEADER_BRAND_ALIGN_VALUES)[number];
12
+ export type HeaderBrandWrap = (typeof HEADER_BRAND_WRAP_VALUES)[number];
13
+ export type HeaderMenuDisplay = (typeof HEADER_MENU_DISPLAY_VALUES)[number];
14
+ export type HeaderThemeToggle = (typeof HEADER_THEME_TOGGLE_VALUES)[number];
15
+ export interface EspThemeToggleEventDetail {
16
+ scheme: "light" | "dark";
17
+ }
10
18
  /**
11
19
  * Used to build the top navigation for a site. An empty header
12
20
  * displays a bar. It has three slots for populating header content:
@@ -104,10 +112,13 @@ type HeaderThemeToggle = "hidden" | "visible";
104
112
  * <esp-header
105
113
  * slot="header"
106
114
  * layout="centered-brand"
107
- * brand-logo="/assets/favicon.svg"
115
+ * light-brand-logo="/assets/logo-light.svg"
116
+ * dark-brand-logo="/assets/logo-dark.svg"
108
117
  * brand-text="Espalier"
109
118
  * brand-href="/"
110
119
  * brand-alt="Espalier logo"
120
+ * light-brand-color="oklch(0.35 0.12 216)"
121
+ * dark-brand-color="oklch(0.9 0.08 216)"
111
122
  * brand-align="center"
112
123
  * menu-display="auto"
113
124
  * theme-toggle="visible"
@@ -137,6 +148,19 @@ type HeaderThemeToggle = "hidden" | "visible";
137
148
  * </esp-header>
138
149
  * ```
139
150
  *
151
+ * The built-in theme toggle emits `esp-theme-toggle` only for a visitor
152
+ * activation, so a host can persist explicit choices without treating
153
+ * automatic scheme resolution as intent:
154
+ *
155
+ * ```js
156
+ * const root = document.querySelector("esp-root");
157
+ * root.addEventListener("esp-theme-toggle", (event) => {
158
+ * localStorage.setItem("scheme", event.detail.scheme);
159
+ * });
160
+ * ```
161
+ *
162
+ * @event {CustomEvent<EspThemeToggleEventDetail>} esp-theme-toggle - Fired after the built-in theme toggle changes the nearest `esp-root`. Bubbles and crosses the shadow boundary.
163
+ *
140
164
  * @cssprop --esp-header-background - The background color of the header bar. Defaults to `var(--esp-color-layer-2)`.
141
165
  * @cssprop --esp-header-border-width - The border width of the header. Defaults to `0 0 1px 0`.
142
166
  * @cssprop --esp-header-border - The border style of the header. Defaults to `solid var(--esp-color-border)`.
@@ -240,6 +264,8 @@ export declare class EspalierHeader extends EspalierElementBase {
240
264
  * picker.addEventListener("value-changed", applyLayout);
241
265
  * </script>
242
266
  * ```
267
+ *
268
+ * @default "standard"
243
269
  */
244
270
  layout: HeaderLayout;
245
271
  /**
@@ -250,6 +276,16 @@ export declare class EspalierHeader extends EspalierElementBase {
250
276
  * Configured brand logo URL used when the `brand` slot is empty.
251
277
  */
252
278
  brandLogo: string;
279
+ /**
280
+ * Configured brand logo URL used in light scheme. A non-empty value
281
+ * overrides `brand-logo`; an empty value falls back to it.
282
+ */
283
+ lightBrandLogo: string;
284
+ /**
285
+ * Configured brand logo URL used in dark scheme. A non-empty value
286
+ * overrides `brand-logo`; an empty value falls back to it.
287
+ */
288
+ darkBrandLogo: string;
253
289
  /**
254
290
  * Optional brand link used by configured logo/text branding.
255
291
  */
@@ -265,24 +301,40 @@ export declare class EspalierHeader extends EspalierElementBase {
265
301
  * header override.
266
302
  */
267
303
  brandColor: string;
304
+ /**
305
+ * Configured brand color used in light scheme. A non-empty value
306
+ * overrides `brand-color`; an empty value falls back to it and then
307
+ * `--esp-header-brand-color`.
308
+ */
309
+ lightBrandColor: string;
310
+ /**
311
+ * Configured brand color used in dark scheme. A non-empty value
312
+ * overrides `brand-color`; an empty value falls back to it and then
313
+ * `--esp-header-brand-color`.
314
+ */
315
+ darkBrandColor: string;
268
316
  /**
269
317
  * Horizontal placement of the brand content inside its grid area.
318
+ * @default "start"
270
319
  */
271
320
  brandAlign: HeaderBrandAlign;
272
321
  /**
273
322
  * Long-brand behavior for configured brand text.
323
+ * @default "truncate"
274
324
  */
275
325
  brandWrap: HeaderBrandWrap;
276
326
  /**
277
327
  * Navigation display intent. `auto` tries inline navigation before
278
328
  * using a drawer, `drawer` always uses the burger/drawer pattern,
279
329
  * and `inline` leaves overflow handling to the slotted menu.
330
+ * @default "auto"
280
331
  */
281
332
  menuDisplay: HeaderMenuDisplay;
282
333
  /**
283
334
  * Whether the header renders its built-in light/dark toggle.
284
335
  * Consumers can still provide their own control in the `buttons`
285
336
  * slot when this is `hidden`.
337
+ * @default "hidden"
286
338
  */
287
339
  themeToggle: HeaderThemeToggle;
288
340
  /**
@@ -323,6 +375,7 @@ export declare class EspalierHeader extends EspalierElementBase {
323
375
  * (e.g. when a drawer is closed via swipe).
324
376
  */
325
377
  get burger(): EspalierBurger | undefined;
378
+ protected willUpdate(changedProperties: PropertyValues): void;
326
379
  protected firstUpdated(props: PropertyValues): void;
327
380
  protected updated(changedProperties: PropertyValues): void;
328
381
  connectedCallback(): void;
@@ -1,42 +1,41 @@
1
- var n=function(p,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(p,e,t,o);else for(var h=p.length-1;h>=0;h--)(l=p[h])&&(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 x,html as d,nothing as c}from"lit";import{customElement as D,property as a,state as u}from"lit/decorators.js";import{classMap as M}from"lit/directives/class-map.js";import{styleMap as T}from"lit/directives/style-map.js";import"../burger/esp-burger.js";import{createRef as f,ref as v}from"lit/directives/ref.js";import{EspalierMenu as m}from"./esp-menu.js";import{EspalierElementBase as w}from"../shared/esp-element-base.js";const S="(max-width: 36rem)";let r=class extends w{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="standard",this.brandText="",this.brandLogo="",this.brandHref="",this.brandAlt="",this.brandColor="",this.brandAlign="start",this.brandWrap="truncate",this.menuDisplay="auto",this.themeToggle="hidden",this.scrollBehavior="none",this.scrollThreshold=16,this.dockOffset=0,this.drawerTarget="",this.fullBleedContent=!1,this.menuContainer=f(),this.menuButton=f(),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.scrollRafId=null,this.resizeObserver=new ResizeObserver(()=>this.syncMenuLayout()),this.menuChildObserver=null,this.updateScrollState=()=>{this.scrollRafId===null&&(this.scrollRafId=requestAnimationFrame(()=>{this.scrollRafId=null,this.runScrollStateUpdate()}))},this.handleMobileMenuQueryChange=e=>{this.mobileMenu=e.matches,this.syncMenuLayout(),this.syncExternalDrawerControl()},this.toggleTheme=()=>{const e=this.getThemeRoot();e&&(e.scheme=e.scheme==="dark"?"light":"dark")},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.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,h=e.has("reveal")&&l&&t>o&&!this.menuOpen;if(this.scrolled=i,this.hiddenByScroll=h,e.has("progress")){const g=document.documentElement,b=Math.max(1,g.scrollHeight-window.innerHeight);this.scrollProgress=Math.min(1,t/b)}else this.scrollProgress=0;this.lastScrollY=t}cancelScrollUpdate(){this.scrollRafId!==null&&(cancelAnimationFrame(this.scrollRafId),this.scrollRafId=null)}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("drawer-opened",this.onMenuDrawerOpened),this.menu.addEventListener("drawer-closed",this.onMenuDrawerClosed),this.menuDrawerListenersAttached=!0)}removeMenuDrawerListeners(){!this.menu||!this.menuDrawerListenersAttached||(this.menu.removeEventListener("drawer-opened",this.onMenuDrawerOpened),this.menu.removeEventListener("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(S),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("drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.removeEventListener("drawer-closed",this.onMenuDrawerClosed),this.externalDrawerTarget instanceof m&&(this.externalDrawerTarget.hasExternalDrawerControl=!1),this.externalDrawerTarget=t,this.externalDrawerTarget?.addEventListener("drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.addEventListener("drawer-closed",this.onMenuDrawerClosed)),this.syncExternalDrawerControl()}burgerVisibleForTarget(){if(this.menuDisplay==="inline")return!1;const e=this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal";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}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"))&&(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("drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.removeEventListener("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()}renderConfiguredBrand(){if(!this.brandLogo&&!this.brandText)return c;const e=this.brandAlt||(this.brandText?"":"Site logo"),t=d`
2
- ${this.brandLogo?d`<img class="brand-logo" src=${this.brandLogo} alt=${e} />`:c}
3
- ${this.brandText?d`<span class="brand-text">${this.brandText}</span>`:c}
4
- `;return this.brandHref?d`<a class="configured-brand" href=${this.brandHref}>${t}</a>`:d`<span class="configured-brand">${t}</span>`}render(){const{menuOpen:e,menuTooLarge:t,mobileMenu:o}=this,s=this.menuDisplay!=="inline",i=s&&(this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal"),l=this.getScrollTokens(),h=l.has("progress"),g={"--_esp-header-brand-color":this.brandColor||null,"--_esp-header-scroll-progress":String(this.scrollProgress)},b={"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")},y=this.scheme==="dark"?"light":"dark";return d`
5
- <header class=${M(b)} style=${T(g)}>
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 C,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 A}from"lit/directives/class-map.js";import{styleMap as B}from"lit/directives/style-map.js";import"../burger/esp-burger.js";import{createRef as E,ref as L}from"lit/directives/ref.js";import{EspalierMenu as m}from"./esp-menu.js";import{renderConfiguredBrand as O,resolveConfiguredBrand as _}from"../shared/configured-brand.js";import{EspalierElementBase as T}from"../shared/esp-element-base.js";import{ESP_EVENTS as R}from"../shared/events.js";const z="(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 H=["standard","centered-brand","extended","extended-centered","minimal"],V=["start","center","end"],U=["truncate","wrap","nowrap"],N=["auto","inline","drawer"],I=["hidden","visible"],g=u(H,"standard"),b=u(V,"start"),f=u(U,"truncate"),v=u(N,"auto"),w=u(I,"hidden");let r=class extends T{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.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.scrollRafId=null,this.resizeObserver=new ResizeObserver(()=>this.syncMenuLayout()),this.menuChildObserver=null,this.updateScrollState=()=>{this.scrollRafId===null&&(this.scrollRafId=requestAnimationFrame(()=>{this.scrollRafId=null,this.runScrollStateUpdate()}))},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(R.ESP_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.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.scrollRafId!==null&&(cancelAnimationFrame(this.scrollRafId),this.scrollRafId=null)}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("drawer-opened",this.onMenuDrawerOpened),this.menu.addEventListener("drawer-closed",this.onMenuDrawerClosed),this.menuDrawerListenersAttached=!0)}removeMenuDrawerListeners(){!this.menu||!this.menuDrawerListenersAttached||(this.menu.removeEventListener("drawer-opened",this.onMenuDrawerOpened),this.menu.removeEventListener("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(z),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("drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.removeEventListener("drawer-closed",this.onMenuDrawerClosed),this.externalDrawerTarget instanceof m&&(this.externalDrawerTarget.hasExternalDrawerControl=!1),this.externalDrawerTarget=t,this.externalDrawerTarget?.addEventListener("drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.addEventListener("drawer-closed",this.onMenuDrawerClosed)),this.syncExternalDrawerControl()}burgerVisibleForTarget(){if(this.menuDisplay==="inline")return!1;const e=this.showBurger||this.menuDisplay==="drawer"||this.layout==="minimal";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")&&!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 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"))&&(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("drawer-opened",this.onMenuDrawerOpened),this.externalDrawerTarget?.removeEventListener("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"),l=this.getScrollTokens(),d=l.has("progress"),p=_({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")},S=this.scheme==="dark"?"light":"dark";return x`
2
+ <header class=${A(M)} style=${B(y)}>
6
3
  <section class="topbar">
7
4
  <slot name="topbar"></slot>
8
5
  </section>
9
6
 
10
7
  <section class="brand">
11
- <slot name="brand">${this.renderConfiguredBrand()}</slot>
8
+ <slot name="brand"
9
+ >${O({brandLogo:p.brandLogo,brandText:this.brandText,brandHref:this.brandHref,brandAlt:this.brandAlt})}</slot
10
+ >
12
11
  </section>
13
12
 
14
- <section ${v(this.menuContainer)} class="menu-container">
13
+ <section ${L(this.menuContainer)} class="menu-container">
15
14
  <slot name="menu"></slot>
16
15
  </section>
17
16
 
18
17
  <section class="buttons">
19
18
  <slot name="buttons"></slot>
20
- ${this.themeToggle==="visible"?d`<esp-header-button
19
+ ${this.themeToggle==="visible"?x`<esp-header-button
21
20
  class="theme-toggle"
22
21
  icon=${this.scheme==="dark"?"sun":"moon"}
23
- aria-label=${`Switch to ${y} mode`}
22
+ aria-label=${`Switch to ${S} mode`}
24
23
  @clicked=${this.toggleTheme}
25
- ></esp-header-button>`:c}
24
+ ></esp-header-button>`:D}
26
25
  <esp-header-button
27
26
  class="menu-toggle"
28
27
  role="button"
29
28
  aria-label=${e?"Close navigation":"Open navigation"}
30
- aria-controls=${this.drawerTarget||c}
29
+ aria-controls=${this.drawerTarget||D}
31
30
  aria-expanded=${e?"true":"false"}
32
31
  @clicked=${this.handleMenuToggleClicked}
33
32
  >
34
- <esp-burger ${v(this.menuButton)} presentation-only></esp-burger>
33
+ <esp-burger ${L(this.menuButton)} presentation-only></esp-burger>
35
34
  </esp-header-button>
36
35
  </section>
37
- ${h?d`<div class="scroll-progress" aria-hidden="true"></div>`:c}
36
+ ${d?x`<div class="scroll-progress" aria-hidden="true"></div>`:D}
38
37
  </header>
39
- `}};r.styles=[...w.styles,x`
38
+ `}};r.styles=[...T.styles,C`
40
39
  :host {
41
40
  --_esp-header-current-height: var(--esp-header-height, calc(4.5 * var(--esp-size-small)));
42
41
 
@@ -108,7 +107,6 @@ var n=function(p,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=Object.getOwnP
108
107
  align-items: center;
109
108
  place-content: var(--esp-header-brand-placement, center start);
110
109
  padding-inline: var(--esp-header-brand-padding-inline, var(--esp-size-small));
111
- color: var(--_esp-header-brand-resolved-color);
112
110
 
113
111
  slot[name="brand"] {
114
112
  display: flex;
@@ -321,7 +319,7 @@ var n=function(p,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=Object.getOwnP
321
319
  color: var(--esp-header-transparent-color, var(--esp-color-headings));
322
320
  }
323
321
 
324
- &.scroll-transparent:not(.is-scrolled) section.brand {
322
+ &.scroll-transparent:not(.is-scrolled) .configured-brand {
325
323
  color: var(--esp-header-transparent-color, var(--_esp-header-brand-resolved-color));
326
324
  }
327
325
 
@@ -431,4 +429,4 @@ var n=function(p,e,t,o){var s=arguments.length,i=s<3?e:o===null?o=Object.getOwnP
431
429
  transition: none;
432
430
  }
433
431
  }
434
- `],n([u()],r.prototype,"menuOpen",void 0),n([u()],r.prototype,"menuTooLarge",void 0),n([u()],r.prototype,"mobileMenu",void 0),n([u()],r.prototype,"scrolled",void 0),n([u()],r.prototype,"hiddenByScroll",void 0),n([u()],r.prototype,"scrollProgress",void 0),n([a({attribute:"show-burger",type:Boolean})],r.prototype,"showBurger",void 0),n([a({type:String,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:"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:"brand-align",type:String,reflect:!0})],r.prototype,"brandAlign",void 0),n([a({attribute:"brand-wrap",type:String,reflect:!0})],r.prototype,"brandWrap",void 0),n([a({attribute:"menu-display",type:String,reflect:!0})],r.prototype,"menuDisplay",void 0),n([a({attribute:"theme-toggle",type:String,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:"full-bleed-content",type:Boolean,reflect:!0})],r.prototype,"fullBleedContent",void 0),r=n([D("esp-header")],r);export{r as EspalierHeader};
432
+ `],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:f.converter,reflect:!0})],r.prototype,"brandWrap",void 0),n([a({attribute:"menu-display",converter:v.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:"full-bleed-content",type:Boolean,reflect:!0})],r.prototype,"fullBleedContent",void 0),r=n([k("esp-header")],r);export{r as EspalierHeader};
package/dist/index.d.ts CHANGED
@@ -25,6 +25,7 @@ export * from "./empty-state/esp-empty-state.js";
25
25
  export * from "./image-upload/esp-image-upload.js";
26
26
  export * from "./file-upload/esp-file-upload.js";
27
27
  export * from "./font-picker/esp-font-picker.js";
28
+ export * from "./footer/index.js";
28
29
  export * from "./grid/esp-grid.js";
29
30
  export * from "./image/esp-image.js";
30
31
  export * from "./lightbox/esp-lightbox.js";
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export*from"./box/esp-box.js";export*from"./action-menu/esp-action-menu.js";export*from"./action-menu/esp-action-menu-item.js";export*from"./avatar/esp-avatar.js";export*from"./avatar/esp-profile-chip.js";export*from"./badge/esp-badge.js";export*from"./checkbox/esp-checkbox.js";export*from"./checkbox/esp-checkbox-group.js";export*from"./data-cell/esp-data-cell.js";export*from"./radio-button/esp-radio-button.js";export*from"./radio-button/esp-radio-button-group.js";export*from"./repeater/esp-repeater.js";export*from"./breadcrumbs/esp-breadcrumbs.js";export*from"./button/esp-button.js";export*from"./button/esp-button-group.js";export*from"./color-picker/esp-color-picker.js";export*from"./flyout/esp-flyout.js";export*from"./form/esp-form.js";export*from"./form-item/esp-form-item.js";export*from"./header/index.js";export*from"./page/esp-page.js";export*from"./popover/esp-popover.js";export*from"./dialog/esp-dialog.js";export*from"./empty-state/esp-empty-state.js";export*from"./image-upload/esp-image-upload.js";export*from"./file-upload/esp-file-upload.js";export*from"./font-picker/esp-font-picker.js";export*from"./grid/esp-grid.js";export*from"./image/esp-image.js";export*from"./lightbox/esp-lightbox.js";export*from"./info/esp-info.js";export*from"./input/esp-input.js";export*from"./textarea/esp-textarea.js";export*from"./pickers/esp-pick-one.js";export*from"./pickers/esp-pick-some.js";export*from"./pickers/esp-picker-menu.js";export*from"./pickers/esp-picker-item.js";export*from"./root/esp-root.js";export*from"./menu/index.js";export*from"./burger/esp-burger.js";export*from"./date-picker/esp-date-picker.js";export*from"./details/esp-details.js";export*from"./details/esp-details-group.js";export*from"./tabs/esp-tab.js";export*from"./tabs/esp-tab-group.js";export*from"./slider/esp-slider.js";export*from"./switch/esp-switch.js";export*from"./toaster/esp-toaster.js";export*from"./tooltip/esp-tooltip.js";export*from"./progress/esp-progress.js";export*from"./search/esp-search.js";export*from"./status-indicator/esp-status-indicator.js";export*from"./tree/esp-tree.js";export*from"./tree/esp-tree-item.js";import{DEFAULT_ICON_SPRITE_URL as eo,DEFAULT_ICON_VIEW_BOX as to,INTENT_VARIANTS as mo,normalizeIntentVariant as po,getIconHref as fo,getIconHrefForHost as xo,getIconSpriteUrl as ao}from"./shared/intent-values.js";import{EspalierElementBase as so}from"./shared/esp-element-base.js";import{VALIDITY_CHANGED_EVENT as Eo}from"./shared/validation.js";import{FormFieldController as go}from"./shared/form-field-controller.js";import{traverseToClosest as no}from"./shared/utilities.js";import{showToast as _o}from"./shared/toast-events.js";import{showFlyout as co,closeFlyout as Ao}from"./shared/flyout-events.js";import{getEspBus as No}from"./shared/bus-events.js";export*from"./shared/events.js";import{getImageDetails as Ho,releasePreviewUrl as So}from"./image-upload/image-helpers.js";import{calculatePhotoLayout as yo}from"./shared/justified-layout.js";import{encodeTheme as Uo,parseTheme as Vo,mergePartials as Wo,layerThemes as Bo,buildTaprootLightTheme as Po,buildTaprootDarkTheme as vo,NESTED_THEME_KEYS as wo}from"./shared/theme.js";import{WEIGHT_LABELS as Oo,extractWeights as Ro,normalizeWeight as ko,bestAvailableWeight as zo,extractFamily as Yo,getFallbackFont as Ko}from"./shared/font-helpers.js";import{getGoogleFonts as Xo}from"./font-picker/esp-font-picker.js";export{eo as DEFAULT_ICON_SPRITE_URL,to as DEFAULT_ICON_VIEW_BOX,so as EspalierElementBase,go as FormFieldController,mo as INTENT_VARIANTS,wo as NESTED_THEME_KEYS,Eo as VALIDITY_CHANGED_EVENT,Oo as WEIGHT_LABELS,zo as bestAvailableWeight,vo as buildTaprootDarkTheme,Po as buildTaprootLightTheme,yo as calculatePhotoLayout,Ao as closeFlyout,Uo as encodeTheme,Yo as extractFamily,Ro as extractWeights,No as getEspBus,Ko as getFallbackFont,Xo as getGoogleFonts,fo as getIconHref,xo as getIconHrefForHost,ao as getIconSpriteUrl,Ho as getImageDetails,Bo as layerThemes,Wo as mergePartials,po as normalizeIntentVariant,ko as normalizeWeight,Vo as parseTheme,So as releasePreviewUrl,co as showFlyout,_o as showToast,no as traverseToClosest};
1
+ export*from"./box/esp-box.js";export*from"./action-menu/esp-action-menu.js";export*from"./action-menu/esp-action-menu-item.js";export*from"./avatar/esp-avatar.js";export*from"./avatar/esp-profile-chip.js";export*from"./badge/esp-badge.js";export*from"./checkbox/esp-checkbox.js";export*from"./checkbox/esp-checkbox-group.js";export*from"./data-cell/esp-data-cell.js";export*from"./radio-button/esp-radio-button.js";export*from"./radio-button/esp-radio-button-group.js";export*from"./repeater/esp-repeater.js";export*from"./breadcrumbs/esp-breadcrumbs.js";export*from"./button/esp-button.js";export*from"./button/esp-button-group.js";export*from"./color-picker/esp-color-picker.js";export*from"./flyout/esp-flyout.js";export*from"./form/esp-form.js";export*from"./form-item/esp-form-item.js";export*from"./header/index.js";export*from"./page/esp-page.js";export*from"./popover/esp-popover.js";export*from"./dialog/esp-dialog.js";export*from"./empty-state/esp-empty-state.js";export*from"./image-upload/esp-image-upload.js";export*from"./file-upload/esp-file-upload.js";export*from"./font-picker/esp-font-picker.js";export*from"./footer/index.js";export*from"./grid/esp-grid.js";export*from"./image/esp-image.js";export*from"./lightbox/esp-lightbox.js";export*from"./info/esp-info.js";export*from"./input/esp-input.js";export*from"./textarea/esp-textarea.js";export*from"./pickers/esp-pick-one.js";export*from"./pickers/esp-pick-some.js";export*from"./pickers/esp-picker-menu.js";export*from"./pickers/esp-picker-item.js";export*from"./root/esp-root.js";export*from"./menu/index.js";export*from"./burger/esp-burger.js";export*from"./date-picker/esp-date-picker.js";export*from"./details/esp-details.js";export*from"./details/esp-details-group.js";export*from"./tabs/esp-tab.js";export*from"./tabs/esp-tab-group.js";export*from"./slider/esp-slider.js";export*from"./switch/esp-switch.js";export*from"./toaster/esp-toaster.js";export*from"./tooltip/esp-tooltip.js";export*from"./progress/esp-progress.js";export*from"./search/esp-search.js";export*from"./status-indicator/esp-status-indicator.js";export*from"./tree/esp-tree.js";export*from"./tree/esp-tree-item.js";import{DEFAULT_ICON_SPRITE_URL as to,DEFAULT_ICON_VIEW_BOX as mo,INTENT_VARIANTS as po,normalizeIntentVariant as fo,getIconHref as xo,getIconHrefForHost as ao,getIconSpriteUrl as lo}from"./shared/intent-values.js";import{EspalierElementBase as To}from"./shared/esp-element-base.js";import{VALIDITY_CHANGED_EVENT as io}from"./shared/validation.js";import{FormFieldController as Io}from"./shared/form-field-controller.js";import{traverseToClosest as ho}from"./shared/utilities.js";import{showToast as Fo}from"./shared/toast-events.js";import{showFlyout as Ao,closeFlyout as Lo}from"./shared/flyout-events.js";import{getEspBus as uo}from"./shared/bus-events.js";export*from"./shared/events.js";import{getImageDetails as So,releasePreviewUrl as bo}from"./image-upload/image-helpers.js";import{calculatePhotoLayout as Co}from"./shared/justified-layout.js";import{encodeTheme as Vo,parseTheme as Wo,mergePartials as Bo,layerThemes as Po,buildTaprootLightTheme as vo,buildTaprootDarkTheme as wo,NESTED_THEME_KEYS as Go}from"./shared/theme.js";import{WEIGHT_LABELS as Ro,extractWeights as ko,normalizeWeight as zo,bestAvailableWeight as Yo,extractFamily as Ko,getFallbackFont as Mo}from"./shared/font-helpers.js";import{getGoogleFonts as jo}from"./font-picker/esp-font-picker.js";export{to as DEFAULT_ICON_SPRITE_URL,mo as DEFAULT_ICON_VIEW_BOX,To as EspalierElementBase,Io as FormFieldController,po as INTENT_VARIANTS,Go as NESTED_THEME_KEYS,io as VALIDITY_CHANGED_EVENT,Ro as WEIGHT_LABELS,Yo as bestAvailableWeight,wo as buildTaprootDarkTheme,vo as buildTaprootLightTheme,Co as calculatePhotoLayout,Lo as closeFlyout,Vo as encodeTheme,Ko as extractFamily,ko as extractWeights,uo as getEspBus,Mo as getFallbackFont,jo as getGoogleFonts,xo as getIconHref,ao as getIconHrefForHost,lo as getIconSpriteUrl,So as getImageDetails,Po as layerThemes,Bo as mergePartials,fo as normalizeIntentVariant,zo as normalizeWeight,Wo as parseTheme,bo as releasePreviewUrl,Ao as showFlyout,Fo as showToast,ho as traverseToClosest};
@@ -12,7 +12,20 @@ export type EspalierMenuOverflow = "auto" | "wrap" | "scroll" | "left-drawer" |
12
12
  * sidebar navigation, and `mode="drawer"` for drawer-only navigation.
13
13
  * The same tree of `esp-menu-item` and `esp-menu-group` children can
14
14
  * render inline and as a drawer so consumers do not need duplicate
15
- * navigation markup for desktop and mobile.
15
+ * navigation markup for desktop and mobile. An inline vertical rail keeps
16
+ * its intrinsic height so a page-level layout can move a tall sidebar with
17
+ * document scroll; the fixed drawer presentation supplies its own vertical
18
+ * scrolling instead.
19
+ *
20
+ * **2.4 migration:** inline vertical rails no longer create their own bounded
21
+ * scroller. A standalone menu inside a fixed-height or overflow-hidden shell
22
+ * can restore that presentation by bounding and scrolling the host:
23
+ *
24
+ * ```html
25
+ * <esp-menu mode="vertical" style="max-height: 100dvh; overflow-y: auto;">
26
+ * ...
27
+ * </esp-menu>
28
+ * ```
16
29
  *
17
30
  * ```html
18
31
  * <esp-menu mode="horizontal" overflow="left-drawer">
@@ -1,4 +1,4 @@
1
- var n=function(p,e,r,o){var t=arguments.length,i=t<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,r):o,s;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(p,e,r,o);else for(var h=p.length-1;h>=0;h--)(s=p[h])&&(i=(t<3?s(i):t>3?s(e,r,i):s(e,r))||i);return t>3&&i&&Object.defineProperty(e,r,i),i};import{css as x,html as w,nothing as f}from"lit";import{customElement as E,property as l,state as g}from"lit/decorators.js";import{classMap as m}from"lit/directives/class-map.js";import{unsafeHTML as v}from"lit/directives/unsafe-html.js";import{createRef as d,ref as c}from"lit/directives/ref.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{getEspBus as D}from"../shared/bus-events.js";import{normalizePath as S,pathStartsWithSegment as y,pathsMatch as T}from"../shared/path-matching.js";import{SwipeRevealController as A}from"./swipe-reveal-controller.js";import"./esp-menu-item.js";import"./esp-menu-group.js";import{EspalierMenuItem as C}from"./esp-menu-item.js";import{EspalierMenuGroup as u}from"./esp-menu-group.js";const O="(max-width: 50em)";let a=class extends b{constructor(){super(),this.itemsSlot=d(),this.railRef=d(),this.scrimRef=d(),this.drawerRef=d(),this.bus=D(),this.closeTransitionTimer=null,this.drawerGroupOpenOverrides=new Map,this._sliding=!1,this._mobileCollapsed=!1,this.verticalDrawerQuery=null,this.onVerticalDrawerChange=e=>this.setMobileCollapsed(e.matches),this.mode="horizontal",this.overflow="auto",this.side="left",this.ariaLabel=null,this.autoExpand=!1,this.drawerOpen=!1,this.drawerTransitioning=!1,this.drawerTrigger=null,this.hasExternalDrawerControl=!1,this.getWidth=()=>{const e=this.railRef.value;return e?Math.max(e.scrollWidth,e.clientWidth):-1},this.onDrawerTransitionEnd=()=>{this.closeTransitionTimer&&(clearTimeout(this.closeTransitionTimer),this.closeTransitionTimer=null),this.drawerTransitioning=!1,this.drawerOpen||(this.hideDrawerPopover(),this.drawerGroupOpenOverrides.clear())},this.swipeController=new A(this,this.side),this.swipeController.enabled=!1}get sliding(){return this._sliding}set sliding(e){const r=this._sliding;this._sliding=e,this.syncSwipeEnabled(),this.propagateToItems(),this.requestUpdate("sliding",r)}get collapsed(){return this.drawerActive}set collapsed(e){e?this.mode="drawer":this.mode==="drawer"&&(this.mode="vertical")}get drawerSide(){return this.overflow==="right-drawer"?"right":this.overflow==="left-drawer"?"left":this.side}get drawerActive(){return this.mode==="drawer"||this._sliding||this.overflow==="left-drawer"||this.overflow==="right-drawer"||this.mode==="vertical"&&this._mobileCollapsed&&this.hasExternalDrawerControl}get railMode(){return this.mode==="horizontal"?"horizontal":"vertical"}connectedCallback(){super.connectedCallback(),this.getAttribute("slot")==="right"&&(this.side="right"),!this.verticalDrawerQuery&&typeof window<"u"&&"matchMedia"in window&&(this.verticalDrawerQuery=window.matchMedia(O),this._mobileCollapsed=this.verticalDrawerQuery.matches,this.verticalDrawerQuery.addEventListener("change",this.onVerticalDrawerChange)),this.syncSwipeEnabled()}disconnectedCallback(){this.verticalDrawerQuery?.removeEventListener("change",this.onVerticalDrawerChange),this.verticalDrawerQuery=null,super.disconnectedCallback()}setMobileCollapsed(e){e!==this._mobileCollapsed&&(this._mobileCollapsed=e,this.mode==="vertical"&&this.applyMobileCollapse())}applyMobileCollapse(){this.swipeController.direction=this.drawerSide,this.syncSwipeEnabled(),this.propagateToItems(),this.requestUpdate(),!this.drawerActive&&this.drawerOpen&&this.swipeController.close(!0)}firstUpdated(e){super.firstUpdated(e),this.propagateToItems()}updated(e){super.updated(e),(e.has("mode")||e.has("overflow")||e.has("side")||e.has("hasExternalDrawerControl"))&&(this.swipeController.direction=this.drawerSide,this.syncSwipeEnabled(),this.propagateToItems(),!this.drawerActive&&this.drawerOpen&&this.swipeController.close(!0)),this.autoExpand&&(e.has("autoExpand")||e.has("mode")&&this.mode!=="horizontal")?this.expandToCurrentPage():this.mode==="horizontal"&&e.has("mode")&&this.closeHorizontalTopLevelGroups()}openDrawer(e){this.drawerActive&&(e?this.drawerTrigger=e:this.drawerOpen||(this.drawerTrigger=null),this.swipeController.open())}closeDrawer(){this.swipeController.close(!0)}toggleDrawer(e){this.drawerOpen?this.closeDrawer():this.openDrawer(e)}toggleOpened(){this.toggleDrawer()}get isDrawerOpen(){return this.drawerOpen}syncSwipeEnabled(){this.swipeController.direction=this.drawerSide,this.swipeController.enabled=this.drawerActive}getAssignedChildren(){return this.itemsSlot.value?.assignedElements()??[]}propagateToItems(){const e=this.railMode;for(const r of this.getAssignedChildren())r instanceof C?(r.mode=e,r.depth=0,r.touchDevice=this.swipeController.isTouch):r instanceof u&&(r.mode=e,r.depth=0,r.touchDevice=this.swipeController.isTouch)}handleSlotChange(){this.propagateToItems()}onSwipeRevealChanged(e){e!==this.drawerOpen&&(this.drawerOpen=e,e?(this.drawerGroupOpenOverrides.clear(),this.bus.publish("close-popovers",{}),this.updateComplete.then(()=>this.showDrawerPopover())):(this.drawerTransitioning=!0,this.updateComplete.then(()=>this.startCloseTransition()),requestAnimationFrame(()=>this.restoreDrawerTriggerFocus())),this.dispatchEvent(new CustomEvent(e?"drawer-opened":"drawer-closed",{bubbles:!0,composed:!0})))}showDrawerPopover(){const e=this.scrimRef.value,r=this.drawerRef.value;if(!(!e||!r)){this.swipeController.drawerElement=r;try{e.showPopover(),r.showPopover()}catch{}r.getBoundingClientRect(),requestAnimationFrame(()=>{this.drawerTransitioning=!0,this.requestUpdate()})}}startCloseTransition(){if(!this.drawerRef.value){this.hideDrawerPopover();return}this.closeTransitionTimer&&clearTimeout(this.closeTransitionTimer),this.closeTransitionTimer=setTimeout(()=>{this.closeTransitionTimer=null,!this.drawerOpen&&this.drawerTransitioning&&this.onDrawerTransitionEnd()},400)}hideDrawerPopover(){const e=this.scrimRef.value,r=this.drawerRef.value;this.swipeController.drawerElement=null,r&&(r.style.cssText="");try{r?.hidePopover()}catch{}try{e?.hidePopover()}catch{}}restoreDrawerTriggerFocus(){const e=this.drawerTrigger;this.drawerTrigger=null,e?.isConnected&&e.focus({preventScroll:!0})}getAutoExpandedGroups(e=!0){const r=new Set;let o=null;for(const i of this.querySelectorAll("esp-menu-item")){const s=i.url||i.getAttribute("url");if(s&&T(s)){o=i;break}}if(!o)for(const i of this.querySelectorAll("esp-menu-group")){const s=i.url||i.getAttribute("url");if(s&&T(s)){o=i;break}}if(!o&&e){for(const i of this.querySelectorAll("esp-menu-group"))i.parentElement===this&&r.add(i);return r}if(!o)return r;o instanceof u&&r.add(o);let t=o.parentElement;for(;t&&t!==this;)t instanceof u&&r.add(t),t=t.parentElement;return r}isHorizontalTopLevelGroup(e){return e.mode==="horizontal"&&e.depth===0}groupUrlPrefixMatches(e){return y(location.pathname,e.urlPrefix)}groupPathMatches(e){if(this.groupUrlPrefixMatches(e))return!0;const r=e.url||e.getAttribute("url");return r?y(location.pathname,S(r)):!1}expandToCurrentPage(){const e=this.getAutoExpandedGroups(),r=this.querySelectorAll("esp-menu-group");for(const o of r)o.open=e.has(o)&&!this.isHorizontalTopLevelGroup(o)}closeHorizontalTopLevelGroups(){for(const e of this.querySelectorAll("esp-menu-group"))this.isHorizontalTopLevelGroup(e)&&(e.open=!1)}getDrawerAutoExpandedGroups(){return this.getAutoExpandedGroups(!1)}collectDrawerNodes(e,r=this.getDrawerAutoExpandedGroups()){const o=[];for(const t of e)if(t instanceof C){const i=t.querySelector(":scope > svg, :scope > img");o.push({kind:"item",label:t.label,url:t.url,open:!1,icon:t.icon,iconHtml:i?.outerHTML||"",children:[],originalItem:t,originalGroup:null})}else if(t instanceof u){const i=t.querySelector(':scope > [slot="icon"]'),s=r.has(t)||this.groupPathMatches(t),h=this.drawerGroupOpenOverrides.get(t)??(t.open||s);o.push({kind:"group",label:t.label,url:t.url||"",open:h,icon:t.icon,iconHtml:i?.outerHTML||"",children:this.collectDrawerNodes(Array.from(t.children),r),originalItem:null,originalGroup:t})}return o}renderDrawerNode(e){return e.kind==="item"?w`<esp-menu-item
1
+ var n=function(d,e,r,o){var t=arguments.length,i=t<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,r):o,s;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(d,e,r,o);else for(var h=d.length-1;h>=0;h--)(s=d[h])&&(i=(t<3?s(i):t>3?s(e,r,i):s(e,r))||i);return t>3&&i&&Object.defineProperty(e,r,i),i};import{css as x,html as w,nothing as f}from"lit";import{customElement as E,property as l,state as g}from"lit/decorators.js";import{classMap as m}from"lit/directives/class-map.js";import{unsafeHTML as v}from"lit/directives/unsafe-html.js";import{createRef as p,ref as c}from"lit/directives/ref.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{getEspBus as D}from"../shared/bus-events.js";import{normalizePath as S,pathStartsWithSegment as y,pathsMatch as T}from"../shared/path-matching.js";import{SwipeRevealController as A}from"./swipe-reveal-controller.js";import"./esp-menu-item.js";import"./esp-menu-group.js";import{EspalierMenuItem as C}from"./esp-menu-item.js";import{EspalierMenuGroup as u}from"./esp-menu-group.js";const O="(max-width: 50em)";let a=class extends b{constructor(){super(),this.itemsSlot=p(),this.railRef=p(),this.scrimRef=p(),this.drawerRef=p(),this.bus=D(),this.closeTransitionTimer=null,this.drawerGroupOpenOverrides=new Map,this._sliding=!1,this._mobileCollapsed=!1,this.verticalDrawerQuery=null,this.onVerticalDrawerChange=e=>this.setMobileCollapsed(e.matches),this.mode="horizontal",this.overflow="auto",this.side="left",this.ariaLabel=null,this.autoExpand=!1,this.drawerOpen=!1,this.drawerTransitioning=!1,this.drawerTrigger=null,this.hasExternalDrawerControl=!1,this.getWidth=()=>{const e=this.railRef.value;return e?Math.max(e.scrollWidth,e.clientWidth):-1},this.onDrawerTransitionEnd=()=>{this.closeTransitionTimer&&(clearTimeout(this.closeTransitionTimer),this.closeTransitionTimer=null),this.drawerTransitioning=!1,this.drawerOpen||(this.hideDrawerPopover(),this.drawerGroupOpenOverrides.clear())},this.swipeController=new A(this,this.side),this.swipeController.enabled=!1}get sliding(){return this._sliding}set sliding(e){const r=this._sliding;this._sliding=e,this.syncSwipeEnabled(),this.propagateToItems(),this.requestUpdate("sliding",r)}get collapsed(){return this.drawerActive}set collapsed(e){e?this.mode="drawer":this.mode==="drawer"&&(this.mode="vertical")}get drawerSide(){return this.overflow==="right-drawer"?"right":this.overflow==="left-drawer"?"left":this.side}get drawerActive(){return this.mode==="drawer"||this._sliding||this.overflow==="left-drawer"||this.overflow==="right-drawer"||this.mode==="vertical"&&this._mobileCollapsed&&this.hasExternalDrawerControl}get railMode(){return this.mode==="horizontal"?"horizontal":"vertical"}connectedCallback(){super.connectedCallback(),this.getAttribute("slot")==="right"&&(this.side="right"),!this.verticalDrawerQuery&&typeof window<"u"&&"matchMedia"in window&&(this.verticalDrawerQuery=window.matchMedia(O),this._mobileCollapsed=this.verticalDrawerQuery.matches,this.verticalDrawerQuery.addEventListener("change",this.onVerticalDrawerChange)),this.syncSwipeEnabled()}disconnectedCallback(){this.verticalDrawerQuery?.removeEventListener("change",this.onVerticalDrawerChange),this.verticalDrawerQuery=null,super.disconnectedCallback()}setMobileCollapsed(e){e!==this._mobileCollapsed&&(this._mobileCollapsed=e,this.mode==="vertical"&&this.applyMobileCollapse())}applyMobileCollapse(){this.swipeController.direction=this.drawerSide,this.syncSwipeEnabled(),this.propagateToItems(),this.requestUpdate(),!this.drawerActive&&this.drawerOpen&&this.swipeController.close(!0)}firstUpdated(e){super.firstUpdated(e),this.propagateToItems()}updated(e){super.updated(e),(e.has("mode")||e.has("overflow")||e.has("side")||e.has("hasExternalDrawerControl"))&&(this.swipeController.direction=this.drawerSide,this.syncSwipeEnabled(),this.propagateToItems(),!this.drawerActive&&this.drawerOpen&&this.swipeController.close(!0)),this.autoExpand&&(e.has("autoExpand")||e.has("mode")&&this.mode!=="horizontal")?this.expandToCurrentPage():this.mode==="horizontal"&&e.has("mode")&&this.closeHorizontalTopLevelGroups()}openDrawer(e){this.drawerActive&&(e?this.drawerTrigger=e:this.drawerOpen||(this.drawerTrigger=null),this.swipeController.open())}closeDrawer(){this.swipeController.close(!0)}toggleDrawer(e){this.drawerOpen?this.closeDrawer():this.openDrawer(e)}toggleOpened(){this.toggleDrawer()}get isDrawerOpen(){return this.drawerOpen}syncSwipeEnabled(){this.swipeController.direction=this.drawerSide,this.swipeController.enabled=this.drawerActive}getAssignedChildren(){return this.itemsSlot.value?.assignedElements()??[]}propagateToItems(){const e=this.railMode;for(const r of this.getAssignedChildren())r instanceof C?(r.mode=e,r.depth=0,r.touchDevice=this.swipeController.isTouch):r instanceof u&&(r.mode=e,r.depth=0,r.touchDevice=this.swipeController.isTouch)}handleSlotChange(){this.propagateToItems()}onSwipeRevealChanged(e){e!==this.drawerOpen&&(this.drawerOpen=e,e?(this.drawerGroupOpenOverrides.clear(),this.bus.publish("close-popovers",{}),this.updateComplete.then(()=>this.showDrawerPopover())):(this.drawerTransitioning=!0,this.updateComplete.then(()=>this.startCloseTransition()),requestAnimationFrame(()=>this.restoreDrawerTriggerFocus())),this.dispatchEvent(new CustomEvent(e?"drawer-opened":"drawer-closed",{bubbles:!0,composed:!0})))}showDrawerPopover(){const e=this.scrimRef.value,r=this.drawerRef.value;if(!(!e||!r)){this.swipeController.drawerElement=r;try{e.showPopover(),r.showPopover()}catch{}r.getBoundingClientRect(),requestAnimationFrame(()=>{this.drawerTransitioning=!0,this.requestUpdate()})}}startCloseTransition(){if(!this.drawerRef.value){this.hideDrawerPopover();return}this.closeTransitionTimer&&clearTimeout(this.closeTransitionTimer),this.closeTransitionTimer=setTimeout(()=>{this.closeTransitionTimer=null,!this.drawerOpen&&this.drawerTransitioning&&this.onDrawerTransitionEnd()},400)}hideDrawerPopover(){const e=this.scrimRef.value,r=this.drawerRef.value;this.swipeController.drawerElement=null,r&&(r.style.cssText="");try{r?.hidePopover()}catch{}try{e?.hidePopover()}catch{}}restoreDrawerTriggerFocus(){const e=this.drawerTrigger;this.drawerTrigger=null,e?.isConnected&&e.focus({preventScroll:!0})}getAutoExpandedGroups(e=!0){const r=new Set;let o=null;for(const i of this.querySelectorAll("esp-menu-item")){const s=i.url||i.getAttribute("url");if(s&&T(s)){o=i;break}}if(!o)for(const i of this.querySelectorAll("esp-menu-group")){const s=i.url||i.getAttribute("url");if(s&&T(s)){o=i;break}}if(!o&&e){for(const i of this.querySelectorAll("esp-menu-group"))i.parentElement===this&&r.add(i);return r}if(!o)return r;o instanceof u&&r.add(o);let t=o.parentElement;for(;t&&t!==this;)t instanceof u&&r.add(t),t=t.parentElement;return r}isHorizontalTopLevelGroup(e){return e.mode==="horizontal"&&e.depth===0}groupUrlPrefixMatches(e){return y(location.pathname,e.urlPrefix)}groupPathMatches(e){if(this.groupUrlPrefixMatches(e))return!0;const r=e.url||e.getAttribute("url");return r?y(location.pathname,S(r)):!1}expandToCurrentPage(){const e=this.getAutoExpandedGroups(),r=this.querySelectorAll("esp-menu-group");for(const o of r)o.open=e.has(o)&&!this.isHorizontalTopLevelGroup(o)}closeHorizontalTopLevelGroups(){for(const e of this.querySelectorAll("esp-menu-group"))this.isHorizontalTopLevelGroup(e)&&(e.open=!1)}getDrawerAutoExpandedGroups(){return this.getAutoExpandedGroups(!1)}collectDrawerNodes(e,r=this.getDrawerAutoExpandedGroups()){const o=[];for(const t of e)if(t instanceof C){const i=t.querySelector(":scope > svg, :scope > img");o.push({kind:"item",label:t.label,url:t.url,open:!1,icon:t.icon,iconHtml:i?.outerHTML||"",children:[],originalItem:t,originalGroup:null})}else if(t instanceof u){const i=t.querySelector(':scope > [slot="icon"]'),s=r.has(t)||this.groupPathMatches(t),h=this.drawerGroupOpenOverrides.get(t)??(t.open||s);o.push({kind:"group",label:t.label,url:t.url||"",open:h,icon:t.icon,iconHtml:i?.outerHTML||"",children:this.collectDrawerNodes(Array.from(t.children),r),originalItem:null,originalGroup:t})}return o}renderDrawerNode(e){return e.kind==="item"?w`<esp-menu-item
2
2
  label=${e.label}
3
3
  .url=${e.url}
4
4
  .icon=${e.icon}
@@ -79,9 +79,8 @@ var n=function(p,e,r,o){var t=arguments.length,i=t<3?e:o===null?o=Object.getOwnP
79
79
  display: flex;
80
80
  flex-direction: column;
81
81
  width: min-content;
82
- max-height: calc(100dvh - var(--esp-menu-top-offset, 0px));
83
- overflow-y: auto;
84
- scrollbar-width: thin;
82
+
83
+ overflow-y: visible;
85
84
  background-color: var(--esp-menu-background, var(--esp-color-layer-1));
86
85
  border-bottom: 1px solid var(--esp-menu-border-color, var(--esp-color-border));
87
86
  box-shadow: 2px 0 6px -2px var(--esp-color-shadow);
@@ -25,7 +25,7 @@ type HeaderPosition = "normal" | "sticky" | "fixed";
25
25
  * </esp-header>
26
26
  * <esp-menu slot="sidebar" mode="drawer"></esp-menu>
27
27
  * <div slot="right" style="background-color: purple;">right</div>
28
- * <div slot="footer" style="background-color: blue;">footer</div>
28
+ * <esp-footer slot="footer" brand-text="Espalier"></esp-footer>
29
29
  * <div style="background-color: black; overflow: hidden;">
30
30
  * content
31
31
  * </div>
@@ -43,7 +43,9 @@ type HeaderPosition = "normal" | "sticky" | "fixed";
43
43
  * The persistent `right` aside and the transient flyout are
44
44
  * complementary, not alternatives. A flyout opened with an `anchor`
45
45
  * aligns to that trigger and stays in the same document scroll flow.
46
- * @slot footer - Content to place in the footer.
46
+ * @slot footer - Content to place in the footer. Slot `esp-footer` directly
47
+ * to receive the page's surface-alignment custom-property contract. A wrapper
48
+ * can preserve landmark semantics but does not receive that direct contract.
47
49
  * @slot - The main page content. The main content region applies
48
50
  * `contain: inline-size` so child components cannot push the
49
51
  * content well wider than its grid column. In `narrow` mode,
@@ -65,7 +67,7 @@ type HeaderPosition = "normal" | "sticky" | "fixed";
65
67
  * </esp-menu>
66
68
  * <esp-header-button slot="buttons" icon="cog" aria-label="Settings"></esp-header-button>
67
69
  * </esp-header>
68
- * <div slot="footer" style="background-color: blue;">footer</div>
70
+ * <esp-footer slot="footer" brand-text="Espalier"></esp-footer>
69
71
  * <section style="overflow: hidden;">
70
72
  * <h2>Long content</h2>
71
73
  * <p populate-from="longParagraph"></p>
@@ -98,7 +100,7 @@ type HeaderPosition = "normal" | "sticky" | "fixed";
98
100
  * <div slot="header" style="background-color: red;">header</div>
99
101
  * <div slot="sidebar" style="background-color: green;">sidebar</div>
100
102
  * <div slot="right" style="background-color: purple;">right</div>
101
- * <div slot="footer" style="background-color: blue;">footer</div>
103
+ * <esp-footer slot="footer" brand-text="Espalier"></esp-footer>
102
104
  * <div style="background-color: black; overflow: hidden;">
103
105
  * content
104
106
  * </div>
@@ -162,7 +164,7 @@ type HeaderPosition = "normal" | "sticky" | "fixed";
162
164
  * <div slot="header" style="background-color: red;">header</div>
163
165
  * <div slot="sidebar" style="background-color: green;">sidebar</div>
164
166
  * <div slot="right" style="background-color: purple;">right</div>
165
- * <div slot="footer" style="background-color: blue;">footer</div>
167
+ * <esp-footer slot="footer" brand-text="Espalier"></esp-footer>
166
168
  * <div style="overflow: hidden;">
167
169
  * <h2>With background image</h2>
168
170
  * </div>
@@ -185,7 +187,7 @@ type HeaderPosition = "normal" | "sticky" | "fixed";
185
187
  * <div slot="header" style="background-color: red;">header</div>
186
188
  * <div slot="sidebar" style="background-color: green;">sidebar</div>
187
189
  * <div slot="right" style="background-color: purple;">right</div>
188
- * <div slot="footer" style="background-color: blue;">footer</div>
190
+ * <esp-footer slot="footer" brand-text="Espalier"></esp-footer>
189
191
  * <div style="background-color: black; overflow: hidden;">
190
192
  * content
191
193
  * </div>
@@ -202,6 +204,7 @@ type HeaderPosition = "normal" | "sticky" | "fixed";
202
204
  */
203
205
  export declare class EspalierPage extends EspalierElementBase {
204
206
  constructor();
207
+ connectedCallback(): void;
205
208
  /**
206
209
  * The layout mode of the page.
207
210
  *
@@ -1,5 +1,5 @@
1
- var d=function(h,e,s,o){var n=arguments.length,a=n<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,s):o,t;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")a=Reflect.decorate(h,e,s,o);else for(var r=h.length-1;r>=0;r--)(t=h[r])&&(a=(n<3?t(a):n>3?t(e,s,a):t(e,s))||a);return n>3&&a&&Object.defineProperty(e,s,a),a};import{css as f,html as m}from"lit";import{customElement as v,property as l}from"lit/decorators.js";import{classMap as y}from"lit/directives/class-map.js";import{createRef as c,ref as u}from"lit/directives/ref.js";import{EspalierElementBase as g}from"../shared/esp-element-base.js";import{BiDirectionalStickyController as p}from"./bi-directional-sticky-controller.js";import{getEspBus as w}from"../shared/bus-events.js";import"../toaster/esp-toaster.js";let i=class extends g{constructor(){super(),this.dialogZone=c(),this.flyoutSlot=c(),this.kind="wide",this.align="start",this.contained=!1,this.headerPosition="normal",this.fixedMenus=!1,new p(this,".esp-page-left > .sticky-wrapper"),new p(this,".esp-page-right > .sticky-wrapper"),new p(this,".esp-page-flyout > .sticky-wrapper"),this.addEventListener("flyout-state-changed",e=>this.syncFlyoutState(e))}syncFlyoutState(e){if(e&&e.target?.closest?.("esp-page")!==this)return;const s=t=>{const r=t.mode;return(typeof r=="string"?r:t.getAttribute("mode"))==="overlay"},o=t=>{const r=t.open;return typeof r=="boolean"?r:t.hasAttribute("open")},n=t=>t.anchor!=null,a=(this.flyoutSlot.value?.assignedElements()??[]).filter(t=>t.tagName==="ESP-FLYOUT");this.toggleAttribute("flyout-open",a.some(t=>o(t)&&!s(t))),this.toggleAttribute("flyout-overlay-open",a.some(t=>o(t)&&s(t))),this.toggleAttribute("flyout-anchored",a.some(t=>o(t)&&n(t)))}AddDialog(e){this.dialogZone.value?.appendChild(e)}firstUpdated(e){super.firstUpdated(e),this.syncFlyoutState()}updated(e){super.updated(e),(e.has("fixedMenus")||e.has("headerPosition"))&&w().publish("fixed-menus-changed",{fixed:this.fixedMenus||this.headerPosition==="fixed"})}render(){const e=this.fixedMenus||this.headerPosition==="fixed",s=!e&&this.headerPosition==="sticky";return m`
2
- <div part="wrapper" class="esp-page ${y({"fixed-menus":e,"fixed-header":e,"sticky-header":s})}">
1
+ var i=function(h,e,a,s){var d=arguments.length,o=d<3?e:s===null?s=Object.getOwnPropertyDescriptor(e,a):s,t;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(h,e,a,s);else for(var n=h.length-1;n>=0;n--)(t=h[n])&&(o=(d<3?t(o):d>3?t(e,a,o):t(e,a))||o);return d>3&&o&&Object.defineProperty(e,a,o),o};import{css as m,html as v,nothing as y}from"lit";import{customElement as w,property as l,state as b}from"lit/decorators.js";import{classMap as k}from"lit/directives/class-map.js";import{createRef as p,ref as c}from"lit/directives/ref.js";import{EspalierElementBase as g}from"../shared/esp-element-base.js";import{BiDirectionalStickyController as u}from"./bi-directional-sticky-controller.js";import{getEspBus as x}from"../shared/bus-events.js";import"../toaster/esp-toaster.js";const f='esp-footer, footer, [role~="contentinfo"]';let r=class extends g{constructor(){super(),this.dialogZone=p(),this.flyoutSlot=p(),this.footerSlot=p(),this.footerWrapperIsLandmark=!0,this.kind="wide",this.align="start",this.contained=!1,this.headerPosition="normal",this.fixedMenus=!1,new u(this,".esp-page-left > .sticky-wrapper"),new u(this,".esp-page-right > .sticky-wrapper"),new u(this,".esp-page-flyout > .sticky-wrapper"),this.addEventListener("flyout-state-changed",e=>this.syncFlyoutState(e))}connectedCallback(){const e=Array.from(this.children).filter(a=>a.getAttribute("slot")==="footer");this.footerWrapperIsLandmark=!e.some(a=>this.footerElementProvidesLandmark(a)),super.connectedCallback()}syncFlyoutState(e){if(e&&e.target?.closest?.("esp-page")!==this)return;const a=t=>{const n=t.mode;return(typeof n=="string"?n:t.getAttribute("mode"))==="overlay"},s=t=>{const n=t.open;return typeof n=="boolean"?n:t.hasAttribute("open")},d=t=>t.anchor!=null,o=(this.flyoutSlot.value?.assignedElements()??[]).filter(t=>t.tagName==="ESP-FLYOUT");this.toggleAttribute("flyout-open",o.some(t=>s(t)&&!a(t))),this.toggleAttribute("flyout-overlay-open",o.some(t=>s(t)&&a(t))),this.toggleAttribute("flyout-anchored",o.some(t=>s(t)&&d(t)))}footerElementProvidesLandmark(e){return e.matches(f)||e.querySelector(f)!==null}syncFooterLandmark(){const a=(this.footerSlot.value?.assignedElements({flatten:!0})??[]).some(s=>this.footerElementProvidesLandmark(s));this.footerWrapperIsLandmark=!a}AddDialog(e){this.dialogZone.value?.appendChild(e)}firstUpdated(e){super.firstUpdated(e),this.syncFlyoutState()}updated(e){super.updated(e),(e.has("fixedMenus")||e.has("headerPosition"))&&x().publish("fixed-menus-changed",{fixed:this.fixedMenus||this.headerPosition==="fixed"})}render(){const e=this.fixedMenus||this.headerPosition==="fixed",a=!e&&this.headerPosition==="sticky";return v`
2
+ <div part="wrapper" class="esp-page ${k({"fixed-menus":e,"fixed-header":e,"sticky-header":a})}">
3
3
  <div part="canvas" class="esp-page-canvas esp-page-canvas--left" aria-hidden="true"></div>
4
4
  <div part="canvas" class="esp-page-canvas esp-page-canvas--right" aria-hidden="true"></div>
5
5
  <div part="surface" class="esp-page-surface" aria-hidden="true"></div>
@@ -23,18 +23,18 @@ var d=function(h,e,s,o){var n=arguments.length,a=n<3?e:o===null?o=Object.getOwnP
23
23
  <div class="sticky-wrapper">
24
24
  <slot
25
25
  name="flyout"
26
- ${u(this.flyoutSlot)}
26
+ ${c(this.flyoutSlot)}
27
27
  @slotchange=${()=>this.syncFlyoutState()}
28
28
  ></slot>
29
29
  </div>
30
30
  </div>
31
- <footer>
32
- <slot name="footer"></slot>
33
- </footer>
34
- <div id="dialog-drop-zone" ${u(this.dialogZone)}></div>
31
+ <div class="esp-page-footer" role=${this.footerWrapperIsLandmark?"contentinfo":y}>
32
+ <slot name="footer" ${c(this.footerSlot)} @slotchange=${this.syncFooterLandmark}></slot>
33
+ </div>
34
+ <div id="dialog-drop-zone" ${c(this.dialogZone)}></div>
35
35
  <esp-toaster></esp-toaster>
36
36
  </div>
37
- `}};i.styles=[...g.styles,f`
37
+ `}};r.styles=[...g.styles,m`
38
38
  :host {
39
39
  --_esp-page-resolved-max-width: var(--esp-page-max-width, 1536px);
40
40
 
@@ -130,8 +130,26 @@ var d=function(h,e,s,o){var n=arguments.length,a=n<3?e:o===null?o=Object.getOwnP
130
130
  }
131
131
 
132
132
 
133
+ slot[name="footer"]::slotted(esp-footer) {
134
+ --esp-footer-content-max-width: var(--_esp-page-resolved-max-width);
135
+ --esp-footer-content-lead: 0;
136
+ }
137
+
138
+ :host([align="center"]) slot[name="footer"]::slotted(esp-footer) {
139
+ --esp-footer-content-lead: 0.5;
140
+ }
141
+
142
+ :host([align="end"]) slot[name="footer"]::slotted(esp-footer) {
143
+ --esp-footer-content-lead: 1;
144
+ }
145
+
146
+ :host([kind="full"]) slot[name="footer"]::slotted(esp-footer) {
147
+ --esp-footer-content-max-width: 100%;
148
+ }
149
+
150
+
133
151
  :host([contained]) .esp-page > div.esp-page-top,
134
- :host([contained]) .esp-page > footer {
152
+ :host([contained]) .esp-page > div.esp-page-footer {
135
153
  grid-column: surface;
136
154
  }
137
155
 
@@ -141,6 +159,10 @@ var d=function(h,e,s,o){var n=arguments.length,a=n<3?e:o===null?o=Object.getOwnP
141
159
  --esp-header-shadow: none;
142
160
  }
143
161
 
162
+ :host([contained]) slot[name="footer"]::slotted(esp-footer) {
163
+ --esp-footer-content-max-width: 100%;
164
+ }
165
+
144
166
  :host([kind="narrow"]) .esp-page > div.esp-page-main {
145
167
 
146
168
  > ::slotted(*) {
@@ -297,7 +319,7 @@ var d=function(h,e,s,o){var n=arguments.length,a=n<3?e:o===null?o=Object.getOwnP
297
319
  top: 0;
298
320
  }
299
321
 
300
- > footer {
322
+ > div.esp-page-footer {
301
323
  grid-column: full;
302
324
  grid-row: footer;
303
325
  z-index: 10;
@@ -372,4 +394,4 @@ var d=function(h,e,s,o){var n=arguments.length,a=n<3?e:o===null?o=Object.getOwnP
372
394
  transition: none;
373
395
  }
374
396
  }
375
- `],d([l({reflect:!0})],i.prototype,"kind",void 0),d([l({reflect:!0})],i.prototype,"align",void 0),d([l({type:Boolean,reflect:!0})],i.prototype,"contained",void 0),d([l({attribute:"header-position",reflect:!0})],i.prototype,"headerPosition",void 0),d([l({attribute:"fixed-menus",type:Boolean,reflect:!0})],i.prototype,"fixedMenus",void 0),i=d([v("esp-page")],i);export{i as EspalierPage};
397
+ `],i([b()],r.prototype,"footerWrapperIsLandmark",void 0),i([l({reflect:!0})],r.prototype,"kind",void 0),i([l({reflect:!0})],r.prototype,"align",void 0),i([l({type:Boolean,reflect:!0})],r.prototype,"contained",void 0),i([l({attribute:"header-position",reflect:!0})],r.prototype,"headerPosition",void 0),i([l({attribute:"fixed-menus",type:Boolean,reflect:!0})],r.prototype,"fixedMenus",void 0),r=i([w("esp-page")],r);export{r as EspalierPage};
@@ -0,0 +1,4 @@
1
+ import{html as r,nothing as t}from"lit";function u({scheme:o,brandLogo:n,brandColor:s,lightBrandLogo:e,darkBrandLogo:c,lightBrandColor:a,darkBrandColor:l}){return{brandLogo:(o==="dark"?c:e)||n,brandColor:(o==="dark"?l:a)||s}}function f({brandLogo:o,brandText:n,brandHref:s,brandAlt:e}){if(!o&&!n)return t;const a=r`
2
+ ${o?r`<img class="brand-logo" src=${o} alt=${e||(n?"":"Site logo")} />`:t}
3
+ ${n?r`<span class="brand-text">${n}</span>`:t}
4
+ `;return s?r`<a class="configured-brand" href=${s}>${a}</a>`:r`<span class="configured-brand">${a}</span>`}export{f as renderConfiguredBrand,u as resolveConfiguredBrand};
@@ -30,6 +30,7 @@ export { type FlyoutConfig, type FlyoutCloseReason } from "./flyout-events.js";
30
30
  export { type PickerItem } from "../pickers/esp-picker-item.js";
31
31
  export { type EspalierUploadImage } from "../image-upload/image-helpers.js";
32
32
  export { type FontPickerValueChangedDetail, type GoogleFont, type WebSafeFont, } from "../font-picker/esp-font-picker.js";
33
+ export { type EspThemeToggleEventDetail } from "../header/esp-header.js";
33
34
  import type { EspalierDetails } from "../details/esp-details.js";
34
35
  import type { FlyoutCloseReason } from "./flyout-events.js";
35
36
  import type { ValidityChangedDetail } from "./validation.js";
@@ -39,6 +40,7 @@ import type { PickerItem } from "../pickers/esp-picker-item.js";
39
40
  import type { EspalierUploadImage, UploadEventDetail } from "../image-upload/image-helpers.js";
40
41
  export type { UploadEventDetail } from "../image-upload/image-helpers.js";
41
42
  import type { FontPickerValueChangedDetail } from "../font-picker/esp-font-picker.js";
43
+ import type { EspThemeToggleEventDetail } from "../header/esp-header.js";
42
44
  /**
43
45
  * Canonical event name strings for every CustomEvent in the library.
44
46
  *
@@ -65,6 +67,7 @@ export declare const ESP_EVENTS: {
65
67
  readonly ESP_ACCORDION_CHANGE: "esp-accordion-change";
66
68
  readonly DRAWER_OPENED: "drawer-opened";
67
69
  readonly DRAWER_CLOSED: "drawer-closed";
70
+ readonly ESP_THEME_TOGGLE: "esp-theme-toggle";
68
71
  readonly FLYOUT_OPENED: "flyout-opened";
69
72
  readonly FLYOUT_CLOSED: "flyout-closed";
70
73
  readonly FLYOUT_STATE_CHANGED: "flyout-state-changed";
@@ -284,6 +287,10 @@ export interface EspalierFlyoutEventMap {
284
287
  export interface EspalierHeaderButtonEventMap {
285
288
  [ESP_EVENTS.CLICKED]: CustomEvent<Record<string, never>>;
286
289
  }
290
+ /** Events fired by `<esp-header>`. */
291
+ export interface EspalierHeaderEventMap {
292
+ [ESP_EVENTS.ESP_THEME_TOGGLE]: CustomEvent<EspThemeToggleEventDetail>;
293
+ }
287
294
  /** Events fired by `<esp-grid>`. */
288
295
  export interface EspalierGridEventMap {
289
296
  [ESP_EVENTS.GRID_EVENT]: CustomEvent<GridClickedEvent>;
@@ -1 +1 @@
1
- import{VALIDITY_CHANGED_EVENT as D}from"./validation.js";const e={VALUE_CHANGED:"value-changed",VALIDITY_CHANGED:"validity-changed",CLICKED:"clicked",ESP_SUBMIT:"esp-submit",ESP_SUBMIT_RESPONSE:"esp-submit-response",ESP_SUBMIT_ERROR:"esp-submit-error",ESP_TAB_CHANGED:"esp-tab-changed",ESP_TAB_UPDATED:"esp-tab-updated",ESP_TOGGLE:"esp-toggle",ESP_ACCORDION_CHANGE:"esp-accordion-change",DRAWER_OPENED:"drawer-opened",DRAWER_CLOSED:"drawer-closed",FLYOUT_OPENED:"flyout-opened",FLYOUT_CLOSED:"flyout-closed",FLYOUT_STATE_CHANGED:"flyout-state-changed",POPOVER_OPENED:"popover-opened",POPOVER_CLOSED:"popover-closed",GRID_EVENT:"grid-event",GRID_LOAD_START:"esp-grid-load-start",GRID_LOAD_SUCCESS:"esp-grid-load-success",GRID_LOAD_ERROR:"esp-grid-load-error",GRID_ITEMS_CHANGED:"esp-grid-items-changed",DESTROY:"destroy",FILE_SELECTED:"file-selected",FILE_REMOVED:"file-removed",FILES_SELECTED:"files-selected",FILES_REJECTED:"files-rejected",UPLOAD_RETRY:"upload-retry",RETRY_UPLOAD:"retry-upload",IMAGES_REORDERED:"images-reordered",SEARCH_REQUESTED:"search-requested",RESULT_SELECTED:"result-selected",SEARCH_CLOSED:"search-closed",SELECTION_CHANGED:"selection-changed",CLOSE_MENU:"close-menu",REMOVE_IMAGE:"remove-image"};export{e as ESP_EVENTS,D as VALIDITY_CHANGED_EVENT};
1
+ import{VALIDITY_CHANGED_EVENT as s}from"./validation.js";const e={VALUE_CHANGED:"value-changed",VALIDITY_CHANGED:"validity-changed",CLICKED:"clicked",ESP_SUBMIT:"esp-submit",ESP_SUBMIT_RESPONSE:"esp-submit-response",ESP_SUBMIT_ERROR:"esp-submit-error",ESP_TAB_CHANGED:"esp-tab-changed",ESP_TAB_UPDATED:"esp-tab-updated",ESP_TOGGLE:"esp-toggle",ESP_ACCORDION_CHANGE:"esp-accordion-change",DRAWER_OPENED:"drawer-opened",DRAWER_CLOSED:"drawer-closed",ESP_THEME_TOGGLE:"esp-theme-toggle",FLYOUT_OPENED:"flyout-opened",FLYOUT_CLOSED:"flyout-closed",FLYOUT_STATE_CHANGED:"flyout-state-changed",POPOVER_OPENED:"popover-opened",POPOVER_CLOSED:"popover-closed",GRID_EVENT:"grid-event",GRID_LOAD_START:"esp-grid-load-start",GRID_LOAD_SUCCESS:"esp-grid-load-success",GRID_LOAD_ERROR:"esp-grid-load-error",GRID_ITEMS_CHANGED:"esp-grid-items-changed",DESTROY:"destroy",FILE_SELECTED:"file-selected",FILE_REMOVED:"file-removed",FILES_SELECTED:"files-selected",FILES_REJECTED:"files-rejected",UPLOAD_RETRY:"upload-retry",RETRY_UPLOAD:"retry-upload",IMAGES_REORDERED:"images-reordered",SEARCH_REQUESTED:"search-requested",RESULT_SELECTED:"result-selected",SEARCH_CLOSED:"search-closed",SELECTION_CHANGED:"selection-changed",CLOSE_MENU:"close-menu",REMOVE_IMAGE:"remove-image"};export{e as ESP_EVENTS,s as VALIDITY_CHANGED_EVENT};
@@ -0,0 +1 @@
1
+ function o(t){return t?.assignedNodes({flatten:!0}).some(e=>e.nodeType===Node.ELEMENT_NODE||e.nodeType===Node.TEXT_NODE&&!!e.textContent?.trim())??!1}export{o as slotHasContent};