Make DOMState API more generic

The old interface was too specific to the way domLense works, by
assuming the value to be an array that gets mutated elsewhere (or a
proxy that behaves like one)
This commit is contained in:
Talia 2024-01-15 11:48:52 +01:00
parent eb75dc531a
commit 0e6eee28fd

View file

@ -345,39 +345,45 @@ const mutationObserver = new MutationObserver(mutations => {
}) })
export class DOMState extends SimpleState { export class DOMState extends SimpleState {
#old #target
#options #defer
#changedValue = false #getValue
#value #equal
constructor(target, value, options) { #old
#changedValue = false
constructor(target, options) {
super() super()
this.#options = options this.#defer = options.defer ?? false
this.#old = [...value] this.#target = target
this.#value = value this.#getValue = options.get ?? (target => target.value)
this.#equal = options.equal ?? ((a, b) => a===b)
this.#old = this.#getValue(target)
const controller = new AbortController() const controller = new AbortController()
target.addEventListener(eventName, event=>{this.update(event)}, {signal: controller.signal})
abortRegistry.register(this, controller)
mutationObserver.observe(target, { mutationObserver.observe(target, {
attributes: true, attributes: true,
childList: true, childList: true,
characterData: true, characterData: true,
subtree: true, subtree: true,
}) })
target.addEventListener(eventName, event=>{this.update(event)}, {signal: controller.signal})
abortRegistry.register(this, controller)
} }
get value() { return this.#old } get value() { return this.#old }
update() { update() {
const current = [...this.#value] const current = this.#getValue(this.#target)
if (current.length === this.#old.length) {
for (const idx in current) { if (this.#equal(this.#old, current)) return
if (current[idx] !== this.#old[idx]) break
}
return
}
this.#old = current this.#old = current
if (this.#options?.defer) {
if (this.#defer) {
if (!this.#changedValue) { if (!this.#changedValue) {
queueMicrotask(() => { queueMicrotask(() => {
this.#changedValue = false this.#changedValue = false