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