@taprootio/espalier 2.7.2 → 2.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/custom-elements.json +4091 -4034
- package/dist/dialog/esp-dialog.d.ts +4 -4
- package/dist/popover/esp-popover.d.ts +29 -4
- package/dist/popover/esp-popover.js +6 -6
- package/dist/search/esp-search.d.ts +3 -3
- package/dist/shared/popover-controller.js +1 -1
- package/package.json +1 -1
|
@@ -86,8 +86,8 @@ import { LitElement } from "lit";
|
|
|
86
86
|
* has moved in. Safe to initialize third-party widgets (e.g. Stripe
|
|
87
87
|
* Elements) or measure layout at this point.
|
|
88
88
|
*
|
|
89
|
-
* @event {CustomEvent<{ reason: "escape" | "close-dialog" | "api" }>}
|
|
90
|
-
*
|
|
89
|
+
* @event {CustomEvent<{ reason: "escape" | "close-dialog" | "api" }>} esp-dialog-closing -
|
|
90
|
+
* Fired before the dialog begins closing.
|
|
91
91
|
* Call `event.preventDefault()` to cancel the close (e.g. for
|
|
92
92
|
* unsaved-changes confirmation). The `reason` indicates what
|
|
93
93
|
* triggered the close: `"escape"` for the Escape key,
|
|
@@ -95,8 +95,8 @@ import { LitElement } from "lit";
|
|
|
95
95
|
* (typically `<esp-form method="dialog">`), or `"api"` for a
|
|
96
96
|
* direct `toggleOpen()` call.
|
|
97
97
|
*
|
|
98
|
-
* @event {CustomEvent<{ reason: "escape" | "close-dialog" | "api" }>}
|
|
99
|
-
*
|
|
98
|
+
* @event {CustomEvent<{ reason: "escape" | "close-dialog" | "api" }>} esp-dialog-closed -
|
|
99
|
+
* Fired after the dialog has fully closed,
|
|
100
100
|
* inert state has been restored, and focus has returned to the
|
|
101
101
|
* previously focused element. Safe to tear down resources.
|
|
102
102
|
*
|
|
@@ -54,10 +54,12 @@ export declare class EspalierPopover extends LitElement {
|
|
|
54
54
|
*/
|
|
55
55
|
readonly popoverId: string;
|
|
56
56
|
/**
|
|
57
|
-
* Attach determines which side of the target the
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
57
|
+
* Attach determines which side of the target the popover will appear on.
|
|
58
|
+
* With the default `collision="flip"`, the popover tries the specified side
|
|
59
|
+
* first but may use the opposite side when it has more room. Use
|
|
60
|
+
* `collision="shift"` to preserve this requested side while shifting the
|
|
61
|
+
* panel into the viewport, or `collision="none"` to disable adjustment.
|
|
62
|
+
* It can be one of the following:
|
|
61
63
|
*
|
|
62
64
|
* #### Place above
|
|
63
65
|
*
|
|
@@ -104,6 +106,29 @@ export declare class EspalierPopover extends LitElement {
|
|
|
104
106
|
* ```
|
|
105
107
|
*/
|
|
106
108
|
attach: "left" | "right" | "above" | "below";
|
|
109
|
+
/**
|
|
110
|
+
* Determines how the popover responds when its natural placement would
|
|
111
|
+
* leave the viewport:
|
|
112
|
+
*
|
|
113
|
+
* - `"flip"` moves the popover to the opposite side when that side has
|
|
114
|
+
* more room, then constrains it horizontally. This is the default and
|
|
115
|
+
* preserves the existing behavior.
|
|
116
|
+
* - `"shift"` keeps the requested `attach` side and shifts the popover
|
|
117
|
+
* within the viewport. Oversized panels are pinned to the viewport's
|
|
118
|
+
* top or left edge and may overlap content beyond the trigger.
|
|
119
|
+
* - `"none"` keeps the requested side without viewport adjustment.
|
|
120
|
+
*
|
|
121
|
+
* Use `shift` when the attachment side conveys meaning and a partial
|
|
122
|
+
* overlap is preferable to flipping the panel:
|
|
123
|
+
*
|
|
124
|
+
* ```html
|
|
125
|
+
* <esp-popover attach="above" collision="shift">
|
|
126
|
+
* <esp-button label="Banner settings" slot="target"></esp-button>
|
|
127
|
+
* <esp-box slot="popover">Settings stay attached above.</esp-box>
|
|
128
|
+
* </esp-popover>
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
collision: "flip" | "shift" | "none";
|
|
107
132
|
/**
|
|
108
133
|
* Align determines how the popover is aligned relative
|
|
109
134
|
* to the target. For example, if attach is "below" and align
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var
|
|
1
|
+
var n=function(u,t,e,r){var o=arguments.length,i=o<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,e):r,h;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(u,t,e,r);else for(var s=u.length-1;s>=0;s--)(h=u[s])&&(i=(o<3?h(i):o>3?h(t,e,i):h(t,e))||i);return o>3&&i&&Object.defineProperty(t,e,i),i};import{LitElement as b,css as T,html as w}from"lit";import{customElement as D,property as a,state as P}from"lit/decorators.js";import{createRef as g,ref as m}from"lit/directives/ref.js";import{findContainingPopovers as y,PopoverController as O}from"../shared/popover-controller.js";import{alignAttributeTextInheritance as C}from"../shared/style-fragments.js";let $=0,l=class extends b{constructor(){super(...arguments),this.popoverOpen=!1,this.thePopover=g(),this.popoverSlot=g(),this.targetSlot=g(),this.attachTo=null,this.showDelayTimer=null,this.hideDelayTimer=null,this.isHovered=!1,this.isFocused=!1,this.collisionRafId=0,this.popoverId=`esp-popover-${++$}`,this.popoverCtrl=new O({host:this,closeStrategy:"skip-list",isOpen:()=>this.popoverOpen,onShouldClose:()=>this.closePopover(),onPositionUpdate:()=>this.positionPopover(),getPositionElements:()=>[this.attachTo,this.thePopover.value],getInsideElements:()=>[this.thePopover.value??null],onOutsideClick:()=>this.closePopover()}),this.attach="below",this.collision="flip",this.align="start",this.offset="",this.offsetX=0,this.offsetY=0,this.trigger="click",this.showDelay=0,this.hideDelay=0,this.closePopover=()=>{this.cancelDelays(),this.cancelCollisionAdjustment();const t=this.thePopover.value;if(t&&this.popoverOpen)try{t.hidePopover()}catch{}this.popoverCtrl.stopTracking(),this.popoverCtrl.stopOutsideClick(),this.popoverOpen&&(this.popoverOpen=!1,this.dispatchEvent(new CustomEvent("popover-closed",{bubbles:!0,composed:!0})))},this.openPopover=()=>{this.scheduleOpen()},this.updatePosition=()=>{this.popoverOpen&&this.positionPopover()},this.toggleOpen=t=>{this.trigger==="click"&&(t.stopPropagation(),this.popoverOpen?this.closePopover():this.doOpen())}}cancelDelays(){this.showDelayTimer!==null&&(clearTimeout(this.showDelayTimer),this.showDelayTimer=null),this.hideDelayTimer!==null&&(clearTimeout(this.hideDelayTimer),this.hideDelayTimer=null)}cancelCollisionAdjustment(){this.collisionRafId&&(cancelAnimationFrame(this.collisionRafId),this.collisionRafId=0)}applyPixelOffset(t,e){if(e===0)return t;const r=t.startsWith("calc(")&&t.endsWith(")")?t.slice(5,-1):t,o=e>0?"+":"-";return`calc(${r} ${o} ${Math.abs(e)}px)`}scheduleOpen(){this.hideDelayTimer!==null&&(clearTimeout(this.hideDelayTimer),this.hideDelayTimer=null),!this.popoverOpen&&(this.showDelay>0&&this.showDelayTimer===null?this.showDelayTimer=setTimeout(()=>{this.showDelayTimer=null,this.doOpen()},this.showDelay):this.showDelay<=0&&this.doOpen())}scheduleClose(){this.showDelayTimer!==null&&(clearTimeout(this.showDelayTimer),this.showDelayTimer=null),this.popoverOpen&&(this.hideDelay>0&&this.hideDelayTimer===null?this.hideDelayTimer=setTimeout(()=>{this.hideDelayTimer=null,this.closePopover()},this.hideDelay):this.hideDelay<=0&&this.closePopover())}doOpen(){if(this.popoverOpen)return;const t=y(this);this.popoverCtrl.publishCloseExcept(t),this.popoverOpen=!0,this.positionPopover(),this.popoverCtrl.startTracking(),this.popoverCtrl.startOutsideClick(),this.dispatchEvent(new CustomEvent("popover-opened",{bubbles:!0,composed:!0}))}positionPopover(){const t=this.thePopover.value;if(!t||!this.attachTo)return;const e=this.attachTo.getBoundingClientRect(),r=this.offset.length?this.offset:"0px";t.matches(":popover-open")||t.showPopover();const o=t.getBoundingClientRect(),i=window.innerHeight||document.documentElement.clientHeight,h=window.innerWidth||document.documentElement.clientWidth;this.cancelCollisionAdjustment();let s=this.attach;this.collision==="flip"&&(s==="above"&&e.top<o.height&&i-e.bottom>e.top?s="below":s==="below"&&i-e.bottom<o.height&&e.top>i-e.bottom?s="above":s==="left"&&e.left<o.width&&h-e.right>e.left?s="right":s==="right"&&h-e.right<o.width&&e.left>h-e.right&&(s="left"));let c="0px",f="0px";switch(s){case"above":c=`calc(${e.top-o.height}px - ${r})`;break;case"below":c=`calc(${e.bottom}px + ${r})`;break;case"left":f=`calc(${e.left-o.width}px - ${r})`;break;case"right":f=`calc(${e.right}px + ${r})`;break}if(s==="above"||s==="below")switch(this.align){case"start":f=`${e.left}px`;break;case"center":f=`${e.left+e.width/2-o.width/2}px`;break;case"end":f=`${e.right-o.width}px`;break}else switch(this.align){case"start":c=`${e.top}px`;break;case"center":c=`${e.top+e.height/2-o.height/2}px`;break;case"end":c=`${e.bottom-o.height}px`;break}f=this.applyPixelOffset(f,this.offsetX),c=this.applyPixelOffset(c,this.offsetY),t.style.top=c,t.style.left=f,this.collision!=="none"&&(this.collisionRafId=requestAnimationFrame(()=>{if(this.collisionRafId=0,!this.popoverOpen||!t.matches(":popover-open"))return;const p=t.getBoundingClientRect();let d=p.left;if(p.width>h?d=0:d=Math.min(Math.max(p.left,0),h-p.width),d!==p.left&&(t.style.left=`${d}px`),this.collision!=="shift")return;let v=p.top;p.height>i?v=0:v=Math.min(Math.max(p.top,0),i-p.height),v!==p.top&&(t.style.top=`${v}px`)}))}handleHoverEnter(){this.isHovered=!0,this.scheduleOpen()}handleHoverLeave(){if(this.isHovered=!1,this.trigger==="focus-hover"&&this.isFocused){this.hideDelayTimer!==null&&(clearTimeout(this.hideDelayTimer),this.hideDelayTimer=null);return}this.scheduleClose()}handleFocusIn(){this.isFocused=!0,this.scheduleOpen()}handleFocusOut(){if(this.isFocused=!1,this.trigger==="focus-hover"&&this.isHovered){this.hideDelayTimer!==null&&(clearTimeout(this.hideDelayTimer),this.hideDelayTimer=null);return}this.scheduleClose()}disconnectedCallback(){super.disconnectedCallback(),this.cancelDelays(),this.cancelCollisionAdjustment()}updated(t){t.has("trigger")&&(this.isHovered=!1,this.isFocused=!1,this.cancelDelays()),this.popoverOpen&&["attach","align","collision","offset","offsetX","offsetY"].some(e=>t.has(e))&&this.positionPopover()}firstUpdated(t){let e=this.targetSlot.value.assignedElements()[0];for(;e instanceof HTMLSlotElement;)e=e.assignedElements()[0];this.attachTo=e;const r=this.thePopover.value;r&&(r.setAttribute("popover","manual"),r.id=this.popoverId);const o=this.popoverSlot.value?.assignedElements();if(o?.length){let i=o[0];for(;i instanceof HTMLSlotElement;)i=i.assignedElements()[0];i&&(i["linked-popover"]=this,i.addEventListener("click",h=>{h.stopPropagation();const s=[this,...y(this)];this.popoverCtrl.publishCloseExcept(s)}))}}render(){return w`
|
|
2
2
|
<slot
|
|
3
|
-
${
|
|
3
|
+
${m(this.targetSlot)}
|
|
4
4
|
@click=${t=>{this.trigger==="click"&&this.toggleOpen(t)}}
|
|
5
5
|
@mouseenter=${()=>{this.trigger!=="hover"&&this.trigger!=="focus-hover"||this.handleHoverEnter()}}
|
|
6
6
|
@mouseleave=${()=>{this.trigger!=="hover"&&this.trigger!=="focus-hover"||this.handleHoverLeave()}}
|
|
@@ -9,14 +9,14 @@ var p=function(u,t,e,r){var o=arguments.length,i=o<3?t:r===null?r=Object.getOwnP
|
|
|
9
9
|
name="target"
|
|
10
10
|
></slot>
|
|
11
11
|
<div
|
|
12
|
-
${
|
|
12
|
+
${m(this.thePopover)}
|
|
13
13
|
class="popover-content"
|
|
14
14
|
@mouseenter=${()=>{this.trigger!=="hover"&&this.trigger!=="focus-hover"||(this.isHovered=!0,this.hideDelayTimer!==null&&(clearTimeout(this.hideDelayTimer),this.hideDelayTimer=null))}}
|
|
15
15
|
@mouseleave=${()=>{this.trigger!=="hover"&&this.trigger!=="focus-hover"||this.handleHoverLeave()}}
|
|
16
16
|
>
|
|
17
|
-
<slot name="popover" ${
|
|
17
|
+
<slot name="popover" ${m(this.popoverSlot)}></slot>
|
|
18
18
|
</div>
|
|
19
|
-
`}};
|
|
19
|
+
`}};l.styles=[C,T`
|
|
20
20
|
:host {
|
|
21
21
|
position: relative;
|
|
22
22
|
display: flex;
|
|
@@ -33,4 +33,4 @@ var p=function(u,t,e,r){var o=arguments.length,i=o<3?t:r===null?r=Object.getOwnP
|
|
|
33
33
|
overflow: visible;
|
|
34
34
|
color: var(--esp-color-text);
|
|
35
35
|
}
|
|
36
|
-
`],
|
|
36
|
+
`],n([P()],l.prototype,"popoverOpen",void 0),n([a({attribute:"attach",type:String})],l.prototype,"attach",void 0),n([a({attribute:"collision",type:String})],l.prototype,"collision",void 0),n([a({attribute:"align",type:String})],l.prototype,"align",void 0),n([a({attribute:"offset",type:String})],l.prototype,"offset",void 0),n([a({attribute:"offset-x",type:Number})],l.prototype,"offsetX",void 0),n([a({attribute:"offset-y",type:Number})],l.prototype,"offsetY",void 0),n([a({attribute:"trigger",type:String})],l.prototype,"trigger",void 0),n([a({attribute:"show-delay",type:Number})],l.prototype,"showDelay",void 0),n([a({attribute:"hide-delay",type:Number})],l.prototype,"hideDelay",void 0),l=n([D("esp-popover")],l);export{l as EspalierPopover};
|
|
@@ -19,14 +19,14 @@ export interface SearchResult {
|
|
|
19
19
|
* etc.) by listening for `search-requested` events and calling
|
|
20
20
|
* `setResults()` with the matches.
|
|
21
21
|
*
|
|
22
|
-
* @fires search-requested
|
|
22
|
+
* @fires search-requested - The user changed the query input. Fires on
|
|
23
23
|
* every keystroke (not debounced) so consumers can track the latest
|
|
24
24
|
* query and discard stale async results. Consumers that need debouncing
|
|
25
25
|
* should apply it themselves (e.g. Pagefind's `debouncedSearch()`).
|
|
26
26
|
* `detail: { query: string }`
|
|
27
|
-
* @fires result-selected
|
|
27
|
+
* @fires result-selected - The user chose a result.
|
|
28
28
|
* `detail: { url: string }`
|
|
29
|
-
* @fires search-closed
|
|
29
|
+
* @fires search-closed - The overlay was closed (Escape, backdrop click,
|
|
30
30
|
* or result selection). Consumers should use this to cancel in-flight
|
|
31
31
|
* searches or discard pending results.
|
|
32
32
|
* `detail: {}`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getEspBus as c}from"./bus-events.js";function
|
|
1
|
+
import{getEspBus as c}from"./bus-events.js";function l(r){const s=[],t=new Set;let e=r;for(;e&&!t.has(e);){t.add(e);const i=e["linked-popover"];if(i){e=i;continue}const o=e.closest("esp-popover");if(o){s.includes(o)||s.push(o),e=o.parentElement||o.getRootNode()?.host;continue}const n=e.getRootNode();e=n instanceof ShadowRoot?n.host:void 0}return s}class u{constructor(s){this.bus=c(),this.rafId=0,this.positionResizeObserver=null,this.handleClosePopovers=t=>{if(!this.opts.isOpen())return;const e=this.opts.host;if(this.opts.closeStrategy==="source-identity"){if(!t.source||t.source===e||t.source instanceof Node&&(e.contains(t.source)||e.shadowRoot?.contains(t.source)))return}else if(t.skipPopovers?.includes(e))return;this.opts.onShouldClose()},this.onScrollOrResize=()=>{this.rafId||(this.rafId=requestAnimationFrame(()=>{if(this.rafId=0,!!this.opts.isOpen()){if(this.opts.shouldContinueTracking&&!this.opts.shouldContinueTracking()){this.opts.onShouldClose();return}this.opts.onPositionUpdate?.()}}))},this.onDocumentClick=t=>{const e=this.opts.host,i=t.composedPath();if(i.includes(e))return;const o=this.opts.getInsideElements?.()??[];for(const n of o)if(n&&i.includes(n))return;this.opts.isOpen()&&this.opts.onOutsideClick?.()},this.opts=s,s.host.addController(this)}hostConnected(){this.bus.subscribe("close-popovers",this.handleClosePopovers)}hostDisconnected(){this.bus.unsubscribe("close-popovers",this.handleClosePopovers),this.stopTracking(),this.stopOutsideClick()}startTracking(){if(this.opts.onPositionUpdate&&(window.addEventListener("scroll",this.onScrollOrResize,{capture:!0,passive:!0}),window.addEventListener("resize",this.onScrollOrResize,{passive:!0}),this.opts.getPositionElements&&typeof ResizeObserver<"u")){this.positionResizeObserver?.disconnect(),this.positionResizeObserver=new ResizeObserver(this.onScrollOrResize);const s=new Set(this.opts.getPositionElements().filter(Boolean));for(const t of s)this.positionResizeObserver.observe(t)}}stopTracking(){window.removeEventListener("scroll",this.onScrollOrResize,{capture:!0}),window.removeEventListener("resize",this.onScrollOrResize),this.positionResizeObserver?.disconnect(),this.positionResizeObserver=null,this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=0)}startOutsideClick(){this.opts.onOutsideClick&&document.addEventListener("click",this.onDocumentClick,!0)}stopOutsideClick(){document.removeEventListener("click",this.onDocumentClick,!0)}publishCloseOthers(s=[]){this.bus.publish("close-popovers",{source:this.opts.host,...s.length>0?{skipPopovers:s}:{}})}publishCloseExcept(s){this.bus.publish("close-popovers",{source:this.opts.host,skipPopovers:s})}}export{u as PopoverController,l as findContainingPopovers};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taprootio/espalier",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.1",
|
|
4
4
|
"packageManager": "bun@1.3.12",
|
|
5
5
|
"description": "Espalier — a themeable, accessible, framework-agnostic, enterprise-grade design system built on web standards and love.",
|
|
6
6
|
"customElements": "custom-elements.json",
|