Implement missing methods matching CustomElementRegistry
This commit is contained in:
parent
a5c0502666
commit
74142e375f
1 changed files with 48 additions and 15 deletions
|
@ -1,5 +1,7 @@
|
|||
/** @typedef {Promise & {signal: AbortSignal}} PromiseWithSignal */
|
||||
/** @typedef {(element: HTMLElement, detach: PromiseWithSignal) => void} Callback */
|
||||
/** @typedef {(element: HTMLElement, detached: PromiseWithSignal) => void} Callback */
|
||||
/** @typedef {new (element: HTMLElement, detached: PromiseWithSignal) => Object} ControllerClass */
|
||||
/** @typedef {Callback|ControllerClass} Controller */
|
||||
|
||||
export class ControllerList {
|
||||
/** @type {HTMLElement} */
|
||||
|
@ -105,6 +107,11 @@ export class ControllerRegistry {
|
|||
/** @type {Map<string,Callback>} */
|
||||
#defined = new Map()
|
||||
|
||||
/** @type {Map<string,Controller>} */
|
||||
#lookup = new Map()
|
||||
/** @type {Map<Controller,string>} */
|
||||
#nameLookup = new Map()
|
||||
|
||||
#attribute
|
||||
|
||||
/** @typedef {Document|DocumentFragment|HTMLElement} Root */
|
||||
|
@ -141,20 +148,25 @@ export class ControllerRegistry {
|
|||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {Callback} callback
|
||||
* @param {Controller} callback
|
||||
*/
|
||||
define(name, callback) {
|
||||
if (this.#nameLookup.has(callback)) console.warn(`Redefining controller ${this.#nameLookup.get(callback)} under new name ${name}:`, callback)
|
||||
|
||||
this.#lookup.set(name, callback)
|
||||
this.#nameLookup.set(callback, name)
|
||||
|
||||
if (("function" == typeof callback) && callback.prototype) {
|
||||
callback = async (element, disconnected) => {
|
||||
const {proxy, revoke} = Proxy.revocable(element, {})
|
||||
const controller = new callback(proxy, disconnected)
|
||||
const controller = new /** @type {ControllerClass} */(callback)(proxy, disconnected)
|
||||
await disconnected
|
||||
revoke()
|
||||
if ("detach" in controller) controller.detach(element)
|
||||
}
|
||||
}
|
||||
|
||||
this.#defined.set(name, callback)
|
||||
this.#defined.set(name, /** @type {Callback} */(callback))
|
||||
|
||||
const waitingList = this.#waiting.get(name)
|
||||
|
||||
|
@ -162,13 +174,42 @@ export class ControllerRegistry {
|
|||
this.#attach(element, name)
|
||||
}
|
||||
this.#waiting.delete(name)
|
||||
|
||||
if (this.#whenDefined.has(name)) {
|
||||
this.#whenDefined.get(name)[1]?.()
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets a controller associated with a given name
|
||||
* @param {string} name
|
||||
*/
|
||||
get(name) {
|
||||
return this.#defined.get(name)
|
||||
return this.#lookup.get(name)
|
||||
}
|
||||
|
||||
/** Gets the name a controller is registered with
|
||||
* @param {Controller} controller
|
||||
*/
|
||||
getName(controller) {
|
||||
return this.#nameLookup.get(controller)
|
||||
}
|
||||
|
||||
/** @type {Map<string,[Promise, ()=>void]>} */
|
||||
#whenDefined = new Map()
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
whenDefined(name) {
|
||||
if (!this.#whenDefined.has(name)) {
|
||||
if (this.#defined.has(name)) {
|
||||
this.#whenDefined.set(name, [Promise.resolve(), undefined])
|
||||
} else {
|
||||
let resolve
|
||||
const promise = new Promise(_resolve => {resolve = _resolve})
|
||||
this.#whenDefined.set(name, [promise, resolve])
|
||||
}
|
||||
}
|
||||
return this.#whenDefined.get(name)[0]
|
||||
}
|
||||
|
||||
/** @type {WeakMap<HTMLElement,ControllerList>} */
|
||||
|
@ -192,18 +233,10 @@ export class ControllerRegistry {
|
|||
const attached = this.#attached.get(element)
|
||||
if (attached)
|
||||
return [...attached.entries().filter(pair => pair[1]).map(pair => pair[0])]
|
||||
else
|
||||
else
|
||||
return []
|
||||
}
|
||||
|
||||
getName(controller) {
|
||||
// TODO: Return name of controller
|
||||
}
|
||||
|
||||
whenDefined(name) {
|
||||
// TODO: Return a promise
|
||||
}
|
||||
|
||||
/** @param {HTMLElement} element */
|
||||
#update(element) {
|
||||
const names = this.#getControllerNames(element)
|
||||
|
@ -238,7 +271,7 @@ export class ControllerRegistry {
|
|||
if (!this.#attached.has(element)) this.#attached.set(element, new Map())
|
||||
const attached = this.#attached.get(element)
|
||||
|
||||
const callback = this.get(name)
|
||||
const callback = this.#defined.get(name)
|
||||
|
||||
if (callback) {
|
||||
if (attached.has("name") && attached.get("name")) return console.warn(`Controller ${name} already fully attached`, element)
|
||||
|
|
Loading…
Reference in a new issue