@data-slot/popover 0.2.41 → 0.2.43

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/README.md CHANGED
@@ -53,6 +53,7 @@ const popover = createPopover(element, {
53
53
  alignOffset: 0,
54
54
  avoidCollisions: true,
55
55
  collisionPadding: 8,
56
+ portal: true,
56
57
  closeOnClickOutside: true,
57
58
  closeOnEscape: true,
58
59
  onOpenChange: (open) => console.log(open),
@@ -70,6 +71,7 @@ const popover = createPopover(element, {
70
71
  | `alignOffset` | `number` | `0` | Offset from alignment edge in pixels |
71
72
  | `avoidCollisions` | `boolean` | `true` | Flip/shift to stay in viewport |
72
73
  | `collisionPadding` | `number` | `8` | Viewport edge padding in pixels |
74
+ | `portal` | `boolean` | `true` | Portal content to `document.body` while open |
73
75
  | `position` | `"top" \| "bottom" \| "left" \| "right"` | - | Deprecated alias for `side` |
74
76
  | `closeOnClickOutside` | `boolean` | `true` | Close when clicking outside |
75
77
  | `closeOnEscape` | `boolean` | `true` | Close when pressing Escape |
@@ -119,6 +121,7 @@ Options can also be set via data attributes on the root element. JS options take
119
121
  | `data-align-offset` | number | `0` | Offset from alignment edge (px) |
120
122
  | `data-avoid-collisions` | boolean | `true` | Flip/shift to stay in viewport |
121
123
  | `data-collision-padding` | number | `8` | Viewport edge padding (px) |
124
+ | `data-portal` | boolean | `true` | Portal content to `document.body` while open |
122
125
  | `data-close-on-click-outside` | boolean | `true` | Close when clicking outside |
123
126
  | `data-close-on-escape` | boolean | `true` | Close when pressing Escape |
124
127
 
@@ -141,31 +144,66 @@ Placement can be set on root or content (content takes precedence):
141
144
 
142
145
  ## Styling
143
146
 
144
- Popover position is computed in JavaScript and applied as `position: fixed` + inline `top/left`.
145
- Use `data-state`, `data-side`, and `data-align` for styling/animation:
147
+ Popover position is computed in JavaScript and applied as `position: absolute` + inline `transform: translate3d(...)`.
148
+ By default, content is portaled to `document.body` while open (document coordinates). In this mode, a generated `popover-positioner` wrapper receives the positioning transform. If `portal` is disabled, positioning is applied directly to `popover-content`.
149
+ Use `data-open`/`data-closed` and `data-side` for styling/animation.
150
+ When portaling is enabled (default), a transient wrapper with `data-slot="popover-positioner"` is created while open and receives the positioning transform. This keeps `popover-content` free for transform animations.
146
151
 
147
152
  ```css
148
- /* Hidden state */
149
- [data-slot="popover-content"][hidden] {
150
- display: none;
153
+ [data-slot="popover-content"] {
154
+ transform-origin: var(--transform-origin, center);
155
+ --popover-slide-x: 0px;
156
+ --popover-slide-y: -4px;
151
157
  }
152
158
 
153
- [data-slot="popover-content"] {
154
- position: fixed;
155
- transition: opacity 0.2s ease-out, transform 0.2s ease-out;
159
+ [data-slot="popover-content"][data-side="top"] {
160
+ --popover-slide-y: 4px;
161
+ }
162
+ [data-slot="popover-content"][data-side="bottom"] {
163
+ --popover-slide-y: -4px;
164
+ }
165
+ [data-slot="popover-content"][data-side="left"] {
166
+ --popover-slide-x: 4px;
167
+ --popover-slide-y: 0px;
168
+ }
169
+ [data-slot="popover-content"][data-side="right"] {
170
+ --popover-slide-x: -4px;
171
+ --popover-slide-y: 0px;
156
172
  }
157
173
 
158
- [data-slot="popover-content"][hidden][data-side="top"] {
159
- transform: translateY(4px);
174
+ [data-slot="popover-content"][data-open] {
175
+ animation: popover-in 160ms cubic-bezier(0.16, 1, 0.3, 1);
160
176
  }
161
- [data-slot="popover-content"][hidden][data-side="bottom"] {
162
- transform: translateY(-4px);
177
+
178
+ [data-slot="popover-content"][data-closed] {
179
+ pointer-events: none;
180
+ animation: popover-out 120ms ease-in forwards;
163
181
  }
164
- [data-slot="popover-content"][hidden][data-side="left"] {
165
- transform: translateX(4px);
182
+
183
+ @keyframes popover-in {
184
+ from {
185
+ opacity: 0;
186
+ scale: 0.96;
187
+ translate: var(--popover-slide-x) var(--popover-slide-y);
188
+ }
189
+ to {
190
+ opacity: 1;
191
+ scale: 1;
192
+ translate: 0 0;
193
+ }
166
194
  }
167
- [data-slot="popover-content"][hidden][data-side="right"] {
168
- transform: translateX(-4px);
195
+
196
+ @keyframes popover-out {
197
+ from {
198
+ opacity: 1;
199
+ scale: 1;
200
+ translate: 0 0;
201
+ }
202
+ to {
203
+ opacity: 0;
204
+ scale: 0.96;
205
+ translate: var(--popover-slide-x) var(--popover-slide-y);
206
+ }
169
207
  }
170
208
  ```
171
209
 
@@ -178,13 +216,15 @@ With Tailwind:
178
216
  data-slot="popover-content"
179
217
  data-side="bottom"
180
218
  data-align="start"
181
- class="fixed bg-white shadow-lg rounded-lg p-4 transition data-[state=closed]:opacity-0"
219
+ class="absolute bg-white shadow-lg rounded-lg p-4"
182
220
  >
183
221
  Content
184
222
  </div>
185
223
  </div>
186
224
  ```
187
225
 
226
+ Use Tailwind for layout/colors and keep the state selectors from the CSS snippet above for fade/zoom animation.
227
+
188
228
  ## Accessibility
189
229
 
190
230
  The component automatically handles:
@@ -28,6 +28,8 @@ interface PopoverOptions {
28
28
  collisionPadding?: number;
29
29
  /** Callback when open state changes */
30
30
  onOpenChange?: (open: boolean) => void;
31
+ /** Portal content to body while open. @default true */
32
+ portal?: boolean;
31
33
  /** Close when clicking outside */
32
34
  closeOnClickOutside?: boolean;
33
35
  /** Close when pressing Escape */
@@ -28,6 +28,8 @@ interface PopoverOptions {
28
28
  collisionPadding?: number;
29
29
  /** Callback when open state changes */
30
30
  onOpenChange?: (open: boolean) => void;
31
+ /** Portal content to body while open. @default true */
32
+ portal?: boolean;
31
33
  /** Close when clicking outside */
32
34
  closeOnClickOutside?: boolean;
33
35
  /** Close when pressing Escape */
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@data-slot/core`);const t=[`top`,`right`,`bottom`,`left`],n=[`start`,`center`,`end`];function r(r,i={}){let a=(0,e.getPart)(r,`popover-trigger`),o=(0,e.getPart)(r,`popover-content`),s=(0,e.getPart)(r,`popover-close`);if(!a||!o)throw Error(`Popover requires trigger and content slots`);let c=i.defaultOpen??(0,e.getDataBool)(r,`defaultOpen`)??!1,l=i.onOpenChange,u=i.closeOnClickOutside??(0,e.getDataBool)(r,`closeOnClickOutside`)??!0,d=i.closeOnEscape??(0,e.getDataBool)(r,`closeOnEscape`)??!0,f=i.position??(0,e.getDataEnum)(o,`position`,t)??(0,e.getDataEnum)(r,`position`,t),p=i.side??(0,e.getDataEnum)(o,`side`,t)??(0,e.getDataEnum)(r,`side`,t)??f??`bottom`,m=i.align??(0,e.getDataEnum)(o,`align`,n)??(0,e.getDataEnum)(r,`align`,n)??`center`,h=i.sideOffset??(0,e.getDataNumber)(o,`sideOffset`)??(0,e.getDataNumber)(r,`sideOffset`)??4,g=i.alignOffset??(0,e.getDataNumber)(o,`alignOffset`)??(0,e.getDataNumber)(r,`alignOffset`)??0,_=i.avoidCollisions??(0,e.getDataBool)(o,`avoidCollisions`)??(0,e.getDataBool)(r,`avoidCollisions`)??!0,v=i.collisionPadding??(0,e.getDataNumber)(o,`collisionPadding`)??(0,e.getDataNumber)(r,`collisionPadding`)??8,y=c,b=[],x=null,S=!1,C=()=>{S&&=(o.removeAttribute(`tabindex`),!1)},w=()=>{let e=o.querySelector(`[autofocus]`);if(e)return e.focus();let t=o.querySelector(`a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])`);if(t)return t.focus();o.getAttribute(`tabindex`)||(o.setAttribute(`tabindex`,`-1`),S=!0),o.focus()},T=(0,e.ensureId)(o,`popover-content`);a.setAttribute(`aria-haspopup`,`dialog`),a.setAttribute(`aria-controls`,T),o.setAttribute(`data-side`,p),o.setAttribute(`data-align`,m),o.setAttribute(`data-position`,p);let E=()=>{let t=r.ownerDocument.defaultView??window,n=(0,e.computeFloatingPosition)({anchorRect:a.getBoundingClientRect(),contentRect:o.getBoundingClientRect(),side:p,align:m,sideOffset:h,alignOffset:g,avoidCollisions:_,collisionPadding:v});o.style.position=`absolute`,o.style.top=`${n.y+t.scrollY}px`,o.style.left=`${n.x+t.scrollX}px`,o.style.margin=`0`,o.setAttribute(`data-side`,n.side),o.setAttribute(`data-align`,n.align),o.setAttribute(`data-position`,n.side)},D=(0,e.createPositionSync)({observedElements:[a,o],isActive:()=>y,ancestorScroll:!1,onUpdate:E}),O=t=>{y!==t&&(t&&(x=document.activeElement),y=t,(0,e.setAria)(a,`expanded`,y),(0,e.emit)(r,`popover:change`,{open:y}),l?.(y),t?(o.hidden=!1,r.setAttribute(`data-state`,`open`),o.setAttribute(`data-state`,`open`),E(),D.start(),D.update(),requestAnimationFrame(w)):(D.stop(),o.hidden=!0,r.setAttribute(`data-state`,`closed`),o.setAttribute(`data-state`,`closed`),C(),requestAnimationFrame(()=>{x&&x.isConnected?x.focus():a.focus(),x=null})))};return(0,e.setAria)(a,`expanded`,y),o.hidden=!y,r.setAttribute(`data-state`,y?`open`:`closed`),o.setAttribute(`data-state`,y?`open`:`closed`),c&&(E(),D.start(),D.update(),requestAnimationFrame(w)),b.push((0,e.on)(a,`click`,()=>O(!y))),s&&b.push((0,e.on)(s,`click`,()=>O(!1))),b.push((0,e.createDismissLayer)({root:r,isOpen:()=>y,onDismiss:()=>O(!1),closeOnClickOutside:u,closeOnEscape:d})),b.push((0,e.on)(r,`popover:set`,e=>{let t=e.detail,n;t?.open===void 0?t?.value!==void 0&&(n=t.value):n=t.open,typeof n==`boolean`&&O(n)})),{open:()=>O(!0),close:()=>O(!1),toggle:()=>O(!y),get isOpen(){return y},destroy:()=>{D.stop(),b.forEach(e=>e()),b.length=0,C()}}}const i=new WeakSet;function a(t=document){let n=[];for(let a of(0,e.getRoots)(t,`popover`))i.has(a)||(i.add(a),n.push(r(a)));return n}exports.create=a,exports.createPopover=r;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`@data-slot/core`);const t=[`top`,`right`,`bottom`,`left`],n=[`start`,`center`,`end`];function r(r,i={}){let a=(0,e.getPart)(r,`popover-trigger`),o=(0,e.getPart)(r,`popover-content`),s=(0,e.getPart)(r,`popover-close`);if(!a||!o)throw Error(`Popover requires trigger and content slots`);let c=i.defaultOpen??(0,e.getDataBool)(r,`defaultOpen`)??!1,l=i.onOpenChange,u=i.closeOnClickOutside??(0,e.getDataBool)(r,`closeOnClickOutside`)??!0,d=i.closeOnEscape??(0,e.getDataBool)(r,`closeOnEscape`)??!0,f=i.portal??(0,e.getDataBool)(o,`portal`)??(0,e.getDataBool)(r,`portal`)??!0,p=i.position??(0,e.getDataEnum)(o,`position`,t)??(0,e.getDataEnum)(r,`position`,t),m=i.side??(0,e.getDataEnum)(o,`side`,t)??(0,e.getDataEnum)(r,`side`,t)??p??`bottom`,h=i.align??(0,e.getDataEnum)(o,`align`,n)??(0,e.getDataEnum)(r,`align`,n)??`center`,g=i.sideOffset??(0,e.getDataNumber)(o,`sideOffset`)??(0,e.getDataNumber)(r,`sideOffset`)??4,_=i.alignOffset??(0,e.getDataNumber)(o,`alignOffset`)??(0,e.getDataNumber)(r,`alignOffset`)??0,v=i.avoidCollisions??(0,e.getDataBool)(o,`avoidCollisions`)??(0,e.getDataBool)(r,`avoidCollisions`)??!0,y=i.collisionPadding??(0,e.getDataNumber)(o,`collisionPadding`)??(0,e.getDataNumber)(r,`collisionPadding`)??8,b=c,x=[],S=(0,e.createPortalLifecycle)({content:o,root:r,enabled:f,wrapperSlot:`popover-positioner`}),C=!1,w=null,T=!1,E=()=>{T&&=(o.removeAttribute(`tabindex`),!1)},D=()=>{let e=o.querySelector(`[autofocus]`);if(e)return e.focus();let t=o.querySelector(`a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])`);if(t)return t.focus();o.getAttribute(`tabindex`)||(o.setAttribute(`tabindex`,`-1`),T=!0),o.focus()},O=(0,e.ensureId)(o,`popover-content`);a.setAttribute(`aria-haspopup`,`dialog`),a.setAttribute(`aria-controls`,O),o.setAttribute(`data-side`,m),o.setAttribute(`data-align`,h),o.setAttribute(`data-position`,m);let k=()=>{let t=S.container,n=r.ownerDocument.defaultView??window,i=(0,e.computeFloatingPosition)({anchorRect:a.getBoundingClientRect(),contentRect:o.getBoundingClientRect(),side:m,align:h,sideOffset:g,alignOffset:_,avoidCollisions:v,collisionPadding:y});t.style.position=`absolute`,t.style.top=`0px`,t.style.left=`0px`,t.style.transform=`translate3d(${i.x+n.scrollX}px, ${i.y+n.scrollY}px, 0)`,t.style.willChange=`transform`,t.style.margin=`0`,o.setAttribute(`data-side`,i.side),o.setAttribute(`data-align`,i.align),t!==o&&(t.setAttribute(`data-side`,i.side),t.setAttribute(`data-align`,i.align)),o.setAttribute(`data-position`,i.side)},A=e=>{let t=S.container;r.setAttribute(`data-state`,e),o.setAttribute(`data-state`,e),t!==o&&t.setAttribute(`data-state`,e),e===`open`?(r.setAttribute(`data-open`,``),o.setAttribute(`data-open`,``),t!==o&&t.setAttribute(`data-open`,``),r.removeAttribute(`data-closed`),o.removeAttribute(`data-closed`),t!==o&&t.removeAttribute(`data-closed`)):(r.setAttribute(`data-closed`,``),o.setAttribute(`data-closed`,``),t!==o&&t.setAttribute(`data-closed`,``),r.removeAttribute(`data-open`),o.removeAttribute(`data-open`),t!==o&&t.removeAttribute(`data-open`))},j=()=>{requestAnimationFrame(()=>{w&&w.isConnected?w.focus():a.focus(),w=null})},M=(0,e.createPresenceLifecycle)({element:o,onExitComplete:()=>{C||(S.restore(),o.hidden=!0,E(),j())}}),N=(0,e.createPositionSync)({observedElements:[a,o],isActive:()=>b,ancestorScroll:!1,onUpdate:k}),P=t=>{b!==t&&(t&&(w=document.activeElement),b=t,(0,e.setAria)(a,`expanded`,b),t?(S.mount(),o.hidden=!1,A(`open`),M.enter(),k(),N.start(),N.update(),requestAnimationFrame(D)):(A(`closed`),M.exit(),N.stop()),(0,e.emit)(r,`popover:change`,{open:b}),l?.(b))};return(0,e.setAria)(a,`expanded`,b),A(b?`open`:`closed`),o.hidden=!b,c&&(S.mount(),M.enter(),o.hidden=!1,k(),N.start(),N.update(),requestAnimationFrame(D)),x.push((0,e.on)(a,`click`,()=>P(!b))),s&&x.push((0,e.on)(s,`click`,()=>P(!1))),x.push((0,e.createDismissLayer)({root:r,isOpen:()=>b,onDismiss:()=>P(!1),closeOnClickOutside:u,closeOnEscape:d})),x.push((0,e.on)(r,`popover:set`,e=>{let t=e.detail,n;t?.open===void 0?t?.value!==void 0&&(n=t.value):n=t.open,typeof n==`boolean`&&P(n)})),{open:()=>P(!0),close:()=>P(!1),toggle:()=>P(!b),get isOpen(){return b},destroy:()=>{C=!0,N.stop(),M.cleanup(),S.cleanup(),x.forEach(e=>e()),x.length=0,E()}}}const i=new WeakSet;function a(t=document){let n=[];for(let a of(0,e.getRoots)(t,`popover`))i.has(a)||(i.add(a),n.push(r(a)));return n}exports.create=a,exports.createPopover=r;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{computeFloatingPosition as e,createDismissLayer as t,createPositionSync as n,emit as r,ensureId as i,getDataBool as a,getDataEnum as o,getDataNumber as s,getPart as c,getRoots as l,on as u,setAria as d}from"@data-slot/core";const f=[`top`,`right`,`bottom`,`left`],p=[`start`,`center`,`end`];function m(l,m={}){let h=c(l,`popover-trigger`),g=c(l,`popover-content`),_=c(l,`popover-close`);if(!h||!g)throw Error(`Popover requires trigger and content slots`);let v=m.defaultOpen??a(l,`defaultOpen`)??!1,y=m.onOpenChange,b=m.closeOnClickOutside??a(l,`closeOnClickOutside`)??!0,x=m.closeOnEscape??a(l,`closeOnEscape`)??!0,S=m.position??o(g,`position`,f)??o(l,`position`,f),C=m.side??o(g,`side`,f)??o(l,`side`,f)??S??`bottom`,w=m.align??o(g,`align`,p)??o(l,`align`,p)??`center`,T=m.sideOffset??s(g,`sideOffset`)??s(l,`sideOffset`)??4,E=m.alignOffset??s(g,`alignOffset`)??s(l,`alignOffset`)??0,D=m.avoidCollisions??a(g,`avoidCollisions`)??a(l,`avoidCollisions`)??!0,O=m.collisionPadding??s(g,`collisionPadding`)??s(l,`collisionPadding`)??8,k=v,A=[],j=null,M=!1,N=()=>{M&&=(g.removeAttribute(`tabindex`),!1)},P=()=>{let e=g.querySelector(`[autofocus]`);if(e)return e.focus();let t=g.querySelector(`a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])`);if(t)return t.focus();g.getAttribute(`tabindex`)||(g.setAttribute(`tabindex`,`-1`),M=!0),g.focus()},F=i(g,`popover-content`);h.setAttribute(`aria-haspopup`,`dialog`),h.setAttribute(`aria-controls`,F),g.setAttribute(`data-side`,C),g.setAttribute(`data-align`,w),g.setAttribute(`data-position`,C);let I=()=>{let t=l.ownerDocument.defaultView??window,n=e({anchorRect:h.getBoundingClientRect(),contentRect:g.getBoundingClientRect(),side:C,align:w,sideOffset:T,alignOffset:E,avoidCollisions:D,collisionPadding:O});g.style.position=`absolute`,g.style.top=`${n.y+t.scrollY}px`,g.style.left=`${n.x+t.scrollX}px`,g.style.margin=`0`,g.setAttribute(`data-side`,n.side),g.setAttribute(`data-align`,n.align),g.setAttribute(`data-position`,n.side)},L=n({observedElements:[h,g],isActive:()=>k,ancestorScroll:!1,onUpdate:I}),R=e=>{k!==e&&(e&&(j=document.activeElement),k=e,d(h,`expanded`,k),r(l,`popover:change`,{open:k}),y?.(k),e?(g.hidden=!1,l.setAttribute(`data-state`,`open`),g.setAttribute(`data-state`,`open`),I(),L.start(),L.update(),requestAnimationFrame(P)):(L.stop(),g.hidden=!0,l.setAttribute(`data-state`,`closed`),g.setAttribute(`data-state`,`closed`),N(),requestAnimationFrame(()=>{j&&j.isConnected?j.focus():h.focus(),j=null})))};return d(h,`expanded`,k),g.hidden=!k,l.setAttribute(`data-state`,k?`open`:`closed`),g.setAttribute(`data-state`,k?`open`:`closed`),v&&(I(),L.start(),L.update(),requestAnimationFrame(P)),A.push(u(h,`click`,()=>R(!k))),_&&A.push(u(_,`click`,()=>R(!1))),A.push(t({root:l,isOpen:()=>k,onDismiss:()=>R(!1),closeOnClickOutside:b,closeOnEscape:x})),A.push(u(l,`popover:set`,e=>{let t=e.detail,n;t?.open===void 0?t?.value!==void 0&&(n=t.value):n=t.open,typeof n==`boolean`&&R(n)})),{open:()=>R(!0),close:()=>R(!1),toggle:()=>R(!k),get isOpen(){return k},destroy:()=>{L.stop(),A.forEach(e=>e()),A.length=0,N()}}}const h=new WeakSet;function g(e=document){let t=[];for(let n of l(e,`popover`))h.has(n)||(h.add(n),t.push(m(n)));return t}export{g as create,m as createPopover};
1
+ import{computeFloatingPosition as e,createDismissLayer as t,createPortalLifecycle as n,createPositionSync as r,createPresenceLifecycle as i,emit as a,ensureId as o,getDataBool as s,getDataEnum as c,getDataNumber as l,getPart as u,getRoots as d,on as f,setAria as p}from"@data-slot/core";const m=[`top`,`right`,`bottom`,`left`],h=[`start`,`center`,`end`];function g(d,g={}){let _=u(d,`popover-trigger`),v=u(d,`popover-content`),y=u(d,`popover-close`);if(!_||!v)throw Error(`Popover requires trigger and content slots`);let b=g.defaultOpen??s(d,`defaultOpen`)??!1,x=g.onOpenChange,S=g.closeOnClickOutside??s(d,`closeOnClickOutside`)??!0,C=g.closeOnEscape??s(d,`closeOnEscape`)??!0,w=g.portal??s(v,`portal`)??s(d,`portal`)??!0,T=g.position??c(v,`position`,m)??c(d,`position`,m),E=g.side??c(v,`side`,m)??c(d,`side`,m)??T??`bottom`,D=g.align??c(v,`align`,h)??c(d,`align`,h)??`center`,O=g.sideOffset??l(v,`sideOffset`)??l(d,`sideOffset`)??4,k=g.alignOffset??l(v,`alignOffset`)??l(d,`alignOffset`)??0,A=g.avoidCollisions??s(v,`avoidCollisions`)??s(d,`avoidCollisions`)??!0,j=g.collisionPadding??l(v,`collisionPadding`)??l(d,`collisionPadding`)??8,M=b,N=[],P=n({content:v,root:d,enabled:w,wrapperSlot:`popover-positioner`}),F=!1,I=null,L=!1,R=()=>{L&&=(v.removeAttribute(`tabindex`),!1)},z=()=>{let e=v.querySelector(`[autofocus]`);if(e)return e.focus();let t=v.querySelector(`a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])`);if(t)return t.focus();v.getAttribute(`tabindex`)||(v.setAttribute(`tabindex`,`-1`),L=!0),v.focus()},B=o(v,`popover-content`);_.setAttribute(`aria-haspopup`,`dialog`),_.setAttribute(`aria-controls`,B),v.setAttribute(`data-side`,E),v.setAttribute(`data-align`,D),v.setAttribute(`data-position`,E);let V=()=>{let t=P.container,n=d.ownerDocument.defaultView??window,r=e({anchorRect:_.getBoundingClientRect(),contentRect:v.getBoundingClientRect(),side:E,align:D,sideOffset:O,alignOffset:k,avoidCollisions:A,collisionPadding:j});t.style.position=`absolute`,t.style.top=`0px`,t.style.left=`0px`,t.style.transform=`translate3d(${r.x+n.scrollX}px, ${r.y+n.scrollY}px, 0)`,t.style.willChange=`transform`,t.style.margin=`0`,v.setAttribute(`data-side`,r.side),v.setAttribute(`data-align`,r.align),t!==v&&(t.setAttribute(`data-side`,r.side),t.setAttribute(`data-align`,r.align)),v.setAttribute(`data-position`,r.side)},H=e=>{let t=P.container;d.setAttribute(`data-state`,e),v.setAttribute(`data-state`,e),t!==v&&t.setAttribute(`data-state`,e),e===`open`?(d.setAttribute(`data-open`,``),v.setAttribute(`data-open`,``),t!==v&&t.setAttribute(`data-open`,``),d.removeAttribute(`data-closed`),v.removeAttribute(`data-closed`),t!==v&&t.removeAttribute(`data-closed`)):(d.setAttribute(`data-closed`,``),v.setAttribute(`data-closed`,``),t!==v&&t.setAttribute(`data-closed`,``),d.removeAttribute(`data-open`),v.removeAttribute(`data-open`),t!==v&&t.removeAttribute(`data-open`))},U=()=>{requestAnimationFrame(()=>{I&&I.isConnected?I.focus():_.focus(),I=null})},W=i({element:v,onExitComplete:()=>{F||(P.restore(),v.hidden=!0,R(),U())}}),G=r({observedElements:[_,v],isActive:()=>M,ancestorScroll:!1,onUpdate:V}),K=e=>{M!==e&&(e&&(I=document.activeElement),M=e,p(_,`expanded`,M),e?(P.mount(),v.hidden=!1,H(`open`),W.enter(),V(),G.start(),G.update(),requestAnimationFrame(z)):(H(`closed`),W.exit(),G.stop()),a(d,`popover:change`,{open:M}),x?.(M))};return p(_,`expanded`,M),H(M?`open`:`closed`),v.hidden=!M,b&&(P.mount(),W.enter(),v.hidden=!1,V(),G.start(),G.update(),requestAnimationFrame(z)),N.push(f(_,`click`,()=>K(!M))),y&&N.push(f(y,`click`,()=>K(!1))),N.push(t({root:d,isOpen:()=>M,onDismiss:()=>K(!1),closeOnClickOutside:S,closeOnEscape:C})),N.push(f(d,`popover:set`,e=>{let t=e.detail,n;t?.open===void 0?t?.value!==void 0&&(n=t.value):n=t.open,typeof n==`boolean`&&K(n)})),{open:()=>K(!0),close:()=>K(!1),toggle:()=>K(!M),get isOpen(){return M},destroy:()=>{F=!0,G.stop(),W.cleanup(),P.cleanup(),N.forEach(e=>e()),N.length=0,R()}}}const _=new WeakSet;function v(e=document){let t=[];for(let n of d(e,`popover`))_.has(n)||(_.add(n),t.push(g(n)));return t}export{v as create,g as createPopover};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@data-slot/popover",
3
- "version": "0.2.41",
3
+ "version": "0.2.43",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.cjs",
@@ -38,6 +38,6 @@
38
38
  ],
39
39
  "license": "MIT",
40
40
  "dependencies": {
41
- "@data-slot/core": "0.2.41"
41
+ "@data-slot/core": "0.2.43"
42
42
  }
43
43
  }