@data-slot/popover 0.2.4 → 0.2.5

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
@@ -97,12 +97,29 @@ const popover = createPopover(element, {
97
97
 
98
98
  ### Data Attributes
99
99
 
100
- Set position via HTML:
100
+ Options can also be set via data attributes on the root element. JS options take precedence over data attributes.
101
+
102
+ | Attribute | Type | Default | Description |
103
+ |-----------|------|---------|-------------|
104
+ | `data-default-open` | boolean | `false` | Initial open state |
105
+ | `data-close-on-click-outside` | boolean | `true` | Close when clicking outside |
106
+ | `data-close-on-escape` | boolean | `true` | Close when pressing Escape |
107
+
108
+ Boolean attributes: present or `"true"` = true, `"false"` = false, absent = default.
109
+
110
+ Position is set via `data-position` on the content element:
101
111
 
102
112
  ```html
103
113
  <div data-slot="popover-content" data-position="top">
104
114
  ```
105
115
 
116
+ ```html
117
+ <!-- Popover that stays open when clicking outside -->
118
+ <div data-slot="popover" data-close-on-click-outside="false">
119
+ ...
120
+ </div>
121
+ ```
122
+
106
123
  ## Styling
107
124
 
108
125
  Use `data-state` and `data-position` attributes:
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- const e=(e,t)=>e.querySelector(`[data-slot="${t}"]`),t=(e,t)=>[...e.querySelectorAll(`[data-slot="${t}"]`)];let n=0;const r=(e,t)=>e.id||=`${t}-${++n}`,i=(e,t,n)=>{n===null?e.removeAttribute(`aria-${t}`):e.setAttribute(`aria-${t}`,String(n))};function a(e,t,n,r){return e.addEventListener(t,n,r),()=>e.removeEventListener(t,n,r)}const o=(e,t,n)=>e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:n}));function s(t,n={}){let{defaultOpen:s=!1,onOpenChange:c,closeOnClickOutside:l=!0,closeOnEscape:u=!0}=n,d=e(t,`popover-trigger`),f=e(t,`popover-content`),p=e(t,`popover-close`);if(!d||!f)throw Error(`Popover requires trigger and content slots`);let m=n.position??f.dataset.position??`bottom`,h=s,g=[],_=r(f,`popover-content`);d.setAttribute(`aria-haspopup`,`dialog`),d.setAttribute(`aria-controls`,_),f.setAttribute(`data-position`,m);let v=e=>{h!==e&&(h=e,i(d,`expanded`,h),f.hidden=!h,t.setAttribute(`data-state`,h?`open`:`closed`),o(t,`popover:change`,{open:h}),c?.(h))};i(d,`expanded`,h),f.hidden=!h,t.setAttribute(`data-state`,h?`open`:`closed`),g.push(a(d,`click`,()=>v(!h))),p&&g.push(a(p,`click`,()=>v(!1))),l&&g.push(a(document,`pointerdown`,e=>{if(!h)return;let n=e.target;t.contains(n)||v(!1)})),u&&g.push(a(document,`keydown`,e=>{h&&e.key===`Escape`&&(e.preventDefault(),v(!1),d.focus())}));let y={open:()=>v(!0),close:()=>v(!1),toggle:()=>v(!h),get isOpen(){return h},destroy:()=>{g.forEach(e=>e()),g.length=0}};return y}const c=new WeakSet;function l(e=document){let n=[];for(let r of t(e,`popover`)){if(c.has(r))continue;c.add(r),n.push(s(r))}return n}exports.create=l,exports.createPopover=s;
1
+ const e=(e,t)=>e.querySelector(`[data-slot="${t}"]`),t=(e,t)=>[...e.querySelectorAll(`[data-slot="${t}"]`)],n=new WeakMap;function r(e,t,r){if(typeof process<`u`&&process.env?.NODE_ENV===`production`)return;let i=n.get(e);i||(i=new Set,n.set(e,i)),!i.has(t)&&(i.add(t),console.warn(`[@data-slot] ${r}`))}function i(e){let t=`data-${e.replace(/([A-Z])/g,`-$1`).toLowerCase()}`,n=`data-${e}`;return t===n?[t]:[t,n]}function a(e,t){for(let n of i(t))if(e.hasAttribute(n))return e.getAttribute(n);return null}function o(e,t){return i(t).some(t=>e.hasAttribute(t))}const s=new Set([``,`true`,`1`,`yes`]),c=new Set([`false`,`0`,`no`]);function l(e,t){if(!o(e,t))return;let n=a(e,t);if(n===null)return;let i=n.toLowerCase();if(s.has(i))return!0;if(c.has(i))return!1;r(e,t,`Invalid boolean value "${n}" for data-${t}. Expected: true/false/1/0/yes/no or empty.`)}function u(e,t,n){let i=a(e,t);if(i!==null){if(n.includes(i))return i;r(e,t,`Invalid value "${i}" for data-${t}. Expected one of: ${n.join(`, `)}.`)}}let d=0;const f=(e,t)=>e.id||=`${t}-${++d}`,p=(e,t,n)=>{n===null?e.removeAttribute(`aria-${t}`):e.setAttribute(`aria-${t}`,String(n))};function m(e,t,n,r){return e.addEventListener(t,n,r),()=>e.removeEventListener(t,n,r)}const h=(e,t,n)=>e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:n})),g=[`top`,`bottom`,`left`,`right`];function _(t,n={}){let r=e(t,`popover-trigger`),i=e(t,`popover-content`),a=e(t,`popover-close`);if(!r||!i)throw Error(`Popover requires trigger and content slots`);let o=n.defaultOpen??l(t,`defaultOpen`)??!1,s=n.onOpenChange,c=n.closeOnClickOutside??l(t,`closeOnClickOutside`)??!0,d=n.closeOnEscape??l(t,`closeOnEscape`)??!0,_=n.position??u(i,`position`,g)??u(t,`position`,g)??`bottom`,v=o,y=[],b=f(i,`popover-content`);r.setAttribute(`aria-haspopup`,`dialog`),r.setAttribute(`aria-controls`,b),i.setAttribute(`data-position`,_);let x=e=>{v!==e&&(v=e,p(r,`expanded`,v),i.hidden=!v,t.setAttribute(`data-state`,v?`open`:`closed`),h(t,`popover:change`,{open:v}),s?.(v))};p(r,`expanded`,v),i.hidden=!v,t.setAttribute(`data-state`,v?`open`:`closed`),y.push(m(r,`click`,()=>x(!v))),a&&y.push(m(a,`click`,()=>x(!1))),c&&y.push(m(document,`pointerdown`,e=>{if(!v)return;let n=e.target;t.contains(n)||x(!1)})),d&&y.push(m(document,`keydown`,e=>{v&&e.key===`Escape`&&(e.preventDefault(),x(!1),r.focus())}));let S={open:()=>x(!0),close:()=>x(!1),toggle:()=>x(!v),get isOpen(){return v},destroy:()=>{y.forEach(e=>e()),y.length=0}};return S}const v=new WeakSet;function y(e=document){let n=[];for(let r of t(e,`popover`)){if(v.has(r))continue;v.add(r),n.push(_(r))}return n}exports.create=y,exports.createPopover=_;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- const e=(e,t)=>e.querySelector(`[data-slot="${t}"]`),t=(e,t)=>[...e.querySelectorAll(`[data-slot="${t}"]`)];let n=0;const r=(e,t)=>e.id||=`${t}-${++n}`,i=(e,t,n)=>{n===null?e.removeAttribute(`aria-${t}`):e.setAttribute(`aria-${t}`,String(n))};function a(e,t,n,r){return e.addEventListener(t,n,r),()=>e.removeEventListener(t,n,r)}const o=(e,t,n)=>e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:n}));function s(t,n={}){let{defaultOpen:s=!1,onOpenChange:c,closeOnClickOutside:l=!0,closeOnEscape:u=!0}=n,d=e(t,`popover-trigger`),f=e(t,`popover-content`),p=e(t,`popover-close`);if(!d||!f)throw Error(`Popover requires trigger and content slots`);let m=n.position??f.dataset.position??`bottom`,h=s,g=[],_=r(f,`popover-content`);d.setAttribute(`aria-haspopup`,`dialog`),d.setAttribute(`aria-controls`,_),f.setAttribute(`data-position`,m);let v=e=>{h!==e&&(h=e,i(d,`expanded`,h),f.hidden=!h,t.setAttribute(`data-state`,h?`open`:`closed`),o(t,`popover:change`,{open:h}),c?.(h))};i(d,`expanded`,h),f.hidden=!h,t.setAttribute(`data-state`,h?`open`:`closed`),g.push(a(d,`click`,()=>v(!h))),p&&g.push(a(p,`click`,()=>v(!1))),l&&g.push(a(document,`pointerdown`,e=>{if(!h)return;let n=e.target;t.contains(n)||v(!1)})),u&&g.push(a(document,`keydown`,e=>{h&&e.key===`Escape`&&(e.preventDefault(),v(!1),d.focus())}));let y={open:()=>v(!0),close:()=>v(!1),toggle:()=>v(!h),get isOpen(){return h},destroy:()=>{g.forEach(e=>e()),g.length=0}};return y}const c=new WeakSet;function l(e=document){let n=[];for(let r of t(e,`popover`)){if(c.has(r))continue;c.add(r),n.push(s(r))}return n}export{l as create,s as createPopover};
1
+ const e=(e,t)=>e.querySelector(`[data-slot="${t}"]`),t=(e,t)=>[...e.querySelectorAll(`[data-slot="${t}"]`)],n=new WeakMap;function r(e,t,r){if(typeof process<`u`&&process.env?.NODE_ENV===`production`)return;let i=n.get(e);i||(i=new Set,n.set(e,i)),!i.has(t)&&(i.add(t),console.warn(`[@data-slot] ${r}`))}function i(e){let t=`data-${e.replace(/([A-Z])/g,`-$1`).toLowerCase()}`,n=`data-${e}`;return t===n?[t]:[t,n]}function a(e,t){for(let n of i(t))if(e.hasAttribute(n))return e.getAttribute(n);return null}function o(e,t){return i(t).some(t=>e.hasAttribute(t))}const s=new Set([``,`true`,`1`,`yes`]),c=new Set([`false`,`0`,`no`]);function l(e,t){if(!o(e,t))return;let n=a(e,t);if(n===null)return;let i=n.toLowerCase();if(s.has(i))return!0;if(c.has(i))return!1;r(e,t,`Invalid boolean value "${n}" for data-${t}. Expected: true/false/1/0/yes/no or empty.`)}function u(e,t,n){let i=a(e,t);if(i!==null){if(n.includes(i))return i;r(e,t,`Invalid value "${i}" for data-${t}. Expected one of: ${n.join(`, `)}.`)}}let d=0;const f=(e,t)=>e.id||=`${t}-${++d}`,p=(e,t,n)=>{n===null?e.removeAttribute(`aria-${t}`):e.setAttribute(`aria-${t}`,String(n))};function m(e,t,n,r){return e.addEventListener(t,n,r),()=>e.removeEventListener(t,n,r)}const h=(e,t,n)=>e.dispatchEvent(new CustomEvent(t,{bubbles:!0,detail:n})),g=[`top`,`bottom`,`left`,`right`];function _(t,n={}){let r=e(t,`popover-trigger`),i=e(t,`popover-content`),a=e(t,`popover-close`);if(!r||!i)throw Error(`Popover requires trigger and content slots`);let o=n.defaultOpen??l(t,`defaultOpen`)??!1,s=n.onOpenChange,c=n.closeOnClickOutside??l(t,`closeOnClickOutside`)??!0,d=n.closeOnEscape??l(t,`closeOnEscape`)??!0,_=n.position??u(i,`position`,g)??u(t,`position`,g)??`bottom`,v=o,y=[],b=f(i,`popover-content`);r.setAttribute(`aria-haspopup`,`dialog`),r.setAttribute(`aria-controls`,b),i.setAttribute(`data-position`,_);let x=e=>{v!==e&&(v=e,p(r,`expanded`,v),i.hidden=!v,t.setAttribute(`data-state`,v?`open`:`closed`),h(t,`popover:change`,{open:v}),s?.(v))};p(r,`expanded`,v),i.hidden=!v,t.setAttribute(`data-state`,v?`open`:`closed`),y.push(m(r,`click`,()=>x(!v))),a&&y.push(m(a,`click`,()=>x(!1))),c&&y.push(m(document,`pointerdown`,e=>{if(!v)return;let n=e.target;t.contains(n)||x(!1)})),d&&y.push(m(document,`keydown`,e=>{v&&e.key===`Escape`&&(e.preventDefault(),x(!1),r.focus())}));let S={open:()=>x(!0),close:()=>x(!1),toggle:()=>x(!v),get isOpen(){return v},destroy:()=>{y.forEach(e=>e()),y.length=0}};return S}const v=new WeakSet;function y(e=document){let n=[];for(let r of t(e,`popover`)){if(v.has(r))continue;v.add(r),n.push(_(r))}return n}export{y as create,_ as createPopover};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@data-slot/popover",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.cjs",