class IntersectionSentinel extends HTMLElement {
observer: IntersectionObserver | null
constructor() {
super()
this.observer = null
}
static get observedAttributes() {
return ["root", "root-margin", "threshold", "disabled"]
}
connectedCallback() {
this.subscribe()
}
disconnectedCallback() {
this.unsubscribe()
}
attributeChangedCallback(name: string, _: string, newValue: string) {
console.log(name, newValue)
if (name === "disabled") {
if (newValue === "true") {
this.unsubscribe()
} else {
this.subscribe()
}
}
}
subscribe() {
if (this.observer == null) {
const rootAttribute = this.getAttribute("root")
const root =
rootAttribute != null ? document.getElementById(rootAttribute) : null
const rootMargin = this.getAttribute("root-margin") ?? "0px"
const threshold = parseFloat(this.getAttribute("threshold") ?? "0.5")
this.observer = new IntersectionObserver(
(entries) => {
console.log("IntersectionSentinel intersection", entries)
entries.forEach((entry) => {
if (entry.isIntersecting) {
this.dispatchEvent(
new CustomEvent("intersection", {
detail: entry,
})
)
}
})
},
{
root,
rootMargin,
threshold,
}
)
this.observer.observe(this)
}
}
unsubscribe() {
if (this.observer != null) {
this.observer.disconnect()
this.observer = null
}
}
}
customElements.define("intersection-sentinel", IntersectionSentinel)