@taprootio/espalier 2.10.0 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,12 +2,14 @@ import { type PropertyValues } from "lit";
2
2
  import { EspalierElementBase } from "../shared/esp-element-base.js";
3
3
  import { type FlyoutCloseReason } from "../shared/flyout-events.js";
4
4
  /**
5
- * A transient panel for help, more-info, and preview content that
6
- * claims designed spare width before ever covering the page.
5
+ * A transient panel for help and more-info content that claims designed spare
6
+ * width before ever covering the page.
7
7
  *
8
8
  * Place one `esp-flyout` in an `esp-page`'s `flyout` slot. The panel
9
- * lives on the canvas, outside the content surface. The page decides
10
- * where it goes, from widest viewport to narrowest:
9
+ * lives on the canvas after any persistent preview, outside the content
10
+ * surface. It negotiates between `--esp-page-flyout-min-width` and
11
+ * `--esp-page-flyout-max-width`; preview receives flexible room first. The page
12
+ * decides where help goes, from widest viewport to narrowest:
11
13
  *
12
14
  * 1. **Gutter** — the panel occupies the right canvas gutter. When the
13
15
  * gutter already has room, it claims existing spare canvas and the
@@ -18,19 +20,25 @@ import { type FlyoutCloseReason } from "../shared/flyout-events.js";
18
20
  * 3. **Docked sidebar** — once the gutter is gone, the panel competes
19
21
  * for width with the main well; content narrows but is never
20
22
  * covered.
21
- * 4. **Overlay drawer** — below the mobile threshold (`50em`, the
22
- * same one the `esp-menu` drawer uses) the panel becomes a fixed
23
+ * 4. **Overlay drawer** — when the complete sidebar + main + help
24
+ * minimums do not fit, or below the mobile threshold (`50em`, the
25
+ * same one the `esp-menu` drawer uses), the panel becomes a fixed
23
26
  * drawer over a vellum backdrop. Set `mode="overlay"` to get this
24
27
  * presentation at every width.
25
28
  *
26
29
  * The panel is styled as a tear-off piece: a dotted perforation on
27
30
  * its leading edge, rounded trailing corners, and no shadow — all
28
31
  * overridable through the `--esp-flyout-*` tokens below.
32
+ * An anchored panel shown with preview keeps its caret at the main/preview
33
+ * edge and receives a non-interactive dotted bridge across preview from the
34
+ * page. A short, thick terminus on the preview/help seam completes that
35
+ * connection; no consumer positioning is required.
29
36
  *
30
37
  * A11y follows the presentation. In the in-grid modes (1–3) the
31
38
  * flyout is a non-modal `complementary` landmark named by its
32
- * `heading`, and opening it never steals focus. In the overlay-drawer
33
- * mode (4) it is a true modal: `role="dialog"` + `aria-modal`, the
39
+ * `heading`, opening it never steals focus, and boundary scrolling chains
40
+ * back to the main document. In the overlay-drawer mode (4) it is a true
41
+ * modal: `role="dialog"` + `aria-modal`, the
34
42
  * background goes inert, scroll is locked, focus moves into the drawer
35
43
  * and is trapped, and focus is restored on close. `Escape` closes it
36
44
  * in every mode.
@@ -38,7 +46,7 @@ import { type FlyoutCloseReason } from "../shared/flyout-events.js";
38
46
  * ```html
39
47
  * <style>
40
48
  * esp-page.flyout-demo {
41
- * --esp-page-max-width: 420px;
49
+ * --esp-page-main-max-width: 420px;
42
50
  * --esp-page-canvas-background: var(--esp-color-layer-1);
43
51
  * &::part(wrapper) {
44
52
  * min-height: 320px;
@@ -72,7 +80,7 @@ import { type FlyoutCloseReason } from "../shared/flyout-events.js";
72
80
  * ```html
73
81
  * <style>
74
82
  * esp-page.flyout-match-demo {
75
- * --esp-page-max-width: 420px;
83
+ * --esp-page-main-max-width: 420px;
76
84
  * &::part(wrapper) {
77
85
  * min-height: 320px;
78
86
  * height: 320px;
@@ -317,8 +325,8 @@ export declare class EspalierFlyout extends EspalierElementBase {
317
325
  * Placement behavior.
318
326
  *
319
327
  * - `"auto"` (default) — the page's placement ladder: gutter,
320
- * docked sidebar, then overlay drawer below the `50em` viewport
321
- * threshold.
328
+ * docked sidebar, then overlay drawer when the complete in-grid
329
+ * minimums do not fit or below the `50em` viewport threshold.
322
330
  * - `"overlay"` — always the fixed overlay drawer, at any width.
323
331
  * The page never reserves a grid track for an overlay-mode
324
332
  * flyout.
@@ -1,4 +1,4 @@
1
- var h=function(d,e,t,i){var o=arguments.length,s=o<3?e:i===null?i=Object.getOwnPropertyDescriptor(e,t):i,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(d,e,t,i);else for(var r=d.length-1;r>=0;r--)(a=d[r])&&(s=(o<3?a(s):o>3?a(e,t,s):a(e,t))||s);return o>3&&s&&Object.defineProperty(e,t,s),s};import{css as p,html as w,nothing as S}from"lit";import{customElement as F,property as l}from"lit/decorators.js";import{classMap as L}from"lit/directives/class-map.js";import{createRef as M,ref as O}from"lit/directives/ref.js";import{EspalierElementBase as A}from"../shared/esp-element-base.js";import{getEspBus as f}from"../shared/bus-events.js";import{FLYOUT_FULL_HEIGHT_REQUEST_EVENT as k,markFlyoutRequestServiced as _}from"../shared/flyout-events.js";import{OverlayController as G}from"../shared/overlay-controller.js";import{cancelSVG as B}from"../shared/svgs/cancel.js";import{traverseToClosest as y}from"../shared/utilities.js";const H="(max-width: 50em)",q="Flyout",R=p`
1
+ var l=function(d,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(d,e,t,r);else for(var i=d.length-1;i>=0;i--)(n=d[i])&&(s=(o<3?n(s):o>3?n(e,t,s):n(e,t))||s);return o>3&&s&&Object.defineProperty(e,t,s),s};import{css as p,html as w,nothing as T}from"lit";import{customElement as _,property as h}from"lit/decorators.js";import{classMap as O}from"lit/directives/class-map.js";import{createRef as F,ref as L}from"lit/directives/ref.js";import{EspalierElementBase as k}from"../shared/esp-element-base.js";import{getEspBus as f}from"../shared/bus-events.js";import{FLYOUT_FULL_HEIGHT_REQUEST_EVENT as A,markFlyoutRequestServiced as M}from"../shared/flyout-events.js";import{OverlayController as q}from"../shared/overlay-controller.js";import{cancelSVG as G}from"../shared/svgs/cancel.js";import{traverseToClosest as v}from"../shared/utilities.js";const B="(max-width: 50em)",H="Flyout",R=p`
2
2
  position: fixed;
3
3
  inset: 0;
4
4
  margin-block-start: 0;
@@ -13,13 +13,13 @@ var h=function(d,e,t,i){var o=arguments.length,s=o<3?e:i===null?i=Object.getOwnP
13
13
  inset: 0;
14
14
  background-color: var(--esp-vellum-background, var(--esp-color-layer-3));
15
15
  opacity: var(--esp-vellum-opacity, 0.85);
16
- `,P=p`
16
+ `,z=p`
17
17
  position: absolute;
18
18
  inset-block: 0;
19
19
  inset-inline-end: 0;
20
20
  block-size: auto;
21
21
  max-block-size: none;
22
- width: min(var(--esp-page-flyout-width, 20rem), 85vw);
22
+ width: min(var(--esp-page-flyout-width, var(--esp-page-flyout-max-width, 30rem)), 85vw);
23
23
  overflow-y: auto;
24
24
 
25
25
  border-start-end-radius: 0;
@@ -31,25 +31,26 @@ var h=function(d,e,t,i){var o=arguments.length,s=o<3?e:i===null?i=Object.getOwnP
31
31
  @starting-style {
32
32
  translate: 100% 0;
33
33
  }
34
- `;let n=class extends A{constructor(){super(...arguments),this.open=!1,this.heading="",this.mode="auto",this.fullHeight=!1,this.matchSurface=!1,this.standalone=!1,this.scope="outermost",this.lastGeneratedAriaLabel=null,this.boundKeydown=e=>this.handleKeydown(e),this.boundShowRequest=e=>this.handleShowRequest(e),this.boundCloseRequest=()=>this.close(),this.boundOverlayMediaChange=()=>{this.syncOverlayModal(),this.syncAnchorTracking(),this.syncAnchorGeometry()},this.boundAnchorViewportChange=()=>this.scheduleAnchorGeometrySync(),this.boundFullHeightRequest=e=>{e.stopPropagation(),this.fullHeight=!0},this.anchorPositionRaf=0,this.trackingAnchorPosition=!1,this.busSubscribed=!1,this.panelRef=M(),this.overlay=new G({host:this,getFocusTrapContainer:()=>this.panelRef.value??null,getFocusFallback:()=>this.panelRef.value??null,promote:!1}),this.overlayActive=!1,this.baseRole="complementary"}get effectiveOverlay(){return this.mode==="overlay"||(this.overlayMediaQuery?.matches??!1)}connectedCallback(){super.connectedCallback(),this.hasAttribute("role")||this.setAttribute("role","complementary"),this.baseRole=this.getAttribute("role")??"complementary",!this.overlayMediaQuery&&typeof window<"u"&&"matchMedia"in window&&(this.overlayMediaQuery=window.matchMedia(H)),this.overlayMediaQuery?.addEventListener("change",this.boundOverlayMediaChange),this.syncBusSubscription(),document.addEventListener("keydown",this.boundKeydown),this.addEventListener(k,this.boundFullHeightRequest),this.syncOverlayModal(),this.syncAnchorTracking(),this.syncAnchorGeometry()}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeBus(),this.overlayMediaQuery?.removeEventListener("change",this.boundOverlayMediaChange),document.removeEventListener("keydown",this.boundKeydown),this.removeEventListener(k,this.boundFullHeightRequest),this.stopAnchorTracking(),this.overlayActive&&(this.overlayActive=!1,this.setAttribute("role",this.baseRole),this.removeAttribute("aria-modal"),this.updateGeneratedAriaLabel()),this.overlayReturnFocusTo=void 0}syncBusSubscription(){if(this.standalone||!this.isConnected){this.unsubscribeBus();return}this.busSubscribed||(f().subscribe("show-flyout",this.boundShowRequest),f().subscribe("close-flyout",this.boundCloseRequest),this.busSubscribed=!0)}unsubscribeBus(){this.busSubscribed&&(f().unsubscribe("show-flyout",this.boundShowRequest),f().unsubscribe("close-flyout",this.boundCloseRequest),this.busSubscribed=!1)}show(){this.open||(this.open=!0,this.dispatchEvent(new CustomEvent("flyout-opened",{detail:{},bubbles:!0,composed:!0})))}close(e="programmatic"){if(this.open){if(this.open=!1,this.overlayActive)this.overlayReturnFocusTo=this.returnFocusTo;else{const t=this.focusIsInside();this.overlay.close(),t&&this.returnFocusTo?.focus()}this.returnFocusTo=void 0,this.dispatchEvent(new CustomEvent("flyout-closed",{detail:{reason:e},bubbles:!0,composed:!0}))}}toggle(){this.open?this.close():this.show()}handleShowRequest(e){this.shouldHandleShowRequest(e)&&(_(e),e.heading!==void 0&&(this.heading=e.heading),e.content!==void 0&&this.replaceChildren(typeof e.content=="string"?document.createTextNode(e.content):e.content),this.anchor=e.anchor,this.fullHeight=e.fullHeight??!1,this.returnFocusTo=e.returnFocusTo,this.show())}shouldHandleShowRequest(e){const t=y(this,"esp-page"),i=e.anchor??e.returnFocusTo;if(!i){if(!t)return!0;const r=this.getPageChain(t);return this.scope==="outermost"&&r[r.length-1]===t}const o=this.getPageChain(i);if(o.length===0)return t===null;const s=o.find(r=>this.hasNearestScopeFlyout(r)),a=s??o[o.length-1];return t!==a?!1:s?this.scope==="nearest":this.scope==="outermost"}getPageChain(e){const t=[];let i=e;for(;i;){const o=y(i,"esp-page");if(!o||t.includes(o))break;t.push(o),i=this.composedParent(o)}return t}hasNearestScopeFlyout(e){return Array.from(e.querySelectorAll("esp-flyout")).some(t=>!t.standalone&&t.scope==="nearest"&&y(t,"esp-page")===e)}handleKeydown(e){if(this.open){if(this.overlayActive&&e.key==="Tab"){this.overlay.trapFocus(e);return}e.key!=="Escape"||e.defaultPrevented||(e.preventDefault(),this.close("escape"))}}focusIsInside(){const e=document.activeElement;return e&&this.contains(e)?!0:this.shadowRoot?.activeElement!=null}updated(e){super.updated(e),e.has("standalone")&&this.syncBusSubscription(),e.has("heading")&&this.updateGeneratedAriaLabel(),(e.has("anchor")||e.has("fullHeight")||e.has("open")||e.has("mode"))&&(this.syncAnchorTracking(),this.syncAnchorGeometry()),(e.has("open")||e.has("mode"))&&this.syncOverlayModal(),(e.has("open")||e.has("mode")||e.has("anchor"))&&this.dispatchEvent(new CustomEvent("flyout-state-changed",{detail:{},bubbles:!0,composed:!0}))}syncAnchorGeometry(){const e=y(this,"esp-page"),t=this.anchor?this.getPageChain(this.anchor):[],i=e?.shadowRoot?.querySelector(".esp-page-main"),o=this.panelRef.value;if(!this.open||this.effectiveOverlay||!this.anchor||!e||!t.includes(e)||!i||!o){this.clearAnchorGeometry();return}const s=this.anchor.getBoundingClientRect(),a=Math.max(0,s.top-i.getBoundingClientRect().top),r=this.getVisibleBlockBounds(),u=Math.max(0,r.bottom-r.top),c=Number.isFinite(s.height)?s.height:0;this.setGeometryProperty("--_esp-flyout-anchor-offset",`${a}px`),this.setGeometryProperty("--_esp-flyout-max-block-size",`${u}px`),this.setGeometryProperty("--_esp-flyout-anchor-block-size",`${c}px`);const v=o.getBoundingClientRect().height||u,b=Math.max(0,s.top+v-r.bottom),C=Math.max(0,v-c),g=this.fullHeight?b:Math.min(b,C);this.setGeometryProperty("--_esp-flyout-viewport-shift",`${g}px`);const z=s.top-g,m=8,E=s.top+c/2,T=Math.min(Math.max(m,v-m),Math.max(m,E-z));this.setGeometryProperty("--_esp-flyout-anchor-marker-offset",`${T}px`)}getVisibleBlockBounds(){const e=window.visualViewport;let t=e?.offsetTop??0,i=t+(e?.height??window.innerHeight);for(let o=this.composedParent(this);o;o=this.composedParent(o)){const s=getComputedStyle(o).overflowY;if(s!=="auto"&&s!=="scroll")continue;const a=o.getBoundingClientRect(),r=o instanceof HTMLElement?o.clientTop:0,u=o instanceof HTMLElement?o.clientHeight:a.height;if(u<=0)continue;const c=a.top+r;t=Math.max(t,c),i=Math.min(i,c+u)}return{top:t,bottom:Math.max(t,i)}}composedParent(e){if(e.parentElement)return e.parentElement;const t=e.getRootNode();return t instanceof ShadowRoot?t.host:null}setGeometryProperty(e,t){this.style.getPropertyValue(e)!==t&&this.style.setProperty(e,t)}clearAnchorGeometry(){this.style.removeProperty("--_esp-flyout-anchor-offset"),this.style.removeProperty("--_esp-flyout-viewport-shift"),this.style.removeProperty("--_esp-flyout-max-block-size"),this.style.removeProperty("--_esp-flyout-anchor-block-size"),this.style.removeProperty("--_esp-flyout-anchor-marker-offset")}scheduleAnchorGeometrySync(){!this.isConnected||this.anchorPositionRaf||(this.anchorPositionRaf=requestAnimationFrame(()=>{this.anchorPositionRaf=0,this.syncAnchorGeometry()}))}syncAnchorTracking(){if(!(this.isConnected&&this.open&&!!this.anchor&&!this.effectiveOverlay)){this.stopAnchorTracking();return}this.trackingAnchorPosition||(this.trackingAnchorPosition=!0,window.addEventListener("scroll",this.boundAnchorViewportChange,{capture:!0,passive:!0}),window.addEventListener("resize",this.boundAnchorViewportChange,{passive:!0}));const t=this.panelRef.value;t&&t!==this.observedAnchorPanel&&typeof ResizeObserver<"u"&&(this.anchorResizeObserver??=new ResizeObserver(this.boundAnchorViewportChange),this.anchorResizeObserver.disconnect(),this.anchorResizeObserver.observe(t),this.observedAnchorPanel=t)}stopAnchorTracking(){this.trackingAnchorPosition&&(window.removeEventListener("scroll",this.boundAnchorViewportChange,{capture:!0}),window.removeEventListener("resize",this.boundAnchorViewportChange),this.trackingAnchorPosition=!1),this.anchorPositionRaf&&(cancelAnimationFrame(this.anchorPositionRaf),this.anchorPositionRaf=0),this.anchorResizeObserver?.disconnect(),this.observedAnchorPanel=void 0}syncOverlayModal(){const e=this.isConnected&&this.open&&this.effectiveOverlay;if(e===this.overlayActive){!e&&!this.open&&this.overlay.close();return}e?(this.overlayActive=!0,this.setAttribute("role","dialog"),this.setAttribute("aria-modal","true"),this.updateGeneratedAriaLabel(),this.overlay.open(),this.updateComplete.then(()=>{this.overlayActive&&this.overlay.moveFocusInto()})):(this.overlayActive=!1,this.overlay.close(),this.overlayReturnFocusTo&&(this.overlayReturnFocusTo.focus(),this.overlayReturnFocusTo=void 0),this.setAttribute("role",this.baseRole),this.removeAttribute("aria-modal"),this.updateGeneratedAriaLabel())}updateGeneratedAriaLabel(){const e=this.getAttribute("aria-label");if(e!==null&&e!==this.lastGeneratedAriaLabel)return;const t=this.heading||(this.overlayActive?q:"");t?(this.setAttribute("aria-label",t),this.lastGeneratedAriaLabel=t):(this.removeAttribute("aria-label"),this.lastGeneratedAriaLabel=null)}render(){return w`
34
+ `;let a=class extends k{constructor(){super(...arguments),this.open=!1,this.heading="",this.mode="auto",this.pageOverlayRequested=!1,this.fullHeight=!1,this.matchSurface=!1,this.standalone=!1,this.scope="outermost",this.lastGeneratedAriaLabel=null,this.boundKeydown=e=>this.handleKeydown(e),this.boundShowRequest=e=>this.handleShowRequest(e),this.boundCloseRequest=()=>this.close(),this.boundOverlayMediaChange=()=>{this.syncOverlayModal(),this.syncAnchorTracking(),this.syncAnchorGeometry(),this.dispatchEvent(new CustomEvent("flyout-state-changed",{detail:{},bubbles:!0,composed:!0}))},this.boundAnchorViewportChange=()=>this.scheduleAnchorGeometrySync(),this.boundFullHeightRequest=e=>{e.stopPropagation(),this.fullHeight=!0},this.anchorPositionRaf=0,this.trackingAnchorPosition=!1,this.busSubscribed=!1,this.panelRef=F(),this.overlay=new q({host:this,getFocusTrapContainer:()=>this.panelRef.value??null,getFocusFallback:()=>this.panelRef.value??null,promote:!1}),this.overlayActive=!1,this.baseRole="complementary"}get effectiveOverlay(){return this.mode==="overlay"||this.pageOverlayRequested||(this.overlayMediaQuery?.matches??!1)}connectedCallback(){super.connectedCallback(),this.hasAttribute("role")||this.setAttribute("role","complementary"),this.baseRole=this.getAttribute("role")??"complementary",!this.overlayMediaQuery&&typeof window<"u"&&"matchMedia"in window&&(this.overlayMediaQuery=window.matchMedia(B)),this.overlayMediaQuery?.addEventListener("change",this.boundOverlayMediaChange),this.syncBusSubscription(),document.addEventListener("keydown",this.boundKeydown),this.addEventListener(A,this.boundFullHeightRequest),this.syncOverlayModal(),this.syncAnchorTracking(),this.syncAnchorGeometry()}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeBus(),this.overlayMediaQuery?.removeEventListener("change",this.boundOverlayMediaChange),document.removeEventListener("keydown",this.boundKeydown),this.removeEventListener(A,this.boundFullHeightRequest),this.stopAnchorTracking(),this.overlayActive&&(this.overlayActive=!1,this.setAttribute("role",this.baseRole),this.removeAttribute("aria-modal"),this.updateGeneratedAriaLabel()),this.overlayReturnFocusTo=void 0}syncBusSubscription(){if(this.standalone||!this.isConnected){this.unsubscribeBus();return}this.busSubscribed||(f().subscribe("show-flyout",this.boundShowRequest),f().subscribe("close-flyout",this.boundCloseRequest),this.busSubscribed=!0)}unsubscribeBus(){this.busSubscribed&&(f().unsubscribe("show-flyout",this.boundShowRequest),f().unsubscribe("close-flyout",this.boundCloseRequest),this.busSubscribed=!1)}show(){this.open||(this.open=!0,this.dispatchEvent(new CustomEvent("flyout-opened",{detail:{},bubbles:!0,composed:!0})))}close(e="programmatic"){if(this.open){if(this.open=!1,this.overlayActive)this.overlayReturnFocusTo=this.returnFocusTo;else{const t=this.focusIsInside();this.overlay.close(),t&&this.returnFocusTo?.focus()}this.returnFocusTo=void 0,this.dispatchEvent(new CustomEvent("flyout-closed",{detail:{reason:e},bubbles:!0,composed:!0}))}}toggle(){this.open?this.close():this.show()}handleShowRequest(e){this.shouldHandleShowRequest(e)&&(M(e),e.heading!==void 0&&(this.heading=e.heading),e.content!==void 0&&this.replaceChildren(typeof e.content=="string"?document.createTextNode(e.content):e.content),this.anchor=e.anchor,this.fullHeight=e.fullHeight??!1,this.returnFocusTo=e.returnFocusTo,this.show())}shouldHandleShowRequest(e){const t=v(this,"esp-page"),r=e.anchor??e.returnFocusTo;if(!r){if(!t)return!0;const i=this.getPageChain(t);return this.scope==="outermost"&&i[i.length-1]===t}const o=this.getPageChain(r);if(o.length===0)return t===null;const s=o.find(i=>this.hasNearestScopeFlyout(i)),n=s??o[o.length-1];return t!==n?!1:s?this.scope==="nearest":this.scope==="outermost"}getPageChain(e){const t=[];let r=e;for(;r;){const o=v(r,"esp-page");if(!o||t.includes(o))break;t.push(o),r=this.composedParent(o)}return t}hasNearestScopeFlyout(e){return Array.from(e.querySelectorAll("esp-flyout")).some(t=>!t.standalone&&t.scope==="nearest"&&v(t,"esp-page")===e)}handleKeydown(e){if(this.open){if(this.overlayActive&&e.key==="Tab"){this.overlay.trapFocus(e);return}e.key!=="Escape"||e.defaultPrevented||(e.preventDefault(),this.close("escape"))}}focusIsInside(){const e=document.activeElement;return e&&this.contains(e)?!0:this.shadowRoot?.activeElement!=null}updated(e){super.updated(e),e.has("standalone")&&this.syncBusSubscription(),e.has("heading")&&this.updateGeneratedAriaLabel(),(e.has("anchor")||e.has("fullHeight")||e.has("open")||e.has("mode")||e.has("pageOverlayRequested"))&&(this.syncAnchorTracking(),this.syncAnchorGeometry()),(e.has("open")||e.has("mode")||e.has("pageOverlayRequested"))&&this.syncOverlayModal(),(e.has("open")||e.has("mode")||e.has("anchor")||e.has("pageOverlayRequested"))&&this.dispatchEvent(new CustomEvent("flyout-state-changed",{detail:{},bubbles:!0,composed:!0}))}syncAnchorGeometry(){const e=v(this,"esp-page"),t=this.anchor?this.getPageChain(this.anchor):[],r=e?.shadowRoot?.querySelector(".esp-page-main"),o=this.panelRef.value;if(!this.open||this.effectiveOverlay||!this.anchor||!e||!t.includes(e)||!r||!o){this.clearAnchorGeometry();return}const s=this.anchor.getBoundingClientRect(),n=Math.max(0,s.top-r.getBoundingClientRect().top),i=this.getVisibleBlockBounds(),u=Math.max(0,i.bottom-i.top),c=Number.isFinite(s.height)?s.height:0;this.setGeometryProperty("--_esp-flyout-anchor-offset",`${n}px`),this.setGeometryProperty("--_esp-flyout-max-block-size",`${u}px`),this.setGeometryProperty("--_esp-flyout-anchor-block-size",`${c}px`);const y=o.getBoundingClientRect().height||u,b=Math.max(0,s.top+y-i.bottom),P=Math.max(0,y-c),g=this.fullHeight?b:Math.min(b,P);this.setGeometryProperty("--_esp-flyout-viewport-shift",`${g}px`);const C=s.top-g,m=8,E=s.top+c/2,S=Math.min(Math.max(m,y-m),Math.max(m,E-C));this.setGeometryProperty("--_esp-flyout-anchor-marker-offset",`${S}px`)}getVisibleBlockBounds(){const e=window.visualViewport;let t=e?.offsetTop??0,r=t+(e?.height??window.innerHeight);for(let o=this.composedParent(this);o;o=this.composedParent(o)){const s=getComputedStyle(o).overflowY;if(s!=="auto"&&s!=="scroll")continue;const n=o.getBoundingClientRect(),i=o instanceof HTMLElement?o.clientTop:0,u=o instanceof HTMLElement?o.clientHeight:n.height;if(u<=0)continue;const c=n.top+i;t=Math.max(t,c),r=Math.min(r,c+u)}return{top:t,bottom:Math.max(t,r)}}composedParent(e){if(e.parentElement)return e.parentElement;const t=e.getRootNode();return t instanceof ShadowRoot?t.host:null}setGeometryProperty(e,t){this.style.getPropertyValue(e)!==t&&this.style.setProperty(e,t)}clearAnchorGeometry(){this.style.removeProperty("--_esp-flyout-anchor-offset"),this.style.removeProperty("--_esp-flyout-viewport-shift"),this.style.removeProperty("--_esp-flyout-max-block-size"),this.style.removeProperty("--_esp-flyout-anchor-block-size"),this.style.removeProperty("--_esp-flyout-anchor-marker-offset")}scheduleAnchorGeometrySync(){!this.isConnected||this.anchorPositionRaf||(this.anchorPositionRaf=requestAnimationFrame(()=>{this.anchorPositionRaf=0,this.syncAnchorGeometry()}))}syncAnchorTracking(){if(!(this.isConnected&&this.open&&!!this.anchor&&!this.effectiveOverlay)){this.stopAnchorTracking();return}this.trackingAnchorPosition||(this.trackingAnchorPosition=!0,window.addEventListener("scroll",this.boundAnchorViewportChange,{capture:!0,passive:!0}),window.addEventListener("resize",this.boundAnchorViewportChange,{passive:!0}));const t=this.panelRef.value;t&&t!==this.observedAnchorPanel&&typeof ResizeObserver<"u"&&(this.anchorResizeObserver??=new ResizeObserver(this.boundAnchorViewportChange),this.anchorResizeObserver.disconnect(),this.anchorResizeObserver.observe(t),this.observedAnchorPanel=t)}stopAnchorTracking(){this.trackingAnchorPosition&&(window.removeEventListener("scroll",this.boundAnchorViewportChange,{capture:!0}),window.removeEventListener("resize",this.boundAnchorViewportChange),this.trackingAnchorPosition=!1),this.anchorPositionRaf&&(cancelAnimationFrame(this.anchorPositionRaf),this.anchorPositionRaf=0),this.anchorResizeObserver?.disconnect(),this.observedAnchorPanel=void 0}syncOverlayModal(){const e=this.isConnected&&this.open&&this.effectiveOverlay;if(e===this.overlayActive){!e&&!this.open&&this.overlay.close();return}e?(this.overlayActive=!0,this.setAttribute("role","dialog"),this.setAttribute("aria-modal","true"),this.updateGeneratedAriaLabel(),this.overlay.open(),this.updateComplete.then(()=>{this.overlayActive&&this.overlay.moveFocusInto()})):(this.overlayActive=!1,this.overlay.close(),this.overlayReturnFocusTo&&(this.overlayReturnFocusTo.focus(),this.overlayReturnFocusTo=void 0),this.setAttribute("role",this.baseRole),this.removeAttribute("aria-modal"),this.updateGeneratedAriaLabel())}updateGeneratedAriaLabel(){const e=this.getAttribute("aria-label");if(e!==null&&e!==this.lastGeneratedAriaLabel)return;const t=this.heading||(this.overlayActive?H:"");t?(this.setAttribute("aria-label",t),this.lastGeneratedAriaLabel=t):(this.removeAttribute("aria-label"),this.lastGeneratedAriaLabel=null)}render(){return w`
35
35
  <div class="vellum" aria-hidden="true" @click=${()=>this.close("vellum")}></div>
36
36
  <div
37
- class=${L({panel:!0,anchored:!!this.anchor,"full-height":this.fullHeight})}
37
+ class=${O({panel:!0,anchored:!!this.anchor,"full-height":this.fullHeight})}
38
38
  part="panel"
39
- ${O(this.panelRef)}
39
+ ${L(this.panelRef)}
40
40
  >
41
+ <span class="anchor-terminus" aria-hidden="true"></span>
41
42
  <header part="header">
42
- ${this.heading?w`<h2>${this.heading}</h2>`:S}
43
+ ${this.heading?w`<h2>${this.heading}</h2>`:T}
43
44
 
44
45
  <button class="close" aria-label="Close" @click=${()=>this.close("button")}>
45
- ${B}
46
+ ${G}
46
47
  </button>
47
48
  </header>
48
49
  <div class="content" part="content">
49
50
  <slot @slotchange=${this.boundAnchorViewportChange}></slot>
50
51
  </div>
51
52
  </div>
52
- `}};n.styles=[...A.styles,p`
53
+ `}};a.styles=[...k.styles,p`
53
54
  :host {
54
55
  display: none;
55
56
  }
@@ -57,7 +58,10 @@ var h=function(d,e,t,i){var o=arguments.length,s=o<3?e:i===null?i=Object.getOwnP
57
58
  :host([open]) {
58
59
  display: block;
59
60
 
60
- width: var(--esp-page-flyout-width, 20rem);
61
+ width: var(
62
+ --_esp-flyout-used-width,
63
+ var(--esp-page-flyout-width, var(--esp-page-flyout-min-width, 20rem))
64
+ );
61
65
  margin-block-start: calc(
62
66
  var(--_esp-flyout-anchor-offset, 0px) - var(--_esp-flyout-viewport-shift, 0px)
63
67
  );
@@ -70,7 +74,10 @@ var h=function(d,e,t,i){var o=arguments.length,s=o<3?e:i===null?i=Object.getOwnP
70
74
  .panel {
71
75
  background: var(--esp-flyout-background, var(--esp-color-background));
72
76
 
73
- width: var(--esp-page-flyout-width, 20rem);
77
+ width: var(
78
+ --_esp-flyout-used-width,
79
+ var(--esp-page-flyout-width, var(--esp-page-flyout-min-width, 20rem))
80
+ );
74
81
  display: flex;
75
82
  flex-direction: column;
76
83
  position: relative;
@@ -96,17 +103,34 @@ var h=function(d,e,t,i){var o=arguments.length,s=o<3?e:i===null?i=Object.getOwnP
96
103
  &.full-height {
97
104
  block-size: var(--_esp-flyout-max-block-size, 100dvh);
98
105
 
99
- &::before {
106
+ &::before,
107
+ &::after,
108
+ > .anchor-terminus {
100
109
  display: none;
101
110
  }
102
111
  }
103
112
 
113
+ > .anchor-terminus {
114
+ display: var(--_esp-flyout-preview-anchor-display, none);
115
+ position: absolute;
116
+ z-index: 2;
117
+ inset-block-start: var(--_esp-flyout-anchor-marker-offset, 50%);
118
+ inset-inline-start: -2px;
119
+ inline-size: 4px;
120
+ block-size: var(--esp-size-medium);
121
+ translate: 0 -50%;
122
+ background: var(--esp-color-border);
123
+ pointer-events: none;
124
+ }
125
+
104
126
  &::before {
105
127
  content: "";
106
128
  position: absolute;
107
129
  z-index: 1;
108
130
  inset-block-start: var(--_esp-flyout-anchor-marker-offset, 50%);
109
- inset-inline-start: calc(-1 * var(--esp-size-small));
131
+ inset-inline-start: calc(
132
+ -1 * (var(--esp-size-small) + var(--_esp-flyout-preview-bridge-width, 0px))
133
+ );
110
134
  inline-size: var(--esp-size-small);
111
135
  block-size: var(--esp-size-medium);
112
136
  translate: 0 -50%;
@@ -114,6 +138,24 @@ var h=function(d,e,t,i){var o=arguments.length,s=o<3?e:i===null?i=Object.getOwnP
114
138
  background: var(--esp-color-border);
115
139
  pointer-events: none;
116
140
  }
141
+
142
+
143
+ &::after {
144
+ content: "";
145
+ position: absolute;
146
+ z-index: 1;
147
+ inset-block-start: var(--_esp-flyout-anchor-marker-offset, 50%);
148
+ inset-inline-start: calc(-1 * var(--_esp-flyout-preview-bridge-width, 0px));
149
+ inline-size: var(--_esp-flyout-preview-bridge-width, 0px);
150
+ border-block-start: 2px dotted var(--esp-color-border);
151
+ opacity: 0.4;
152
+ translate: 0 -50%;
153
+ pointer-events: none;
154
+ }
155
+ }
156
+
157
+ > .anchor-terminus {
158
+ display: none;
117
159
  }
118
160
 
119
161
  > header {
@@ -152,25 +194,34 @@ var h=function(d,e,t,i){var o=arguments.length,s=o<3?e:i===null?i=Object.getOwnP
152
194
  flex: 1;
153
195
  min-block-size: 0;
154
196
  overflow-y: auto;
155
- overscroll-behavior-block: contain;
197
+
198
+ overscroll-behavior-block: auto;
156
199
  padding: var(--esp-flyout-padding, var(--esp-size-padding));
157
200
  }
158
201
  }
159
202
 
160
203
 
161
- :host([open][mode="overlay"]) {
204
+ :host([open][mode="overlay"]),
205
+ :host([open][data-page-overlay]) {
162
206
  ${R}
163
207
  }
164
208
 
165
- :host([open][mode="overlay"]) .vellum {
209
+ :host([open][mode="overlay"]) .vellum,
210
+ :host([open][data-page-overlay]) .vellum {
166
211
  ${x}
167
212
  }
168
213
 
169
- :host([open][mode="overlay"]) .panel {
170
- ${P}
214
+ :host([open][mode="overlay"]) .panel,
215
+ :host([open][data-page-overlay]) .panel {
216
+ ${z}
171
217
  }
172
218
 
173
- :host([open][mode="overlay"]) .panel.anchored::before {
219
+ :host([open][mode="overlay"]) .panel.anchored::before,
220
+ :host([open][mode="overlay"]) .panel.anchored::after,
221
+ :host([open][mode="overlay"]) .panel.anchored > .anchor-terminus,
222
+ :host([open][data-page-overlay]) .panel.anchored::before,
223
+ :host([open][data-page-overlay]) .panel.anchored::after,
224
+ :host([open][data-page-overlay]) .panel.anchored > .anchor-terminus {
174
225
  display: none;
175
226
  }
176
227
 
@@ -185,10 +236,12 @@ var h=function(d,e,t,i){var o=arguments.length,s=o<3?e:i===null?i=Object.getOwnP
185
236
  }
186
237
 
187
238
  .panel {
188
- ${P}
239
+ ${z}
189
240
  }
190
241
 
191
- .panel.anchored::before {
242
+ .panel.anchored::before,
243
+ .panel.anchored::after,
244
+ .panel.anchored > .anchor-terminus {
192
245
  display: none;
193
246
  }
194
247
  }
@@ -198,4 +251,4 @@ var h=function(d,e,t,i){var o=arguments.length,s=o<3?e:i===null?i=Object.getOwnP
198
251
  transition: none;
199
252
  }
200
253
  }
201
- `],h([l({type:Boolean,reflect:!0})],n.prototype,"open",void 0),h([l({type:String})],n.prototype,"heading",void 0),h([l({reflect:!0})],n.prototype,"mode",void 0),h([l({attribute:!1})],n.prototype,"anchor",void 0),h([l({type:Boolean,reflect:!0,attribute:"full-height"})],n.prototype,"fullHeight",void 0),h([l({type:Boolean,reflect:!0,attribute:"match-surface"})],n.prototype,"matchSurface",void 0),h([l({type:Boolean,reflect:!0})],n.prototype,"standalone",void 0),h([l({type:String,reflect:!0})],n.prototype,"scope",void 0),n=h([F("esp-flyout")],n);export{n as EspalierFlyout};
254
+ `],l([h({type:Boolean,reflect:!0})],a.prototype,"open",void 0),l([h({type:String})],a.prototype,"heading",void 0),l([h({reflect:!0})],a.prototype,"mode",void 0),l([h({type:Boolean,reflect:!0,attribute:"data-page-overlay"})],a.prototype,"pageOverlayRequested",void 0),l([h({attribute:!1})],a.prototype,"anchor",void 0),l([h({type:Boolean,reflect:!0,attribute:"full-height"})],a.prototype,"fullHeight",void 0),l([h({type:Boolean,reflect:!0,attribute:"match-surface"})],a.prototype,"matchSurface",void 0),l([h({type:Boolean,reflect:!0})],a.prototype,"standalone",void 0),l([h({type:String,reflect:!0})],a.prototype,"scope",void 0),a=l([_("esp-flyout")],a);export{a as EspalierFlyout};
@@ -1 +1 @@
1
- import{getEspBus as d}from"../shared/bus-events.js";class f{getEffectiveTopOffset(){if(this.isHeaderFixed)return this.headerHeight;if(!this.headerElement)return 0;const s=this.headerElement.getBoundingClientRect().bottom;return Math.max(0,Math.min(s,this.headerHeight))}constructor(s,c){this.lastScrollY=0,this.mode="natural",this.headerHeight=0,this.isHeaderFixed=!1,this.frozenDocumentTop=0,this.scrollDirection=null,this.headerElement=null,this._pendingSetup=null,this.bus=d(),this.onFixedMenusChanged=({fixed:e})=>{this.isHeaderFixed=e,this.detectHeaderState(),this.mode="natural",this.scrollDirection=null;const t=this.host.shadowRoot?.querySelector(this.targetSelector);t&&(t.style.top=`${this.getEffectiveTopOffset()}px`),this.lastScrollY=window.scrollY},this.handleResize=()=>{this.detectHeaderState(),this.mode="natural",this.scrollDirection=null;const e=this.host.shadowRoot?.querySelector(this.targetSelector);e&&(e.style.top=`${this.getEffectiveTopOffset()}px`),this.lastScrollY=window.scrollY},this.handleScroll=()=>{const e=this.host.shadowRoot?.querySelector(this.targetSelector);if(!e)return;const t=window.scrollY,l=window.innerHeight,h=e.offsetHeight;if(t===this.lastScrollY)return;const a=t>this.lastScrollY,o=this.getEffectiveTopOffset();if(h+o<=l){e.style.top=`${o}px`,this.mode="natural",this.lastScrollY=t;return}const i=e.getBoundingClientRect(),n=l-h;if(a)switch(this.mode){case"natural":e.style.top=`${n}px`,this.mode="stuck-bottom";break;case"stuck-top":this.frozenDocumentTop=i.top+t,this.scrollDirection="down",this.mode="scrolling",e.style.top=`${i.top}px`;break;case"scrolling":if(this.scrollDirection==="down"){const r=this.frozenDocumentTop-t;r<=n?(e.style.top=`${n}px`,this.mode="stuck-bottom"):e.style.top=`${r}px`}else this.frozenDocumentTop=i.top+t,this.scrollDirection="down",e.style.top=`${i.top}px`;break;case"stuck-bottom":break}else switch(this.mode){case"natural":e.style.top=`${o}px`,this.mode="stuck-top";break;case"stuck-bottom":this.frozenDocumentTop=i.top+t,this.scrollDirection="up",this.mode="scrolling",e.style.top=`${i.top}px`;break;case"scrolling":if(this.scrollDirection==="up"){const r=this.frozenDocumentTop-t;r>=o?(e.style.top=`${o}px`,this.mode="stuck-top"):e.style.top=`${r}px`}else this.frozenDocumentTop=i.top+t,this.scrollDirection="up",e.style.top=`${i.top}px`;break;case"stuck-top":this.isHeaderFixed||(e.style.top=`${o}px`);break}this.lastScrollY=t},(this.host=s).addController(this),this.targetSelector=c,this.resizeObserver=new ResizeObserver(()=>this.handleResize())}hostConnected(){window.addEventListener("scroll",this.handleScroll,{passive:!0}),window.addEventListener("resize",this.handleResize),this.bus.subscribe("fixed-menus-changed",this.onFixedMenusChanged),this.setupTargetObservation()}hostDisconnected(){window.removeEventListener("scroll",this.handleScroll),window.removeEventListener("resize",this.handleResize),this.bus.unsubscribe("fixed-menus-changed",this.onFixedMenusChanged),this.resizeObserver.disconnect(),this._pendingSetup!==null&&(clearTimeout(this._pendingSetup),this._pendingSetup=null)}setupTargetObservation(){if(this._pendingSetup=null,!this.host.isConnected)return;const s=this.host.shadowRoot?.querySelector(this.targetSelector);s?(this.resizeObserver.observe(s),this.detectHeaderState(),this.lastScrollY=window.scrollY,s.style.top=`${this.getEffectiveTopOffset()}px`):this._pendingSetup=setTimeout(()=>this.setupTargetObservation(),100)}detectHeaderState(){this.headerElement=this.host.shadowRoot?.querySelector(".esp-page-top")??null,this.headerElement&&(this.headerHeight=this.headerElement.offsetHeight);const s=this.host.shadowRoot?.querySelector(".esp-page");this.isHeaderFixed=s?.classList.contains("fixed-header")||s?.classList.contains("fixed-menus")||!1}}export{f as BiDirectionalStickyController};
1
+ import{getEspBus as p}from"../shared/bus-events.js";class g{getEffectiveTopOffset(){const s=this.topOffsetOverride?.();if(s!==void 0)return s;if(this.isHeaderFixed)return this.headerHeight;if(!this.headerElement)return 0;const n=this.headerElement.getBoundingClientRect().bottom;return Math.max(0,Math.min(n,this.headerHeight))}constructor(s,n,a={}){this.lastScrollY=0,this.mode="natural",this.headerHeight=0,this.isHeaderFixed=!1,this.frozenDocumentTop=0,this.scrollDirection=null,this.headerElement=null,this._pendingSetup=null,this.bus=p(),this.onFixedMenusChanged=({fixed:e})=>{this.isHeaderFixed=e,this.detectHeaderState(),this.mode="natural",this.scrollDirection=null;const t=this.host.shadowRoot?.querySelector(this.targetSelector);t&&(t.style.top=`${this.getEffectiveTopOffset()}px`),this.lastScrollY=window.scrollY},this.handleResize=()=>{this.detectHeaderState(),this.mode="natural",this.scrollDirection=null;const e=this.host.shadowRoot?.querySelector(this.targetSelector);e&&(e.style.top=`${this.getEffectiveTopOffset()}px`),this.lastScrollY=window.scrollY},this.handleScroll=()=>{const e=this.host.shadowRoot?.querySelector(this.targetSelector);if(!e)return;const t=window.scrollY,h=window.innerHeight,c=e.offsetHeight;if(t===this.lastScrollY)return;const d=t>this.lastScrollY,o=this.getEffectiveTopOffset();if(c+o<=h){e.style.top=`${o}px`,this.mode="natural",this.lastScrollY=t;return}const i=e.getBoundingClientRect(),l=h-c;if(d)switch(this.mode){case"natural":e.style.top=`${l}px`,this.mode="stuck-bottom";break;case"stuck-top":this.frozenDocumentTop=i.top+t,this.scrollDirection="down",this.mode="scrolling",e.style.top=`${i.top}px`;break;case"scrolling":if(this.scrollDirection==="down"){const r=this.frozenDocumentTop-t;r<=l?(e.style.top=`${l}px`,this.mode="stuck-bottom"):e.style.top=`${r}px`}else this.frozenDocumentTop=i.top+t,this.scrollDirection="down",e.style.top=`${i.top}px`;break;case"stuck-bottom":break}else switch(this.mode){case"natural":e.style.top=`${o}px`,this.mode="stuck-top";break;case"stuck-bottom":this.frozenDocumentTop=i.top+t,this.scrollDirection="up",this.mode="scrolling",e.style.top=`${i.top}px`;break;case"scrolling":if(this.scrollDirection==="up"){const r=this.frozenDocumentTop-t;r>=o?(e.style.top=`${o}px`,this.mode="stuck-top"):e.style.top=`${r}px`}else this.frozenDocumentTop=i.top+t,this.scrollDirection="up",e.style.top=`${i.top}px`;break;case"stuck-top":this.isHeaderFixed||(e.style.top=`${o}px`);break}this.lastScrollY=t},(this.host=s).addController(this),this.targetSelector=n,this.topOffsetOverride=a.topOffset,this.resizeObserver=new ResizeObserver(()=>this.handleResize())}hostConnected(){window.addEventListener("scroll",this.handleScroll,{passive:!0}),window.addEventListener("resize",this.handleResize),this.bus.subscribe("fixed-menus-changed",this.onFixedMenusChanged),this.setupTargetObservation()}hostDisconnected(){window.removeEventListener("scroll",this.handleScroll),window.removeEventListener("resize",this.handleResize),this.bus.unsubscribe("fixed-menus-changed",this.onFixedMenusChanged),this.resizeObserver.disconnect(),this._pendingSetup!==null&&(clearTimeout(this._pendingSetup),this._pendingSetup=null)}setupTargetObservation(){if(this._pendingSetup=null,!this.host.isConnected)return;const s=this.host.shadowRoot?.querySelector(this.targetSelector);s?(this.resizeObserver.observe(s),this.detectHeaderState(),this.lastScrollY=window.scrollY,s.style.top=`${this.getEffectiveTopOffset()}px`):this._pendingSetup=setTimeout(()=>this.setupTargetObservation(),100)}detectHeaderState(){this.headerElement=this.host.shadowRoot?.querySelector(".esp-page-top")??null,this.headerElement&&(this.headerHeight=this.headerElement.offsetHeight);const s=this.host.shadowRoot?.querySelector(".esp-page");this.isHeaderFixed=s?.classList.contains("fixed-header")||s?.classList.contains("fixed-menus")||!1}}export{g as BiDirectionalStickyController};