@oddbird/popover-polyfill
Advanced tools
Comparing version 0.0.4 to 0.0.5
@@ -0,1 +1,66 @@ | ||
// src/observer.ts | ||
var popovers = /* @__PURE__ */ new Set(); | ||
var popoversSyncFactory = (method) => (node) => { | ||
if (node instanceof HTMLElement) { | ||
if (node.hasAttribute("popover")) { | ||
method(node); | ||
} | ||
node.querySelectorAll("[popover]").forEach((popover) => { | ||
if (popover instanceof HTMLElement) { | ||
method(popover); | ||
} | ||
}); | ||
} | ||
}; | ||
var nodeAddedCallback = popoversSyncFactory(popovers.add.bind(popovers)); | ||
var nodeRemovedCallback = popoversSyncFactory(popovers.delete.bind(popovers)); | ||
var handleChildListMutation = (mutation) => { | ||
if (mutation.addedNodes.length > 0) { | ||
mutation.addedNodes.forEach(nodeAddedCallback); | ||
} | ||
if (mutation.removedNodes.length > 0) { | ||
mutation.removedNodes.forEach(nodeRemovedCallback); | ||
} | ||
}; | ||
var handlePopoverAttributeMutation = (mutation) => { | ||
if (mutation.target instanceof HTMLElement) { | ||
if (mutation.target.hasAttribute("popover")) { | ||
popovers.add(mutation.target); | ||
} else { | ||
popovers.delete(mutation.target); | ||
} | ||
} | ||
}; | ||
var handleMutation = (mutationList) => { | ||
mutationList.forEach((mutation) => { | ||
switch (mutation.type) { | ||
case "attributes": | ||
switch (mutation.attributeName) { | ||
case "popover": | ||
handlePopoverAttributeMutation(mutation); | ||
break; | ||
} | ||
break; | ||
case "childList": | ||
handleChildListMutation(mutation); | ||
break; | ||
} | ||
}); | ||
}; | ||
var observer = new MutationObserver(handleMutation); | ||
var observePopoversMutations = (root) => { | ||
if (root === document) { | ||
root.querySelectorAll("[popover]").forEach((popover) => { | ||
if (popover instanceof HTMLElement) { | ||
popovers.add(popover); | ||
} | ||
}); | ||
} | ||
observer.observe(root, { | ||
attributeFilter: ["popover"], | ||
childList: true, | ||
subtree: true | ||
}); | ||
}; | ||
// src/popover.ts | ||
@@ -6,2 +71,21 @@ function isSupported() { | ||
var notSupportedMessage = "Not supported on element that does not have valid popover attribute"; | ||
function patchAttachShadow(callback) { | ||
const originalAttachShadow = Element.prototype.attachShadow; | ||
Element.prototype.attachShadow = function(init) { | ||
const shadowRoot = originalAttachShadow.call(this, init); | ||
callback(shadowRoot); | ||
return shadowRoot; | ||
}; | ||
} | ||
var closestElement = (selector, target) => { | ||
const found = target.closest(selector); | ||
if (found) { | ||
return found; | ||
} | ||
const root = target.getRootNode(); | ||
if (root === document || !(root instanceof ShadowRoot)) { | ||
return null; | ||
} | ||
return closestElement(selector, root.host); | ||
}; | ||
function apply() { | ||
@@ -60,8 +144,15 @@ const visibleElements = /* @__PURE__ */ new WeakSet(); | ||
}); | ||
document.addEventListener("click", (event) => { | ||
const onClick = (event) => { | ||
const target = event.target; | ||
if (!(target instanceof Element)) | ||
return; | ||
const doc = target.ownerDocument; | ||
let effectedPopover = target.closest("[popover]"); | ||
const root = target.getRootNode(); | ||
if (root instanceof ShadowRoot) { | ||
event.stopPropagation(); | ||
} else if (!(root instanceof Document)) | ||
return; | ||
let effectedPopover = closestElement( | ||
"[popover]", | ||
target | ||
); | ||
const button = target.closest( | ||
@@ -72,3 +163,3 @@ "[popovertoggletarget],[popoverhidetarget],[popovershowtarget]" | ||
if (isButton && button.hasAttribute("popovershowtarget")) { | ||
effectedPopover = doc.getElementById( | ||
effectedPopover = root.getElementById( | ||
button.getAttribute("popovershowtarget") || "" | ||
@@ -80,3 +171,3 @@ ); | ||
} else if (isButton && button.hasAttribute("popoverhidetarget")) { | ||
effectedPopover = doc.getElementById( | ||
effectedPopover = root.getElementById( | ||
button.getAttribute("popoverhidetarget") || "" | ||
@@ -88,3 +179,3 @@ ); | ||
} else if (isButton && button.hasAttribute("popovertoggletarget")) { | ||
effectedPopover = doc.getElementById( | ||
effectedPopover = root.getElementById( | ||
button.getAttribute("popovertoggletarget") || "" | ||
@@ -100,9 +191,14 @@ ); | ||
} | ||
for (const popover of doc.querySelectorAll( | ||
'[popover="" i].\\:open, [popover=auto i].\\:open' | ||
)) { | ||
if (popover instanceof HTMLElement && popover !== effectedPopover) | ||
for (const popover of [...popovers]) { | ||
if (popover.matches('[popover="" i].\\:open, [popover=auto i].\\:open') && popover !== effectedPopover) | ||
popover.hidePopover(); | ||
} | ||
}); | ||
}; | ||
const addOnClickEventListener = ((callback) => (root) => { | ||
root.addEventListener("click", callback); | ||
})(onClick); | ||
observePopoversMutations(document); | ||
addOnClickEventListener(document); | ||
patchAttachShadow(observePopoversMutations); | ||
patchAttachShadow(addOnClickEventListener); | ||
} | ||
@@ -109,0 +205,0 @@ export { |
@@ -1,2 +0,2 @@ | ||
"use strict";(()=>{function l(){return typeof HTMLElement<"u"&&typeof HTMLElement.prototype=="object"&&"popover"in HTMLElement.prototype}var a="Not supported on element that does not have valid popover attribute";function u(){let o=new WeakSet;Object.defineProperties(HTMLElement.prototype,{popover:{enumerable:!0,configurable:!0,get(){let t=(this.getAttribute("popover")||"").toLowerCase();return t==="manual"?"manual":t===""||t=="auto"?"auto":null},set(t){this.setAttribute("popover",t)}},showPopover:{enumerable:!0,configurable:!0,value(){if(!this.popover)throw new DOMException(a,"NotSupportedError");if(o.has(this))throw new DOMException("Invalid on already-showing Popovers","InvalidStateError");this.classList.add(":open"),o.add(this),this.popover==="auto"&&(this.hasAttribute("autofocus")?this:this.querySelector("[autofocus]"))?.focus()}},hidePopover:{enumerable:!0,configurable:!0,value(){if(!this.popover)throw new DOMException(a,"NotSupportedError");if(!o.has(this))throw new DOMException("Invalid on already-hidden Popovers","InvalidStateError");this.classList.remove(":open"),o.delete(this)}}}),document.addEventListener("click",t=>{let p=t.target;if(!(p instanceof Element))return;let n=p.ownerDocument,e=p.closest("[popover]"),r=p.closest("[popovertoggletarget],[popoverhidetarget],[popovershowtarget]"),i=r instanceof HTMLButtonElement;i&&r.hasAttribute("popovershowtarget")?(e=n.getElementById(r.getAttribute("popovershowtarget")||""),e&&e.popover&&!o.has(e)&&e.showPopover()):i&&r.hasAttribute("popoverhidetarget")?(e=n.getElementById(r.getAttribute("popoverhidetarget")||""),e&&e.popover&&o.has(e)&&e.hidePopover()):i&&r.hasAttribute("popovertoggletarget")&&(e=n.getElementById(r.getAttribute("popovertoggletarget")||""),e&&e.popover&&(o.has(e)?e.hidePopover():e.showPopover()));for(let s of n.querySelectorAll('[popover="" i].\\:open, [popover=auto i].\\:open'))s instanceof HTMLElement&&s!==e&&s.hidePopover()})}l()||u();})(); | ||
"use strict";(()=>{var s=new Set,u=e=>t=>{t instanceof HTMLElement&&(t.hasAttribute("popover")&&e(t),t.querySelectorAll("[popover]").forEach(n=>{n instanceof HTMLElement&&e(n)}))},b=u(s.add.bind(s)),m=u(s.delete.bind(s)),w=e=>{e.addedNodes.length>0&&e.addedNodes.forEach(b),e.removedNodes.length>0&&e.removedNodes.forEach(m)},M=e=>{e.target instanceof HTMLElement&&(e.target.hasAttribute("popover")?s.add(e.target):s.delete(e.target))},L=e=>{e.forEach(t=>{switch(t.type){case"attributes":switch(t.attributeName){case"popover":M(t);break}break;case"childList":w(t);break}})},S=new MutationObserver(L),d=e=>{e===document&&e.querySelectorAll("[popover]").forEach(t=>{t instanceof HTMLElement&&s.add(t)}),S.observe(e,{attributeFilter:["popover"],childList:!0,subtree:!0})};function f(){return typeof HTMLElement<"u"&&typeof HTMLElement.prototype=="object"&&"popover"in HTMLElement.prototype}var h="Not supported on element that does not have valid popover attribute";function v(e){let t=Element.prototype.attachShadow;Element.prototype.attachShadow=function(n){let o=t.call(this,n);return e(o),o}}var E=(e,t)=>{let n=t.closest(e);if(n)return n;let o=t.getRootNode();return o===document||!(o instanceof ShadowRoot)?null:E(e,o.host)};function g(){let e=new WeakSet;Object.defineProperties(HTMLElement.prototype,{popover:{enumerable:!0,configurable:!0,get(){let o=(this.getAttribute("popover")||"").toLowerCase();return o==="manual"?"manual":o===""||o=="auto"?"auto":null},set(o){this.setAttribute("popover",o)}},showPopover:{enumerable:!0,configurable:!0,value(){if(!this.popover)throw new DOMException(h,"NotSupportedError");if(e.has(this))throw new DOMException("Invalid on already-showing Popovers","InvalidStateError");this.classList.add(":open"),e.add(this),this.popover==="auto"&&(this.hasAttribute("autofocus")?this:this.querySelector("[autofocus]"))?.focus()}},hidePopover:{enumerable:!0,configurable:!0,value(){if(!this.popover)throw new DOMException(h,"NotSupportedError");if(!e.has(this))throw new DOMException("Invalid on already-hidden Popovers","InvalidStateError");this.classList.remove(":open"),e.delete(this)}}});let n=(o=>a=>{a.addEventListener("click",o)})(o=>{let a=o.target;if(!(a instanceof Element))return;let p=a.getRootNode();if(p instanceof ShadowRoot)o.stopPropagation();else if(!(p instanceof Document))return;let r=E("[popover]",a),i=a.closest("[popovertoggletarget],[popoverhidetarget],[popovershowtarget]"),l=i instanceof HTMLButtonElement;l&&i.hasAttribute("popovershowtarget")?(r=p.getElementById(i.getAttribute("popovershowtarget")||""),r&&r.popover&&!e.has(r)&&r.showPopover()):l&&i.hasAttribute("popoverhidetarget")?(r=p.getElementById(i.getAttribute("popoverhidetarget")||""),r&&r.popover&&e.has(r)&&r.hidePopover()):l&&i.hasAttribute("popovertoggletarget")&&(r=p.getElementById(i.getAttribute("popovertoggletarget")||""),r&&r.popover&&(e.has(r)?r.hidePopover():r.showPopover()));for(let c of[...s])c.matches('[popover="" i].\\:open, [popover=auto i].\\:open')&&c!==r&&c.hidePopover()});d(document),n(document),v(d),v(n)}f()||g();})(); | ||
//# sourceMappingURL=popover.iife.min.js.map |
@@ -0,1 +1,66 @@ | ||
// src/observer.ts | ||
var popovers = /* @__PURE__ */ new Set(); | ||
var popoversSyncFactory = (method) => (node) => { | ||
if (node instanceof HTMLElement) { | ||
if (node.hasAttribute("popover")) { | ||
method(node); | ||
} | ||
node.querySelectorAll("[popover]").forEach((popover) => { | ||
if (popover instanceof HTMLElement) { | ||
method(popover); | ||
} | ||
}); | ||
} | ||
}; | ||
var nodeAddedCallback = popoversSyncFactory(popovers.add.bind(popovers)); | ||
var nodeRemovedCallback = popoversSyncFactory(popovers.delete.bind(popovers)); | ||
var handleChildListMutation = (mutation) => { | ||
if (mutation.addedNodes.length > 0) { | ||
mutation.addedNodes.forEach(nodeAddedCallback); | ||
} | ||
if (mutation.removedNodes.length > 0) { | ||
mutation.removedNodes.forEach(nodeRemovedCallback); | ||
} | ||
}; | ||
var handlePopoverAttributeMutation = (mutation) => { | ||
if (mutation.target instanceof HTMLElement) { | ||
if (mutation.target.hasAttribute("popover")) { | ||
popovers.add(mutation.target); | ||
} else { | ||
popovers.delete(mutation.target); | ||
} | ||
} | ||
}; | ||
var handleMutation = (mutationList) => { | ||
mutationList.forEach((mutation) => { | ||
switch (mutation.type) { | ||
case "attributes": | ||
switch (mutation.attributeName) { | ||
case "popover": | ||
handlePopoverAttributeMutation(mutation); | ||
break; | ||
} | ||
break; | ||
case "childList": | ||
handleChildListMutation(mutation); | ||
break; | ||
} | ||
}); | ||
}; | ||
var observer = new MutationObserver(handleMutation); | ||
var observePopoversMutations = (root) => { | ||
if (root === document) { | ||
root.querySelectorAll("[popover]").forEach((popover) => { | ||
if (popover instanceof HTMLElement) { | ||
popovers.add(popover); | ||
} | ||
}); | ||
} | ||
observer.observe(root, { | ||
attributeFilter: ["popover"], | ||
childList: true, | ||
subtree: true | ||
}); | ||
}; | ||
// src/popover.ts | ||
@@ -6,2 +71,21 @@ function isSupported() { | ||
var notSupportedMessage = "Not supported on element that does not have valid popover attribute"; | ||
function patchAttachShadow(callback) { | ||
const originalAttachShadow = Element.prototype.attachShadow; | ||
Element.prototype.attachShadow = function(init) { | ||
const shadowRoot = originalAttachShadow.call(this, init); | ||
callback(shadowRoot); | ||
return shadowRoot; | ||
}; | ||
} | ||
var closestElement = (selector, target) => { | ||
const found = target.closest(selector); | ||
if (found) { | ||
return found; | ||
} | ||
const root = target.getRootNode(); | ||
if (root === document || !(root instanceof ShadowRoot)) { | ||
return null; | ||
} | ||
return closestElement(selector, root.host); | ||
}; | ||
function apply() { | ||
@@ -60,8 +144,15 @@ const visibleElements = /* @__PURE__ */ new WeakSet(); | ||
}); | ||
document.addEventListener("click", (event) => { | ||
const onClick = (event) => { | ||
const target = event.target; | ||
if (!(target instanceof Element)) | ||
return; | ||
const doc = target.ownerDocument; | ||
let effectedPopover = target.closest("[popover]"); | ||
const root = target.getRootNode(); | ||
if (root instanceof ShadowRoot) { | ||
event.stopPropagation(); | ||
} else if (!(root instanceof Document)) | ||
return; | ||
let effectedPopover = closestElement( | ||
"[popover]", | ||
target | ||
); | ||
const button = target.closest( | ||
@@ -72,3 +163,3 @@ "[popovertoggletarget],[popoverhidetarget],[popovershowtarget]" | ||
if (isButton && button.hasAttribute("popovershowtarget")) { | ||
effectedPopover = doc.getElementById( | ||
effectedPopover = root.getElementById( | ||
button.getAttribute("popovershowtarget") || "" | ||
@@ -80,3 +171,3 @@ ); | ||
} else if (isButton && button.hasAttribute("popoverhidetarget")) { | ||
effectedPopover = doc.getElementById( | ||
effectedPopover = root.getElementById( | ||
button.getAttribute("popoverhidetarget") || "" | ||
@@ -88,3 +179,3 @@ ); | ||
} else if (isButton && button.hasAttribute("popovertoggletarget")) { | ||
effectedPopover = doc.getElementById( | ||
effectedPopover = root.getElementById( | ||
button.getAttribute("popovertoggletarget") || "" | ||
@@ -100,9 +191,14 @@ ); | ||
} | ||
for (const popover of doc.querySelectorAll( | ||
'[popover="" i].\\:open, [popover=auto i].\\:open' | ||
)) { | ||
if (popover instanceof HTMLElement && popover !== effectedPopover) | ||
for (const popover of [...popovers]) { | ||
if (popover.matches('[popover="" i].\\:open, [popover=auto i].\\:open') && popover !== effectedPopover) | ||
popover.hidePopover(); | ||
} | ||
}); | ||
}; | ||
const addOnClickEventListener = ((callback) => (root) => { | ||
root.addEventListener("click", callback); | ||
})(onClick); | ||
observePopoversMutations(document); | ||
addOnClickEventListener(document); | ||
patchAttachShadow(observePopoversMutations); | ||
patchAttachShadow(addOnClickEventListener); | ||
} | ||
@@ -109,0 +205,0 @@ |
@@ -1,2 +0,2 @@ | ||
function l(){return typeof HTMLElement<"u"&&typeof HTMLElement.prototype=="object"&&"popover"in HTMLElement.prototype}var a="Not supported on element that does not have valid popover attribute";function u(){let o=new WeakSet;Object.defineProperties(HTMLElement.prototype,{popover:{enumerable:!0,configurable:!0,get(){let t=(this.getAttribute("popover")||"").toLowerCase();return t==="manual"?"manual":t===""||t=="auto"?"auto":null},set(t){this.setAttribute("popover",t)}},showPopover:{enumerable:!0,configurable:!0,value(){if(!this.popover)throw new DOMException(a,"NotSupportedError");if(o.has(this))throw new DOMException("Invalid on already-showing Popovers","InvalidStateError");this.classList.add(":open"),o.add(this),this.popover==="auto"&&(this.hasAttribute("autofocus")?this:this.querySelector("[autofocus]"))?.focus()}},hidePopover:{enumerable:!0,configurable:!0,value(){if(!this.popover)throw new DOMException(a,"NotSupportedError");if(!o.has(this))throw new DOMException("Invalid on already-hidden Popovers","InvalidStateError");this.classList.remove(":open"),o.delete(this)}}}),document.addEventListener("click",t=>{let p=t.target;if(!(p instanceof Element))return;let n=p.ownerDocument,e=p.closest("[popover]"),r=p.closest("[popovertoggletarget],[popoverhidetarget],[popovershowtarget]"),i=r instanceof HTMLButtonElement;i&&r.hasAttribute("popovershowtarget")?(e=n.getElementById(r.getAttribute("popovershowtarget")||""),e&&e.popover&&!o.has(e)&&e.showPopover()):i&&r.hasAttribute("popoverhidetarget")?(e=n.getElementById(r.getAttribute("popoverhidetarget")||""),e&&e.popover&&o.has(e)&&e.hidePopover()):i&&r.hasAttribute("popovertoggletarget")&&(e=n.getElementById(r.getAttribute("popovertoggletarget")||""),e&&e.popover&&(o.has(e)?e.hidePopover():e.showPopover()));for(let s of n.querySelectorAll('[popover="" i].\\:open, [popover=auto i].\\:open'))s instanceof HTMLElement&&s!==e&&s.hidePopover()})}l()||u(); | ||
var s=new Set,u=e=>t=>{t instanceof HTMLElement&&(t.hasAttribute("popover")&&e(t),t.querySelectorAll("[popover]").forEach(n=>{n instanceof HTMLElement&&e(n)}))},b=u(s.add.bind(s)),m=u(s.delete.bind(s)),w=e=>{e.addedNodes.length>0&&e.addedNodes.forEach(b),e.removedNodes.length>0&&e.removedNodes.forEach(m)},M=e=>{e.target instanceof HTMLElement&&(e.target.hasAttribute("popover")?s.add(e.target):s.delete(e.target))},L=e=>{e.forEach(t=>{switch(t.type){case"attributes":switch(t.attributeName){case"popover":M(t);break}break;case"childList":w(t);break}})},S=new MutationObserver(L),d=e=>{e===document&&e.querySelectorAll("[popover]").forEach(t=>{t instanceof HTMLElement&&s.add(t)}),S.observe(e,{attributeFilter:["popover"],childList:!0,subtree:!0})};function f(){return typeof HTMLElement<"u"&&typeof HTMLElement.prototype=="object"&&"popover"in HTMLElement.prototype}var h="Not supported on element that does not have valid popover attribute";function v(e){let t=Element.prototype.attachShadow;Element.prototype.attachShadow=function(n){let o=t.call(this,n);return e(o),o}}var E=(e,t)=>{let n=t.closest(e);if(n)return n;let o=t.getRootNode();return o===document||!(o instanceof ShadowRoot)?null:E(e,o.host)};function g(){let e=new WeakSet;Object.defineProperties(HTMLElement.prototype,{popover:{enumerable:!0,configurable:!0,get(){let o=(this.getAttribute("popover")||"").toLowerCase();return o==="manual"?"manual":o===""||o=="auto"?"auto":null},set(o){this.setAttribute("popover",o)}},showPopover:{enumerable:!0,configurable:!0,value(){if(!this.popover)throw new DOMException(h,"NotSupportedError");if(e.has(this))throw new DOMException("Invalid on already-showing Popovers","InvalidStateError");this.classList.add(":open"),e.add(this),this.popover==="auto"&&(this.hasAttribute("autofocus")?this:this.querySelector("[autofocus]"))?.focus()}},hidePopover:{enumerable:!0,configurable:!0,value(){if(!this.popover)throw new DOMException(h,"NotSupportedError");if(!e.has(this))throw new DOMException("Invalid on already-hidden Popovers","InvalidStateError");this.classList.remove(":open"),e.delete(this)}}});let n=(o=>a=>{a.addEventListener("click",o)})(o=>{let a=o.target;if(!(a instanceof Element))return;let p=a.getRootNode();if(p instanceof ShadowRoot)o.stopPropagation();else if(!(p instanceof Document))return;let r=E("[popover]",a),i=a.closest("[popovertoggletarget],[popoverhidetarget],[popovershowtarget]"),l=i instanceof HTMLButtonElement;l&&i.hasAttribute("popovershowtarget")?(r=p.getElementById(i.getAttribute("popovershowtarget")||""),r&&r.popover&&!e.has(r)&&r.showPopover()):l&&i.hasAttribute("popoverhidetarget")?(r=p.getElementById(i.getAttribute("popoverhidetarget")||""),r&&r.popover&&e.has(r)&&r.hidePopover()):l&&i.hasAttribute("popovertoggletarget")&&(r=p.getElementById(i.getAttribute("popovertoggletarget")||""),r&&r.popover&&(e.has(r)?r.hidePopover():r.showPopover()));for(let c of[...s])c.matches('[popover="" i].\\:open, [popover=auto i].\\:open')&&c!==r&&c.hidePopover()});d(document),n(document),v(d),v(n)}f()||g(); | ||
//# sourceMappingURL=popover.min.js.map |
{ | ||
"name": "@oddbird/popover-polyfill", | ||
"version": "0.0.4", | ||
"version": "0.0.5", | ||
"description": "Popover Attribute Polyfill", | ||
@@ -89,17 +89,17 @@ "license": "BSD-3-Clause", | ||
"devDependencies": { | ||
"@playwright/test": "^1.28.1", | ||
"@types/node": "^18.11.13", | ||
"@typescript-eslint/eslint-plugin": "^5.46.0", | ||
"@typescript-eslint/parser": "^5.46.0", | ||
"esbuild": "^0.16.4", | ||
"eslint": "^8.29.0", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-import-resolver-typescript": "^3.5.2", | ||
"eslint-plugin-import": "^2.26.0", | ||
"@playwright/test": "^1.29.2", | ||
"@types/node": "^18.11.18", | ||
"@typescript-eslint/eslint-plugin": "^5.48.1", | ||
"@typescript-eslint/parser": "^5.48.1", | ||
"esbuild": "^0.17.0", | ||
"eslint": "^8.31.0", | ||
"eslint-config-prettier": "^8.6.0", | ||
"eslint-import-resolver-typescript": "^3.5.3", | ||
"eslint-plugin-import": "^2.27.4", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"eslint-plugin-simple-import-sort": "^8.0.0", | ||
"husky": "^8.0.2", | ||
"husky": "^8.0.3", | ||
"lint-staged": "^13.1.0", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^2.8.1", | ||
"prettier": "^2.8.3", | ||
"stylelint-config-standard": "^29.0.0", | ||
@@ -106,0 +106,0 @@ "stylis": "^4.1.3", |
@@ -39,2 +39,5 @@ # Popover Attribute Polyfill | ||
Note that default styles will not be applied to shadow roots. | ||
Each root node will need to include the styles separately. | ||
### With npm | ||
@@ -67,2 +70,7 @@ | ||
```html | ||
<link | ||
rel="stylesheet" | ||
href="https://cdn.jsdelivr.net/npm/@oddbird/popover-polyfill@latest/dist/popover.css" | ||
crossorigin="anonymous" | ||
/> | ||
<script | ||
@@ -69,0 +77,0 @@ src="https://cdn.jsdelivr.net/npm/@oddbird/popover-polyfill@latest" |
@@ -0,1 +1,3 @@ | ||
import { observePopoversMutations, popovers } from './observer.js'; | ||
export function isSupported() { | ||
@@ -12,2 +14,30 @@ return ( | ||
function patchAttachShadow(callback: (shadowRoot: ShadowRoot) => void) { | ||
const originalAttachShadow = Element.prototype.attachShadow; | ||
Element.prototype.attachShadow = function (init) { | ||
const shadowRoot = originalAttachShadow.call(this, init); | ||
callback(shadowRoot); | ||
return shadowRoot; | ||
}; | ||
} | ||
const closestElement: (selector: string, target: Element) => Element | null = ( | ||
selector: string, | ||
target: Element, | ||
) => { | ||
const found = target.closest(selector); | ||
if (found) { | ||
return found; | ||
} | ||
const root = target.getRootNode(); | ||
if (root === document || !(root instanceof ShadowRoot)) { | ||
return null; | ||
} | ||
return closestElement(selector, root.host); | ||
}; | ||
export function apply() { | ||
@@ -70,7 +100,13 @@ const visibleElements = new WeakSet<HTMLElement>(); | ||
document.addEventListener('click', (event: Event) => { | ||
const onClick = (event: Event) => { | ||
const target = event.target; | ||
if (!(target instanceof Element)) return; | ||
const doc = target.ownerDocument; | ||
let effectedPopover: HTMLElement | null = target.closest('[popover]'); | ||
const root = target.getRootNode(); | ||
if (root instanceof ShadowRoot) { | ||
event.stopPropagation(); | ||
} else if (!(root instanceof Document)) return; | ||
let effectedPopover = closestElement( | ||
'[popover]', | ||
target, | ||
) as HTMLElement | null; | ||
const button = target.closest( | ||
@@ -83,3 +119,3 @@ '[popovertoggletarget],[popoverhidetarget],[popovershowtarget]', | ||
if (isButton && button.hasAttribute('popovershowtarget')) { | ||
effectedPopover = doc.getElementById( | ||
effectedPopover = root.getElementById( | ||
button.getAttribute('popovershowtarget') || '', | ||
@@ -96,3 +132,3 @@ ); | ||
} else if (isButton && button.hasAttribute('popoverhidetarget')) { | ||
effectedPopover = doc.getElementById( | ||
effectedPopover = root.getElementById( | ||
button.getAttribute('popoverhidetarget') || '', | ||
@@ -109,3 +145,3 @@ ); | ||
} else if (isButton && button.hasAttribute('popovertoggletarget')) { | ||
effectedPopover = doc.getElementById( | ||
effectedPopover = root.getElementById( | ||
button.getAttribute('popovertoggletarget') || '', | ||
@@ -124,9 +160,22 @@ ); | ||
// Dismiss open Popovers | ||
for (const popover of doc.querySelectorAll( | ||
'[popover="" i].\\:open, [popover=auto i].\\:open', | ||
)) { | ||
if (popover instanceof HTMLElement && popover !== effectedPopover) | ||
for (const popover of [...popovers]) { | ||
if ( | ||
popover.matches('[popover="" i].\\:open, [popover=auto i].\\:open') && | ||
popover !== effectedPopover | ||
) | ||
popover.hidePopover(); | ||
} | ||
}); | ||
}; | ||
const addOnClickEventListener = ( | ||
(callback: (event: Event) => void) => (root: Document | ShadowRoot) => { | ||
root.addEventListener('click', callback); | ||
} | ||
)(onClick); | ||
observePopoversMutations(document); | ||
addOnClickEventListener(document); | ||
patchAttachShadow(observePopoversMutations); | ||
patchAttachShadow(addOnClickEventListener); | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
81663
20
716
89