Files
fizzy/app/javascript/controllers/bridge/title_controller.js
T
2026-01-19 10:05:48 -05:00

64 lines
1.5 KiB
JavaScript

import { BridgeComponent } from "@hotwired/hotwire-native-bridge"
import { viewport } from "helpers/bridge/viewport_helpers"
import { nextFrame } from "helpers/timing_helpers"
export default class extends BridgeComponent {
static component = "title"
static targets = [ "header" ]
static values = { title: String }
async connect() {
super.connect()
await nextFrame()
this.#startObserver()
window.addEventListener("resize", this.#windowResized)
}
disconnect() {
super.disconnect()
this.#stopObserver()
window.removeEventListener("resize", this.#windowResized)
}
notifyBridgeOfVisibilityChange(visible) {
this.send("visibility", { title: this.#title, elementVisible: visible })
}
// Intersection Observer
#startObserver() {
if (!this.hasHeaderTarget) return
this.observer = new IntersectionObserver(([ entry ]) =>
this.notifyBridgeOfVisibilityChange(entry.isIntersecting),
{ rootMargin: `-${this.#topOffset}px 0px 0px 0px` }
)
this.observer.observe(this.headerTarget)
this.previousTopOffset = this.#topOffset
}
#stopObserver() {
this.observer?.disconnect()
}
#updateObserverIfNeeded() {
if (this.#topOffset === this.previousTopOffset) return
this.#stopObserver()
this.#startObserver()
}
#windowResized = () => {
this.#updateObserverIfNeeded()
}
get #title() {
return this.titleValue ? this.titleValue : document.title
}
get #topOffset() {
return viewport.top
}
}