@studiometa/js-toolkit 3.6.0 → 3.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Base/Base.js CHANGED
@@ -122,8 +122,20 @@ class Base {
122
122
  for (const instance of baseMap.values()) {
123
123
  if (instance === "terminated" || !hasInstance(instance)) continue;
124
124
  const { components } = instance.$config;
125
- if (components && Object.values(components).includes(this.constructor)) {
126
- return instance;
125
+ if (components) {
126
+ for (const component of Object.values(components)) {
127
+ if (component === this.constructor) {
128
+ return instance;
129
+ }
130
+ if (isFunction(component) && !("$isBase" in component)) {
131
+ const resolved = instance.__children.__asyncComponentPromises.get(
132
+ component
133
+ );
134
+ if (resolved?.status === "resolved" && resolved.ctor === this.constructor) {
135
+ return instance;
136
+ }
137
+ }
138
+ }
127
139
  }
128
140
  }
129
141
  }
package/Base/Base.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/Base/Base.ts"],
4
- "sourcesContent": ["/* eslint-disable no-use-before-define */\nimport {\n getComponentElements,\n getEventTarget,\n addToQueue,\n addInstance,\n deleteInstance,\n addToRegistry,\n hasInstance,\n} from './utils.js';\nimport {\n ChildrenManager,\n RefsManager,\n ServicesManager,\n EventsManager,\n OptionsManager,\n} from './managers/index.js';\nimport { getInstanceFromElement } from '../helpers/getInstanceFromElement.js';\nimport { queryComponentAll, closestComponent } from '../helpers/queryComponent.js';\nimport { noop, isDev, isFunction, isArray } from '../utils/index.js';\n\nlet id = 0;\n\nexport type BaseEl = HTMLElement & { __base__?: Map<string, Base | 'terminated'> };\nexport type BaseConstructor<T extends Base = Base> = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n new (...args: any[]): T;\n prototype: Base;\n} & Pick<typeof Base, keyof typeof Base>;\nexport type BaseAsyncConstructor<T extends Base = Base> = (\n instance: Base,\n) => Promise<BaseConstructor<T> | { default: BaseConstructor<T> }>;\nexport type BaseOptions = { [name: string]: unknown };\nexport type BaseRefs = { [name: string]: HTMLElement | HTMLElement[] };\nexport type BaseChildren = { [nameOrSelector: string]: Base[] | Promise<Base>[] };\nexport type BaseConfigComponents = {\n [nameOrSelector: string]: BaseConstructor | BaseAsyncConstructor;\n};\n\nexport type BaseConfig = {\n name: string;\n debug?: boolean;\n log?: boolean;\n refs?: string[];\n emits?: string[];\n components?: BaseConfigComponents;\n options?: import('./managers/OptionsManager').OptionsSchema;\n};\n\nexport type BaseProps = {\n $el?: HTMLElement;\n $options?: BaseOptions;\n $refs?: BaseRefs;\n $children?: BaseChildren;\n $parent?: Base;\n};\n\nexport type Managers = {\n ChildrenManager: typeof ChildrenManager;\n EventsManager: typeof EventsManager;\n OptionsManager: typeof OptionsManager;\n RefsManager: typeof RefsManager;\n ServicesManager: typeof ServicesManager;\n};\n\n/**\n * Base class.\n *\n * @link https://js-toolkit.studiometa.dev/api/\n */\nexport class Base<T extends BaseProps = BaseProps> {\n /**\n * Declare the `this.constructor` type\n * @link https://github.com/microsoft/TypeScript/issues/3841#issuecomment-2381594311\n */\n declare ['constructor']: BaseConstructor;\n\n /**\n * This is a Base instance.\n */\n static readonly $isBase = true as const;\n\n /**\n * Config.\n * @link https://js-toolkit.studiometa.dev/api/configuration.html\n */\n static config: BaseConfig = {\n name: 'Base',\n emits: [\n // hook events\n 'before-mounted',\n 'mounted',\n 'after-mounted',\n 'updated',\n 'before-destroyed',\n 'destroyed',\n 'after-destroyed',\n 'terminated',\n // default services' events\n 'ticked',\n 'scrolled',\n 'resized',\n 'moved',\n 'loaded',\n 'keyed',\n ],\n };\n\n /**\n * The instance id.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#id\n */\n $id: string;\n\n /**\n * The root element.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#el\n */\n $el: T['$el'] & BaseEl;\n\n /**\n * The state of the component.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#isMounted\n */\n $isMounted = false;\n\n /**\n * Is the component currently mounting itself and its children?\n * @private\n */\n __isMounting = false;\n\n /**\n * Store the event handlers.\n * @private\n */\n __eventHandlers: Map<string, Set<EventListenerOrEventListenerObject>> = new Map();\n\n /**\n * Get the root instance of the app.\n * @deprecated Use `$closest(name)` instead. Will be removed in v4.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#root\n */\n get $root(): Base {\n if (isDev) {\n console.warn(\n `[${this.$id}] $root is deprecated and will be removed in v4. Use $closest(name) instead.`,\n );\n }\n\n if (!this.__parent) {\n return this;\n }\n\n let parent = this.__parent;\n let root = this.__parent;\n\n while (parent) {\n if (!parent.__parent) {\n root = parent;\n }\n\n parent = parent.__parent;\n }\n\n return root;\n }\n\n /**\n * The parent instance if the current instance is registered as a child component in a parent component.\n * @deprecated Use `$closest(name)` instead. Will be removed in v4.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#parent\n */\n get $parent(): (T['$parent'] & Base) | null {\n if (isDev) {\n console.warn(\n `[${this.$id}] $parent is deprecated and will be removed in v4. Use $closest(name) instead.`,\n );\n }\n\n return this.__parent;\n }\n\n /**\n * Internal parent resolution without deprecation warning.\n * @internal\n */\n get __parent(): (T['$parent'] & Base) | null {\n // Walk up the DOM ancestors and resolve the closest mounted instance whose\n // config declares this component as a child, using each element's `__base__`\n // map for an O(1)-per-ancestor lookup. This is O(tree depth) instead of the\n // O(N_instances) global scan (plus `Set` copy) it replaces.\n let el = this.$el.parentElement;\n\n while (el) {\n const baseMap = (el as BaseEl).__base__;\n\n if (baseMap) {\n for (const instance of baseMap.values()) {\n if (instance === 'terminated' || !hasInstance(instance)) continue;\n\n const { components } = instance.$config;\n if (components && Object.values(components).includes(this.constructor)) {\n return instance as T['$parent'] & Base;\n }\n }\n }\n\n el = el.parentElement;\n }\n\n return null;\n }\n\n /**\n * Merge configuration with the parents' configurations.\n * @private\n */\n get __config(): BaseConfig {\n let proto = Object.getPrototypeOf(this);\n let { config } = proto.constructor;\n\n while (proto.constructor.config && proto.constructor.$isBase) {\n config = { ...proto.constructor.config, ...config };\n\n if (proto.constructor.config.options) {\n config.options = { ...proto.constructor.config.options, ...config.options };\n }\n\n if (proto.constructor.config.emits && config.emits) {\n config.emits = [...proto.constructor.config.emits, ...config.emits];\n }\n\n proto = Object.getPrototypeOf(proto);\n }\n\n config.options = config.options ?? {};\n config.refs = config.refs ?? [];\n config.components = config.components ?? {};\n\n return config;\n }\n\n /**\n * The normalized config of the component.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#config\n */\n get $config() {\n return this.__config;\n }\n\n __services: ServicesManager;\n\n /**\n * Services.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#services\n */\n get $services(): ServicesManager {\n return this.__services;\n }\n\n __refs: RefsManager<T['$refs'] & BaseRefs>;\n\n /**\n * Refs.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#refs\n */\n get $refs(): T['$refs'] & BaseRefs {\n return this.__refs.props;\n }\n\n __options: OptionsManager<T['$options'] & BaseOptions>;\n\n /**\n * Options.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#options\n */\n get $options(): T['$options'] & BaseOptions {\n return this.__options.props;\n }\n\n __children: ChildrenManager<T['$children'] & BaseChildren>;\n\n /**\n * Children.\n * @deprecated Use `$query(name)` instead. Will be removed in v4.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#children\n */\n get $children(): T['$children'] & BaseChildren {\n if (isDev) {\n console.warn(\n `[${this.$id}] $children is deprecated and will be removed in v4. Use $query(name) instead.`,\n );\n }\n\n return this.__children.props;\n }\n\n /**\n * Get all descendant component instances matching the given query.\n * Sugar for `queryComponentAll(query, { from: this.$el })`.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#query-query\n */\n $query<U extends Base = Base>(query: string): U[] {\n return queryComponentAll<U>(query, { from: this.$el });\n }\n\n /**\n * Get the closest ancestor component instance matching the given query.\n * Sugar for `closestComponent(query, { from: this.$el })`.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#closest-query\n */\n $closest<U extends Base = Base>(query: string): U | undefined {\n return closestComponent<U>(query, { from: this.$el });\n }\n\n __events: EventsManager;\n\n /**\n * Small helper to log stuff.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#log-content\n */\n get $log(): (...args: unknown[]) => void {\n return this.$options.log ? window.console.log.bind(window, `[${this.$id}]`) : noop;\n }\n\n /**\n * Small helper to make warning easier.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#warn-content\n */\n get $warn(): (...args: unknown[]) => void {\n return this.$options.log ? window.console.warn.bind(window, `[${this.$id}]`) : noop;\n }\n\n /**\n * Small helper to debug information.\n * @internal\n */\n get __debug(): (...args: unknown[]) => void {\n return isDev && this.$options.debug\n ? window.console.log.bind(window, `[debug] [${this.$id}]`)\n : noop;\n }\n\n /**\n * Get manager constructors.\n * @internal\n */\n get __managers(): Managers {\n return {\n ChildrenManager,\n EventsManager,\n OptionsManager,\n RefsManager,\n ServicesManager,\n };\n }\n\n /**\n * Call an instance method and emit corresponding events.\n * @internal\n */\n __callMethod(method: string, ...args: unknown[]): unknown {\n if (isDev) {\n this.__debug('callMethod', method, ...args);\n }\n\n this.$emit(method, ...args);\n\n // We always emit an event, but we do not call the method if it does not exist\n if (!isFunction(this[method])) {\n return null;\n }\n\n if (isDev) {\n this.__debug(method, this, ...args);\n }\n\n return this[method].call(this, ...args);\n }\n\n /**\n * Test if the given event has been bound to the instance.\n *\n * @param {string} event The event's name.\n * @return {boolean} Wether the given event has been bound or not.\n * @internal\n */\n __hasEvent(event: string): boolean {\n const eventHandlers = this.__eventHandlers.get(event);\n return eventHandlers && eventHandlers.size > 0;\n }\n\n /**\n * Class constructor where all the magic takes place.\n *\n * @param {HTMLElement} element The component's root element dd.\n * @link https://js-toolkit.studiometa.dev/api/instantiation.html\n */\n constructor(element: HTMLElement) {\n if (!element) {\n if (isDev) {\n throw new Error('The root element must be defined.');\n }\n return;\n }\n\n const { $config } = this;\n\n if ($config.name === 'Base') {\n if (isDev) {\n throw new Error('The `config.name` property is required.');\n }\n return;\n }\n\n // Add current component to the registry\n addToRegistry($config.name, this.constructor);\n\n this.$id = `${$config.name}-${id}`;\n id += 1;\n\n this.$el = element;\n this.$el.__base__ ??= new Map();\n this.$el.__base__.set($config.name, this);\n\n for (const service of ['Options', 'Services', 'Events', 'Refs', 'Children']) {\n this[`__${service.toLowerCase()}`] = new this.__managers[`${service}Manager`](this);\n }\n\n this.$on('before-mounted', () => {\n addInstance(this);\n });\n this.$on('after-destroyed', () => {\n deleteInstance(this);\n });\n\n if (isDev) {\n this.__debug('constructor', this);\n }\n }\n\n /**\n * Trigger the `mounted` callback.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#mount\n */\n async $mount(): Promise<this> {\n if (this.$isMounted || this.__isMounting) {\n return this;\n }\n\n this.__isMounting = true;\n this.$emit('before-mounted');\n\n if (isDev) {\n this.__debug('$mount');\n }\n\n await Promise.all([\n addToQueue(() => this.__children.registerAll()),\n addToQueue(() => this.__refs.registerAll()),\n addToQueue(() => this.__events.bindRootElement()),\n addToQueue(() => this.__services.enableAll()),\n addToQueue(() => this.__children.mountAll()),\n ]);\n\n await addToQueue(() => {\n this.$isMounted = true;\n this.__callMethod('mounted');\n });\n\n this.__isMounting = false;\n this.$emit('after-mounted');\n\n return this;\n }\n\n /**\n * Update the instance children.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#update\n */\n async $update(): Promise<this> {\n if (isDev) {\n this.__debug('$update');\n }\n\n await Promise.all([\n // Undo\n addToQueue(() => this.__refs.unregisterAll()),\n addToQueue(() => this.__services.disableAll()),\n // Redo\n addToQueue(() => this.__children.registerAll()),\n addToQueue(() => this.__refs.registerAll()),\n addToQueue(() => this.__services.enableAll()),\n // Update\n addToQueue(() => this.__children.updateAll()),\n ]);\n\n await addToQueue(() => this.__callMethod('updated'));\n\n return this;\n }\n\n /**\n * Trigger the `destroyed` callback.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#destroy\n */\n async $destroy(): Promise<this> {\n if (!this.$isMounted) {\n return this;\n }\n\n if (isDev) {\n this.__debug('$destroy');\n }\n\n this.$emit('before-destroyed');\n this.$isMounted = false;\n\n await Promise.all([\n addToQueue(() => this.__events.unbindRootElement()),\n addToQueue(() => this.__refs.unregisterAll()),\n addToQueue(() => this.__services.disableAll()),\n addToQueue(() => this.__children.destroyAll()),\n ]);\n\n await addToQueue(() => this.__callMethod('destroyed'));\n\n this.$emit('after-destroyed');\n\n return this;\n }\n\n /**\n * Terminate a child instance when it is not needed anymore.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#terminate\n */\n async $terminate(): Promise<void> {\n if (isDev) {\n this.__debug('$terminate');\n }\n\n await Promise.all([\n // First, destroy the component.\n addToQueue(() => this.$destroy()),\n // Execute the `terminated` hook if it exists\n addToQueue(() => this.__callMethod('terminated')),\n // Delete instance\n addToQueue(() => this.$el.__base__.set(this.$config.name, 'terminated')),\n ]);\n }\n\n /**\n * Add an emitted event.\n *\n * @param {string} event The event name.\n * @return {void}\n * @internal\n */\n __addEmits(event: string): void {\n const ctor = this.constructor;\n if (isArray(ctor.config.emits)) {\n ctor.config.emits.push(event);\n } else {\n ctor.config.emits = [event];\n }\n }\n\n /**\n * Remove an emitted event.\n *\n * @param {string} event The event name.\n * @return {void}\n * @internal\n */\n __removeEmits(event: string): void {\n const ctor = this.constructor;\n const index = ctor.config.emits.indexOf(event);\n ctor.config.emits.splice(index, 1);\n }\n\n /**\n * Bind a listener function to an event.\n *\n * @param {string} event\n * Name of the event.\n * @param {EventListenerOrEventListenerObject} listener\n * Function to be called.\n * @param {boolean|AddEventListenerOptions} [options]\n * Options for the `removeEventListener` method.\n * @return {() => void}\n * A function to unbind the listener.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#on-event-callback-options\n */\n $on(\n event: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): () => void {\n if (isDev) {\n this.__debug('$on', event, listener, options);\n }\n\n let set = this.__eventHandlers.get(event);\n\n if (!set) {\n set = new Set();\n this.__eventHandlers.set(event, set);\n }\n\n set.add(listener);\n\n const target = getEventTarget(this, event, this.__config);\n target?.addEventListener(event, listener, options);\n\n if (isDev) {\n if (!target) {\n console.warn(\n `[${this.$id}]`,\n `The \"${event}\" event is missing from the configuration and is not a native`,\n `event for the root element of type \\`${this.$el.constructor.name}\\`.`,\n );\n }\n }\n\n return () => {\n this.$off(event, listener, options);\n };\n }\n\n /**\n * Unbind a listener function from an event.\n *\n * @param {string} event\n * Name of the event.\n * @param {EventListenerOrEventListenerObject} listener\n * Function to be removed.\n * @param {boolean|EventListenerOptions} [options]\n * Options for the `removeEventListener` method.\n * @return {void}\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#off-event-callback-options\n */\n $off(\n event: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ) {\n if (isDev) {\n this.__debug('$off', event, listener);\n }\n\n this.__eventHandlers.get(event)?.delete(listener);\n\n const target = getEventTarget(this, event, this.__config);\n target?.removeEventListener(event, listener, options);\n }\n\n /**\n * Emits an event.\n *\n * @param {string} event Name of the event.\n * @param {any[]} args The arguments to apply to the functions bound to this event.\n * @return {void}\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#emit-event-args\n */\n $emit(event: string | Event, ...args: unknown[]) {\n if (isDev) {\n this.__debug('$emit', event, args);\n }\n\n this.$el.dispatchEvent(\n event instanceof Event ? event : new CustomEvent(event, { detail: args }),\n );\n }\n\n /**\n * Register and mount all instances of the component.\n * @link https://js-toolkit.studiometa.dev/api/static-methods.html#register-nameorselector-string\n */\n static $register<T extends BaseProps = BaseProps, U extends typeof Base<T> = typeof Base<T>>(\n this: U,\n nameOrSelector?: string,\n ): Promise<InstanceType<U>>[] {\n addToRegistry(nameOrSelector ?? this.config.name, this);\n\n return getComponentElements(nameOrSelector ?? this.config.name).map(\n async (el) =>\n getInstanceFromElement(el, this) ?? (new this(el).$mount() as Promise<InstanceType<U>>),\n );\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/* eslint-disable no-use-before-define */\nimport {\n getComponentElements,\n getEventTarget,\n addToQueue,\n addInstance,\n deleteInstance,\n addToRegistry,\n hasInstance,\n} from './utils.js';\nimport {\n ChildrenManager,\n RefsManager,\n ServicesManager,\n EventsManager,\n OptionsManager,\n} from './managers/index.js';\nimport { getInstanceFromElement } from '../helpers/getInstanceFromElement.js';\nimport { queryComponentAll, closestComponent } from '../helpers/queryComponent.js';\nimport { noop, isDev, isFunction, isArray } from '../utils/index.js';\n\nlet id = 0;\n\nexport type BaseEl = HTMLElement & { __base__?: Map<string, Base | 'terminated'> };\nexport type BaseConstructor<T extends Base = Base> = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n new (...args: any[]): T;\n prototype: Base;\n} & Pick<typeof Base, keyof typeof Base>;\nexport type BaseAsyncConstructor<T extends Base = Base> = (\n instance: Base,\n) => Promise<BaseConstructor<T> | { default: BaseConstructor<T> }>;\nexport type BaseOptions = { [name: string]: unknown };\nexport type BaseRefs = { [name: string]: HTMLElement | HTMLElement[] };\nexport type BaseChildren = { [nameOrSelector: string]: Base[] | Promise<Base>[] };\nexport type BaseConfigComponents = {\n [nameOrSelector: string]: BaseConstructor | BaseAsyncConstructor;\n};\n\nexport type BaseConfig = {\n name: string;\n debug?: boolean;\n log?: boolean;\n refs?: string[];\n emits?: string[];\n components?: BaseConfigComponents;\n options?: import('./managers/OptionsManager').OptionsSchema;\n};\n\nexport type BaseProps = {\n $el?: HTMLElement;\n $options?: BaseOptions;\n $refs?: BaseRefs;\n $children?: BaseChildren;\n $parent?: Base;\n};\n\nexport type Managers = {\n ChildrenManager: typeof ChildrenManager;\n EventsManager: typeof EventsManager;\n OptionsManager: typeof OptionsManager;\n RefsManager: typeof RefsManager;\n ServicesManager: typeof ServicesManager;\n};\n\n/**\n * Base class.\n *\n * @link https://js-toolkit.studiometa.dev/api/\n */\nexport class Base<T extends BaseProps = BaseProps> {\n /**\n * Declare the `this.constructor` type\n * @link https://github.com/microsoft/TypeScript/issues/3841#issuecomment-2381594311\n */\n declare ['constructor']: BaseConstructor;\n\n /**\n * This is a Base instance.\n */\n static readonly $isBase = true as const;\n\n /**\n * Config.\n * @link https://js-toolkit.studiometa.dev/api/configuration.html\n */\n static config: BaseConfig = {\n name: 'Base',\n emits: [\n // hook events\n 'before-mounted',\n 'mounted',\n 'after-mounted',\n 'updated',\n 'before-destroyed',\n 'destroyed',\n 'after-destroyed',\n 'terminated',\n // default services' events\n 'ticked',\n 'scrolled',\n 'resized',\n 'moved',\n 'loaded',\n 'keyed',\n ],\n };\n\n /**\n * The instance id.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#id\n */\n $id: string;\n\n /**\n * The root element.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#el\n */\n $el: T['$el'] & BaseEl;\n\n /**\n * The state of the component.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#isMounted\n */\n $isMounted = false;\n\n /**\n * Is the component currently mounting itself and its children?\n * @private\n */\n __isMounting = false;\n\n /**\n * Store the event handlers.\n * @private\n */\n __eventHandlers: Map<string, Set<EventListenerOrEventListenerObject>> = new Map();\n\n /**\n * Get the root instance of the app.\n * @deprecated Use `$closest(name)` instead. Will be removed in v4.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#root\n */\n get $root(): Base {\n if (isDev) {\n console.warn(\n `[${this.$id}] $root is deprecated and will be removed in v4. Use $closest(name) instead.`,\n );\n }\n\n if (!this.__parent) {\n return this;\n }\n\n let parent = this.__parent;\n let root = this.__parent;\n\n while (parent) {\n if (!parent.__parent) {\n root = parent;\n }\n\n parent = parent.__parent;\n }\n\n return root;\n }\n\n /**\n * The parent instance if the current instance is registered as a child component in a parent component.\n * @deprecated Use `$closest(name)` instead. Will be removed in v4.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#parent\n */\n get $parent(): (T['$parent'] & Base) | null {\n if (isDev) {\n console.warn(\n `[${this.$id}] $parent is deprecated and will be removed in v4. Use $closest(name) instead.`,\n );\n }\n\n return this.__parent;\n }\n\n /**\n * Internal parent resolution without deprecation warning.\n * @internal\n */\n get __parent(): (T['$parent'] & Base) | null {\n // Walk up the DOM ancestors and resolve the closest mounted instance whose\n // config declares this component as a child, using each element's `__base__`\n // map for an O(1)-per-ancestor lookup. This is O(tree depth) instead of the\n // O(N_instances) global scan (plus `Set` copy) it replaces.\n let el = this.$el.parentElement;\n\n while (el) {\n const baseMap = (el as BaseEl).__base__;\n\n if (baseMap) {\n for (const instance of baseMap.values()) {\n if (instance === 'terminated' || !hasInstance(instance)) continue;\n\n const { components } = instance.$config;\n if (components) {\n for (const component of Object.values(components)) {\n // Sync child: the declared value is the resolved constructor.\n if (component === this.constructor) {\n return instance as T['$parent'] & Base;\n }\n\n // Async/lazy child: the declared value is a loader function, so it\n // never equals `this.constructor`. Its resolved constructor lives\n // in the ancestor's own ChildrenManager, keyed by that same loader\n // function \u2014 read it back to match by resolved identity.\n if (isFunction(component) && !('$isBase' in component)) {\n const resolved = instance.__children.__asyncComponentPromises.get(\n component as BaseAsyncConstructor,\n );\n if (resolved?.status === 'resolved' && resolved.ctor === this.constructor) {\n return instance as T['$parent'] & Base;\n }\n }\n }\n }\n }\n }\n\n el = el.parentElement;\n }\n\n return null;\n }\n\n /**\n * Merge configuration with the parents' configurations.\n * @private\n */\n get __config(): BaseConfig {\n let proto = Object.getPrototypeOf(this);\n let { config } = proto.constructor;\n\n while (proto.constructor.config && proto.constructor.$isBase) {\n config = { ...proto.constructor.config, ...config };\n\n if (proto.constructor.config.options) {\n config.options = { ...proto.constructor.config.options, ...config.options };\n }\n\n if (proto.constructor.config.emits && config.emits) {\n config.emits = [...proto.constructor.config.emits, ...config.emits];\n }\n\n proto = Object.getPrototypeOf(proto);\n }\n\n config.options = config.options ?? {};\n config.refs = config.refs ?? [];\n config.components = config.components ?? {};\n\n return config;\n }\n\n /**\n * The normalized config of the component.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#config\n */\n get $config() {\n return this.__config;\n }\n\n __services: ServicesManager;\n\n /**\n * Services.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#services\n */\n get $services(): ServicesManager {\n return this.__services;\n }\n\n __refs: RefsManager<T['$refs'] & BaseRefs>;\n\n /**\n * Refs.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#refs\n */\n get $refs(): T['$refs'] & BaseRefs {\n return this.__refs.props;\n }\n\n __options: OptionsManager<T['$options'] & BaseOptions>;\n\n /**\n * Options.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#options\n */\n get $options(): T['$options'] & BaseOptions {\n return this.__options.props;\n }\n\n __children: ChildrenManager<T['$children'] & BaseChildren>;\n\n /**\n * Children.\n * @deprecated Use `$query(name)` instead. Will be removed in v4.\n * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#children\n */\n get $children(): T['$children'] & BaseChildren {\n if (isDev) {\n console.warn(\n `[${this.$id}] $children is deprecated and will be removed in v4. Use $query(name) instead.`,\n );\n }\n\n return this.__children.props;\n }\n\n /**\n * Get all descendant component instances matching the given query.\n * Sugar for `queryComponentAll(query, { from: this.$el })`.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#query-query\n */\n $query<U extends Base = Base>(query: string): U[] {\n return queryComponentAll<U>(query, { from: this.$el });\n }\n\n /**\n * Get the closest ancestor component instance matching the given query.\n * Sugar for `closestComponent(query, { from: this.$el })`.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#closest-query\n */\n $closest<U extends Base = Base>(query: string): U | undefined {\n return closestComponent<U>(query, { from: this.$el });\n }\n\n __events: EventsManager;\n\n /**\n * Small helper to log stuff.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#log-content\n */\n get $log(): (...args: unknown[]) => void {\n return this.$options.log ? window.console.log.bind(window, `[${this.$id}]`) : noop;\n }\n\n /**\n * Small helper to make warning easier.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#warn-content\n */\n get $warn(): (...args: unknown[]) => void {\n return this.$options.log ? window.console.warn.bind(window, `[${this.$id}]`) : noop;\n }\n\n /**\n * Small helper to debug information.\n * @internal\n */\n get __debug(): (...args: unknown[]) => void {\n return isDev && this.$options.debug\n ? window.console.log.bind(window, `[debug] [${this.$id}]`)\n : noop;\n }\n\n /**\n * Get manager constructors.\n * @internal\n */\n get __managers(): Managers {\n return {\n ChildrenManager,\n EventsManager,\n OptionsManager,\n RefsManager,\n ServicesManager,\n };\n }\n\n /**\n * Call an instance method and emit corresponding events.\n * @internal\n */\n __callMethod(method: string, ...args: unknown[]): unknown {\n if (isDev) {\n this.__debug('callMethod', method, ...args);\n }\n\n this.$emit(method, ...args);\n\n // We always emit an event, but we do not call the method if it does not exist\n if (!isFunction(this[method])) {\n return null;\n }\n\n if (isDev) {\n this.__debug(method, this, ...args);\n }\n\n return this[method].call(this, ...args);\n }\n\n /**\n * Test if the given event has been bound to the instance.\n *\n * @param {string} event The event's name.\n * @return {boolean} Wether the given event has been bound or not.\n * @internal\n */\n __hasEvent(event: string): boolean {\n const eventHandlers = this.__eventHandlers.get(event);\n return eventHandlers && eventHandlers.size > 0;\n }\n\n /**\n * Class constructor where all the magic takes place.\n *\n * @param {HTMLElement} element The component's root element dd.\n * @link https://js-toolkit.studiometa.dev/api/instantiation.html\n */\n constructor(element: HTMLElement) {\n if (!element) {\n if (isDev) {\n throw new Error('The root element must be defined.');\n }\n return;\n }\n\n const { $config } = this;\n\n if ($config.name === 'Base') {\n if (isDev) {\n throw new Error('The `config.name` property is required.');\n }\n return;\n }\n\n // Add current component to the registry\n addToRegistry($config.name, this.constructor);\n\n this.$id = `${$config.name}-${id}`;\n id += 1;\n\n this.$el = element;\n this.$el.__base__ ??= new Map();\n this.$el.__base__.set($config.name, this);\n\n for (const service of ['Options', 'Services', 'Events', 'Refs', 'Children']) {\n this[`__${service.toLowerCase()}`] = new this.__managers[`${service}Manager`](this);\n }\n\n this.$on('before-mounted', () => {\n addInstance(this);\n });\n this.$on('after-destroyed', () => {\n deleteInstance(this);\n });\n\n if (isDev) {\n this.__debug('constructor', this);\n }\n }\n\n /**\n * Trigger the `mounted` callback.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#mount\n */\n async $mount(): Promise<this> {\n if (this.$isMounted || this.__isMounting) {\n return this;\n }\n\n this.__isMounting = true;\n this.$emit('before-mounted');\n\n if (isDev) {\n this.__debug('$mount');\n }\n\n await Promise.all([\n addToQueue(() => this.__children.registerAll()),\n addToQueue(() => this.__refs.registerAll()),\n addToQueue(() => this.__events.bindRootElement()),\n addToQueue(() => this.__services.enableAll()),\n addToQueue(() => this.__children.mountAll()),\n ]);\n\n await addToQueue(() => {\n this.$isMounted = true;\n this.__callMethod('mounted');\n });\n\n this.__isMounting = false;\n this.$emit('after-mounted');\n\n return this;\n }\n\n /**\n * Update the instance children.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#update\n */\n async $update(): Promise<this> {\n if (isDev) {\n this.__debug('$update');\n }\n\n await Promise.all([\n // Undo\n addToQueue(() => this.__refs.unregisterAll()),\n addToQueue(() => this.__services.disableAll()),\n // Redo\n addToQueue(() => this.__children.registerAll()),\n addToQueue(() => this.__refs.registerAll()),\n addToQueue(() => this.__services.enableAll()),\n // Update\n addToQueue(() => this.__children.updateAll()),\n ]);\n\n await addToQueue(() => this.__callMethod('updated'));\n\n return this;\n }\n\n /**\n * Trigger the `destroyed` callback.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#destroy\n */\n async $destroy(): Promise<this> {\n if (!this.$isMounted) {\n return this;\n }\n\n if (isDev) {\n this.__debug('$destroy');\n }\n\n this.$emit('before-destroyed');\n this.$isMounted = false;\n\n await Promise.all([\n addToQueue(() => this.__events.unbindRootElement()),\n addToQueue(() => this.__refs.unregisterAll()),\n addToQueue(() => this.__services.disableAll()),\n addToQueue(() => this.__children.destroyAll()),\n ]);\n\n await addToQueue(() => this.__callMethod('destroyed'));\n\n this.$emit('after-destroyed');\n\n return this;\n }\n\n /**\n * Terminate a child instance when it is not needed anymore.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#terminate\n */\n async $terminate(): Promise<void> {\n if (isDev) {\n this.__debug('$terminate');\n }\n\n await Promise.all([\n // First, destroy the component.\n addToQueue(() => this.$destroy()),\n // Execute the `terminated` hook if it exists\n addToQueue(() => this.__callMethod('terminated')),\n // Delete instance\n addToQueue(() => this.$el.__base__.set(this.$config.name, 'terminated')),\n ]);\n }\n\n /**\n * Add an emitted event.\n *\n * @param {string} event The event name.\n * @return {void}\n * @internal\n */\n __addEmits(event: string): void {\n const ctor = this.constructor;\n if (isArray(ctor.config.emits)) {\n ctor.config.emits.push(event);\n } else {\n ctor.config.emits = [event];\n }\n }\n\n /**\n * Remove an emitted event.\n *\n * @param {string} event The event name.\n * @return {void}\n * @internal\n */\n __removeEmits(event: string): void {\n const ctor = this.constructor;\n const index = ctor.config.emits.indexOf(event);\n ctor.config.emits.splice(index, 1);\n }\n\n /**\n * Bind a listener function to an event.\n *\n * @param {string} event\n * Name of the event.\n * @param {EventListenerOrEventListenerObject} listener\n * Function to be called.\n * @param {boolean|AddEventListenerOptions} [options]\n * Options for the `removeEventListener` method.\n * @return {() => void}\n * A function to unbind the listener.\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#on-event-callback-options\n */\n $on(\n event: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ): () => void {\n if (isDev) {\n this.__debug('$on', event, listener, options);\n }\n\n let set = this.__eventHandlers.get(event);\n\n if (!set) {\n set = new Set();\n this.__eventHandlers.set(event, set);\n }\n\n set.add(listener);\n\n const target = getEventTarget(this, event, this.__config);\n target?.addEventListener(event, listener, options);\n\n if (isDev) {\n if (!target) {\n console.warn(\n `[${this.$id}]`,\n `The \"${event}\" event is missing from the configuration and is not a native`,\n `event for the root element of type \\`${this.$el.constructor.name}\\`.`,\n );\n }\n }\n\n return () => {\n this.$off(event, listener, options);\n };\n }\n\n /**\n * Unbind a listener function from an event.\n *\n * @param {string} event\n * Name of the event.\n * @param {EventListenerOrEventListenerObject} listener\n * Function to be removed.\n * @param {boolean|EventListenerOptions} [options]\n * Options for the `removeEventListener` method.\n * @return {void}\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#off-event-callback-options\n */\n $off(\n event: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | EventListenerOptions,\n ) {\n if (isDev) {\n this.__debug('$off', event, listener);\n }\n\n this.__eventHandlers.get(event)?.delete(listener);\n\n const target = getEventTarget(this, event, this.__config);\n target?.removeEventListener(event, listener, options);\n }\n\n /**\n * Emits an event.\n *\n * @param {string} event Name of the event.\n * @param {any[]} args The arguments to apply to the functions bound to this event.\n * @return {void}\n * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#emit-event-args\n */\n $emit(event: string | Event, ...args: unknown[]) {\n if (isDev) {\n this.__debug('$emit', event, args);\n }\n\n this.$el.dispatchEvent(\n event instanceof Event ? event : new CustomEvent(event, { detail: args }),\n );\n }\n\n /**\n * Register and mount all instances of the component.\n * @link https://js-toolkit.studiometa.dev/api/static-methods.html#register-nameorselector-string\n */\n static $register<T extends BaseProps = BaseProps, U extends typeof Base<T> = typeof Base<T>>(\n this: U,\n nameOrSelector?: string,\n ): Promise<InstanceType<U>>[] {\n addToRegistry(nameOrSelector ?? this.config.name, this);\n\n return getComponentElements(nameOrSelector ?? this.config.name).map(\n async (el) =>\n getInstanceFromElement(el, this) ?? (new this(el).$mount() as Promise<InstanceType<U>>),\n );\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -7,6 +7,11 @@ export declare class ChildrenManager<T> extends AbstractManager<T> {
7
7
  /**
8
8
  * Store async component promises to avoid calling them multiple times and
9
9
  * waiting for them when they are already resolved.
10
+ *
11
+ * Also read by `Base.__parent` (backing `$parent`/`$root`) to resolve an
12
+ * async/lazy-declared child to its parent: `config.components` holds the
13
+ * loader function, so `__parent` looks up its resolved `ctor` here to match by
14
+ * identity. Keep the `{ status, ctor }` shape in sync with that reader.
10
15
  */
11
16
  __asyncComponentPromises: WeakMap<BaseAsyncConstructor, {
12
17
  promise: ReturnType<BaseAsyncConstructor>;
@@ -4,6 +4,11 @@ class ChildrenManager extends AbstractManager {
4
4
  /**
5
5
  * Store async component promises to avoid calling them multiple times and
6
6
  * waiting for them when they are already resolved.
7
+ *
8
+ * Also read by `Base.__parent` (backing `$parent`/`$root`) to resolve an
9
+ * async/lazy-declared child to its parent: `config.components` holds the
10
+ * loader function, so `__parent` looks up its resolved `ctor` here to match by
11
+ * identity. Keep the `{ status, ctor }` shape in sync with that reader.
7
12
  */
8
13
  __asyncComponentPromises = /* @__PURE__ */ new WeakMap();
9
14
  get registeredNames() {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../packages/js-toolkit/Base/managers/ChildrenManager.ts"],
4
- "sourcesContent": ["import type { Base, BaseConstructor, BaseAsyncConstructor, BaseEl } from '../index.js';\nimport { AbstractManager } from './AbstractManager.js';\nimport { getComponentElements, addToQueue } from '../utils.js';\n\n/**\n * Children manager.\n */\nexport class ChildrenManager<T> extends AbstractManager<T> {\n /**\n * Store async component promises to avoid calling them multiple times and\n * waiting for them when they are already resolved.\n */\n __asyncComponentPromises: WeakMap<\n BaseAsyncConstructor,\n {\n promise: ReturnType<BaseAsyncConstructor>;\n status: 'pending' | 'resolved';\n ctor?: BaseConstructor;\n }\n > = new WeakMap();\n\n get registeredNames(): string[] {\n return Object.keys(this.props);\n }\n\n /**\n * Register instances of all children components.\n */\n async registerAll() {\n for (const [name, component] of Object.entries(this.__config.components)) {\n this.__register(name, component);\n }\n }\n\n /**\n * Mount all child component instances.\n */\n async mountAll() {\n await this.__triggerHookForAll('$mount');\n }\n\n /**\n * Update all child component instances.\n */\n async updateAll() {\n await this.__triggerHookForAll('$update');\n }\n\n /**\n * Destroy all child component instances.\n */\n async destroyAll() {\n await this.__triggerHookForAll('$destroy');\n }\n\n /**\n * Execute the given hook for the given instance.\n *\n * @param {'$mount'|'$update'|'$destroy'} hook The hook to trigger.\n * @param {Base} instance The target instance.\n * @param {string} name The name of the component.\n * @private\n */\n async __triggerHook(hook: '$mount' | '$update' | '$destroy', instance: Base, name: string) {\n if (hook === '$update' && !instance.$isMounted) {\n // eslint-disable-next-line no-param-reassign\n hook = '$mount';\n }\n\n if (hook === '$update' || hook === '$destroy') {\n this.__eventsManager.unbindChild(name, instance);\n }\n\n if (hook === '$update' || hook === '$mount') {\n this.__eventsManager.bindChild(name, instance);\n }\n\n await instance[hook]();\n }\n\n /**\n * Register instance of a child component.\n *\n * @param {string} name\n * The name of the child component.\n * @param {BaseConstructor|BaseAsyncConstructor} component\n * A Base class or a Promise for async components.\n * @private\n */\n __register(name: string, component: BaseConstructor | BaseAsyncConstructor) {\n Object.defineProperty(this.props, name, {\n enumerable: true,\n configurable: true,\n get: () => this.__getValue(name, component),\n });\n }\n\n /**\n * Get children.\n * @private\n */\n __getValue(name: string, component: BaseConstructor | BaseAsyncConstructor) {\n const elements = getComponentElements(name, this.__element);\n\n if (elements.length === 0) {\n return [];\n }\n\n const children = [];\n for (const element of elements) {\n const child = this.__getChild(element, component);\n if (child !== 'terminated') {\n children.push(child);\n }\n }\n\n return children;\n }\n\n /**\n * Get a child component's instance.\n *\n * @param {BaseEl} el\n * The root element of the child component.\n * @param {BaseConstructor|BaseAsyncConstructor} ComponentClass\n * A Base class or a Promise for async components.\n * @return {Base|Promise<Base | 'terminated'>|'terminated'}\n * A Base instance or a Promise resolving to a Base instance.\n * @private\n */\n __getChild(\n el: BaseEl,\n ComponentClass: BaseConstructor | BaseAsyncConstructor,\n ): Base | Promise<Base | 'terminated'> | 'terminated' {\n const asyncComponentPromise = this.__asyncComponentPromises.get(\n ComponentClass as BaseAsyncConstructor,\n );\n\n // Test if we have a constructor and not a promise or if the promise has been resolved\n if (\n '$isBase' in ComponentClass ||\n (asyncComponentPromise && asyncComponentPromise.status === 'resolved')\n ) {\n let ctor = ComponentClass as BaseConstructor;\n\n // Get resolved constructor from weakmap.\n // Only test for existence as the status was checked before.\n if (asyncComponentPromise) {\n ctor = asyncComponentPromise.ctor;\n }\n\n // Return existing instance if it exists\n if (el.__base__ && el.__base__.has(ctor.config.name)) {\n return el.__base__.get(ctor.config.name);\n }\n\n // Return a new instance if the component class is a child of the Base class\n // eslint-disable-next-line new-cap\n const child = new ctor(el);\n return child;\n }\n\n const promise = asyncComponentPromise\n ? asyncComponentPromise.promise\n : ComponentClass(this.__base);\n\n if (!asyncComponentPromise) {\n this.__asyncComponentPromises.set(ComponentClass, {\n promise,\n status: 'pending',\n ctor: undefined,\n });\n }\n\n // Resolve async components\n return promise.then((module) => {\n // @ts-ignore\n const ctor = module.default ?? module;\n\n this.__asyncComponentPromises.set(ComponentClass, {\n promise,\n status: 'resolved',\n ctor,\n });\n\n return this.__getChild(el, ctor);\n });\n }\n\n /**\n * Execute the given hook for all children instances.\n *\n * @param {'$mount'|'$update'|'$destroy'} hook The hook to execute.\n * @private\n */\n async __triggerHookForAll(hook: '$mount' | '$update' | '$destroy') {\n return addToQueue(() => {\n const promises = [];\n for (const name of this.registeredNames) {\n for (const instance of this.props[name]) {\n if (instance instanceof Promise) {\n instance.then((resolvedInstance) =>\n addToQueue(() => this.__triggerHook(hook, resolvedInstance, name)),\n );\n } else {\n promises.push(addToQueue(() => this.__triggerHook(hook, instance, name)));\n }\n }\n }\n return Promise.all(promises);\n });\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Base, BaseConstructor, BaseAsyncConstructor, BaseEl } from '../index.js';\nimport { AbstractManager } from './AbstractManager.js';\nimport { getComponentElements, addToQueue } from '../utils.js';\n\n/**\n * Children manager.\n */\nexport class ChildrenManager<T> extends AbstractManager<T> {\n /**\n * Store async component promises to avoid calling them multiple times and\n * waiting for them when they are already resolved.\n *\n * Also read by `Base.__parent` (backing `$parent`/`$root`) to resolve an\n * async/lazy-declared child to its parent: `config.components` holds the\n * loader function, so `__parent` looks up its resolved `ctor` here to match by\n * identity. Keep the `{ status, ctor }` shape in sync with that reader.\n */\n __asyncComponentPromises: WeakMap<\n BaseAsyncConstructor,\n {\n promise: ReturnType<BaseAsyncConstructor>;\n status: 'pending' | 'resolved';\n ctor?: BaseConstructor;\n }\n > = new WeakMap();\n\n get registeredNames(): string[] {\n return Object.keys(this.props);\n }\n\n /**\n * Register instances of all children components.\n */\n async registerAll() {\n for (const [name, component] of Object.entries(this.__config.components)) {\n this.__register(name, component);\n }\n }\n\n /**\n * Mount all child component instances.\n */\n async mountAll() {\n await this.__triggerHookForAll('$mount');\n }\n\n /**\n * Update all child component instances.\n */\n async updateAll() {\n await this.__triggerHookForAll('$update');\n }\n\n /**\n * Destroy all child component instances.\n */\n async destroyAll() {\n await this.__triggerHookForAll('$destroy');\n }\n\n /**\n * Execute the given hook for the given instance.\n *\n * @param {'$mount'|'$update'|'$destroy'} hook The hook to trigger.\n * @param {Base} instance The target instance.\n * @param {string} name The name of the component.\n * @private\n */\n async __triggerHook(hook: '$mount' | '$update' | '$destroy', instance: Base, name: string) {\n if (hook === '$update' && !instance.$isMounted) {\n // eslint-disable-next-line no-param-reassign\n hook = '$mount';\n }\n\n if (hook === '$update' || hook === '$destroy') {\n this.__eventsManager.unbindChild(name, instance);\n }\n\n if (hook === '$update' || hook === '$mount') {\n this.__eventsManager.bindChild(name, instance);\n }\n\n await instance[hook]();\n }\n\n /**\n * Register instance of a child component.\n *\n * @param {string} name\n * The name of the child component.\n * @param {BaseConstructor|BaseAsyncConstructor} component\n * A Base class or a Promise for async components.\n * @private\n */\n __register(name: string, component: BaseConstructor | BaseAsyncConstructor) {\n Object.defineProperty(this.props, name, {\n enumerable: true,\n configurable: true,\n get: () => this.__getValue(name, component),\n });\n }\n\n /**\n * Get children.\n * @private\n */\n __getValue(name: string, component: BaseConstructor | BaseAsyncConstructor) {\n const elements = getComponentElements(name, this.__element);\n\n if (elements.length === 0) {\n return [];\n }\n\n const children = [];\n for (const element of elements) {\n const child = this.__getChild(element, component);\n if (child !== 'terminated') {\n children.push(child);\n }\n }\n\n return children;\n }\n\n /**\n * Get a child component's instance.\n *\n * @param {BaseEl} el\n * The root element of the child component.\n * @param {BaseConstructor|BaseAsyncConstructor} ComponentClass\n * A Base class or a Promise for async components.\n * @return {Base|Promise<Base | 'terminated'>|'terminated'}\n * A Base instance or a Promise resolving to a Base instance.\n * @private\n */\n __getChild(\n el: BaseEl,\n ComponentClass: BaseConstructor | BaseAsyncConstructor,\n ): Base | Promise<Base | 'terminated'> | 'terminated' {\n const asyncComponentPromise = this.__asyncComponentPromises.get(\n ComponentClass as BaseAsyncConstructor,\n );\n\n // Test if we have a constructor and not a promise or if the promise has been resolved\n if (\n '$isBase' in ComponentClass ||\n (asyncComponentPromise && asyncComponentPromise.status === 'resolved')\n ) {\n let ctor = ComponentClass as BaseConstructor;\n\n // Get resolved constructor from weakmap.\n // Only test for existence as the status was checked before.\n if (asyncComponentPromise) {\n ctor = asyncComponentPromise.ctor;\n }\n\n // Return existing instance if it exists\n if (el.__base__ && el.__base__.has(ctor.config.name)) {\n return el.__base__.get(ctor.config.name);\n }\n\n // Return a new instance if the component class is a child of the Base class\n // eslint-disable-next-line new-cap\n const child = new ctor(el);\n return child;\n }\n\n const promise = asyncComponentPromise\n ? asyncComponentPromise.promise\n : ComponentClass(this.__base);\n\n if (!asyncComponentPromise) {\n this.__asyncComponentPromises.set(ComponentClass, {\n promise,\n status: 'pending',\n ctor: undefined,\n });\n }\n\n // Resolve async components\n return promise.then((module) => {\n // @ts-ignore\n const ctor = module.default ?? module;\n\n this.__asyncComponentPromises.set(ComponentClass, {\n promise,\n status: 'resolved',\n ctor,\n });\n\n return this.__getChild(el, ctor);\n });\n }\n\n /**\n * Execute the given hook for all children instances.\n *\n * @param {'$mount'|'$update'|'$destroy'} hook The hook to execute.\n * @private\n */\n async __triggerHookForAll(hook: '$mount' | '$update' | '$destroy') {\n return addToQueue(() => {\n const promises = [];\n for (const name of this.registeredNames) {\n for (const instance of this.props[name]) {\n if (instance instanceof Promise) {\n instance.then((resolvedInstance) =>\n addToQueue(() => this.__triggerHook(hook, resolvedInstance, name)),\n );\n } else {\n promises.push(addToQueue(() => this.__triggerHook(hook, instance, name)));\n }\n }\n }\n return Promise.all(promises);\n });\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/Base/utils.js CHANGED
@@ -1,4 +1,4 @@
1
- import { isArray, isDefined, SmartQueue, dashCase } from "../utils/index.js";
1
+ import { isArray, isDefined, SmartQueue, dashCase, isDev } from "../utils/index.js";
2
2
  import { features } from "./features.js";
3
3
  import { useMutation } from "../services/MutationService.js";
4
4
  import { getInstanceFromElement } from "../helpers/getInstanceFromElement.js";
@@ -115,6 +115,11 @@ function mutationCallback() {
115
115
  }
116
116
  function addToRegistry(nameOrSelector, ctor) {
117
117
  if (registry().has(nameOrSelector)) {
118
+ if (isDev && registry().get(nameOrSelector) !== ctor) {
119
+ console.warn(
120
+ `[${nameOrSelector}] A different component is already registered under this name. Registration is ignored \u2014 like \`customElements.define\`, a name maps to a single component. Give this component a unique \`config.name\` (or use \`withExtraConfig\`, which renames automatically).`
121
+ );
122
+ }
118
123
  return;
119
124
  }
120
125
  registry().set(nameOrSelector, ctor);
package/Base/utils.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../packages/js-toolkit/Base/utils.ts"],
4
- "sourcesContent": ["import { isArray, isDefined, SmartQueue, dashCase } from '../utils/index.js';\nimport type { Base, BaseConfig, BaseConstructor } from './index.js';\nimport { features } from './features.js';\nimport { useMutation } from '../services/MutationService.js';\nimport { getInstanceFromElement } from '../helpers/getInstanceFromElement.js';\n\nlet queue: SmartQueue;\n\n/**\n * Add a task to the main queue.\n */\nexport function addToQueue(fn: () => unknown) {\n if (features.get('blocking')) {\n fn();\n return;\n }\n\n if (!queue) {\n queue = new SmartQueue();\n }\n\n return queue.add(fn);\n}\n\nconst selectors = new Map();\n\n// Separator used for multi-component declaration in `data-component` attributeS.\nconst separator = ' ';\n\n/**\n * Get the selector for a given component.\n */\nexport function getSelector(nameOrSelector: string): string {\n const { component } = features.get('attributes');\n const prefix = features.get('prefix');\n const key = prefix + component + nameOrSelector;\n\n if (!selectors.has(key)) {\n const parts = [\n // Tag select\n `${prefix}-${dashCase(nameOrSelector)}`,\n // Single selector\n `[${component}=\"${nameOrSelector}\"]`,\n // Selector in the middle of a list of selectors\n `[${component}*=\"${separator}${nameOrSelector}${separator}\"]`,\n // Selector at the end of a list of selectors\n `[${component}$=\"${separator}${nameOrSelector}\"]`,\n // Selector at the beginning of a list of selectors\n `[${component}^=\"${nameOrSelector}${separator}\"]`,\n ];\n selectors.set(key, parts.join(','));\n }\n\n return selectors.get(key);\n}\n\n/**\n * Get a list of elements based on the name of a component.\n *\n * @param {string} nameOrSelector\n * The name or selector to used for this component.\n * @param {HTMLElement|Document} element\n * The root element on which to query the selector, defaults to `document`.\n * @return {Array<HTMLElement>}\n * A list of elements on which the component should be mounted.\n */\nexport function getComponentElements(\n nameOrSelector: string,\n element: HTMLElement | Document = document,\n): HTMLElement[] {\n const selector = getSelector(nameOrSelector);\n let elements = [];\n\n try {\n elements = Array.from(element.querySelectorAll(selector));\n // eslint-disable-next-line no-empty\n } catch {}\n\n // If no child component found with the default selector, and if the selector does not\n // start with an uppercase letter, matching a component's name, try a classic DOM selector.\n if (elements.length === 0 && nameOrSelector[0] === nameOrSelector[0].toLowerCase()) {\n elements = Array.from(element.querySelectorAll(nameOrSelector));\n }\n\n return elements;\n}\n\n/**\n * Test if an event is defined in the given config.\n */\nexport function eventIsDefinedInConfig(event: string, config: BaseConfig): boolean {\n return isArray(config.emits) && config.emits.includes(event);\n}\n\n/**\n * Test if an event can be used on the given element.\n */\nexport function eventIsNative(event: string, element: HTMLElement): boolean {\n return isDefined(element[`on${event}`]);\n}\n\n/**\n * Get the target of a given event.\n */\nexport function getEventTarget(instance: Base, event: string, config: BaseConfig): Base['$el'] {\n if (eventIsDefinedInConfig(event, config) || eventIsNative(event, instance.$el)) {\n return instance.$el;\n }\n}\n\n/**\n * Get the global instance storage.\n * We attach it to `globalThis` so it can be shared between different\n * instances of the framework.\n */\nfunction getInstancesStorage(): Set<Base> {\n return (globalThis.__JS_TOOLKIT_INSTANCES__ ??= new Set<Base>());\n}\n\n/**\n * Get the global elements storage.\n * It will hold reference to all elements with at least one component attached to it.\n */\nfunction getElementsStorage(): Set<HTMLElement & { __base__: Map<string, Base> }> {\n return (globalThis.__JS_TOOLKIT_ELEMENTS__ ??= new Set<\n HTMLElement & { __base__: Map<string, Base> }\n >());\n}\n\n/**\n * Get all mounted instances or the ones from a given component.\n * @link https://js-toolkit.studiometa.dev/api/helpers/getInstances.html\n */\nexport function getInstances(): ReadonlySet<Base>;\nexport function getInstances<T extends BaseConstructor = BaseConstructor>(\n ctor: T,\n): Set<InstanceType<T>>;\nexport function getInstances<T extends BaseConstructor = BaseConstructor>(\n ctor?: T,\n): ReadonlySet<InstanceType<T>> | ReadonlySet<Base> {\n if (isDefined(ctor)) {\n const filteredInstances = new Set<InstanceType<T>>();\n for (const instance of getInstancesStorage()) {\n if (instance instanceof ctor) {\n filteredInstances.add(instance as InstanceType<T>);\n }\n }\n return filteredInstances;\n }\n\n return new Set(getInstancesStorage());\n}\n\nexport function getElements() {\n return new Set(getElementsStorage());\n}\n\nexport function addInstance(instance: Base) {\n getInstancesStorage().add(instance);\n getElementsStorage().add(instance.$el as HTMLElement & { __base__: Map<string, Base> });\n}\n\nexport function deleteInstance(instance: Base) {\n getInstancesStorage().delete(instance);\n getElementsStorage().delete(instance.$el as HTMLElement & { __base__: Map<string, Base> });\n}\n\n/**\n * Test whether an instance is currently registered in the global storage.\n * Membership is added on `before-mounted` and removed on `after-destroyed`,\n * so this is an O(1) check for \"is this instance live\" without copying the Set.\n */\nexport function hasInstance(instance: Base): boolean {\n return getInstancesStorage().has(instance);\n}\n\nconst registryKey = '__JS_TOOLKIT_REGISTRY__';\n\nfunction registry() {\n return (globalThis[registryKey] ??= new Map<string, BaseConstructor>());\n}\n\nfunction mutationCallback() {\n addToQueue(() => {\n for (const [nameOrSelector, ctor] of registry()) {\n for (const el of getComponentElements(nameOrSelector)) {\n if (!getInstanceFromElement(el, ctor)) {\n new ctor(el).$mount();\n }\n }\n }\n });\n\n addToQueue(() => {\n for (const instance of getInstances()) {\n if (!instance.$el.isConnected) {\n instance.$terminate();\n }\n }\n });\n}\n\nexport function addToRegistry(nameOrSelector: string, ctor: BaseConstructor) {\n if (registry().has(nameOrSelector)) {\n return;\n }\n\n registry().set(nameOrSelector, ctor);\n\n // Add children components to the registry\n if (ctor.config?.components) {\n for (const [selector, childConstructor] of Object.entries(ctor.config?.components)) {\n if ('$isBase' in childConstructor && childConstructor.$isBase) {\n addToRegistry(selector, childConstructor);\n }\n }\n }\n\n const mutation = useMutation(document, { childList: true, subtree: true });\n if (!mutation.has(registryKey)) {\n mutation.add(registryKey, mutationCallback);\n }\n}\n\n/**\n * Find the closest instance from the given element in the given set of Base instances.\n */\nexport function findClosestInstance<T extends Base = Base>(\n element: HTMLElement,\n instances: Set<T>,\n): T {\n let closest = null;\n let minDepth = Infinity;\n\n for (const instance of instances) {\n let depth = 0;\n let el = element;\n while (el && el !== instance.$el) {\n depth++;\n el = el.parentElement;\n }\n\n if (depth < minDepth) {\n minDepth = depth;\n closest = instance;\n }\n }\n\n return closest;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { isArray, isDefined, SmartQueue, dashCase, isDev } from '../utils/index.js';\nimport type { Base, BaseConfig, BaseConstructor } from './index.js';\nimport { features } from './features.js';\nimport { useMutation } from '../services/MutationService.js';\nimport { getInstanceFromElement } from '../helpers/getInstanceFromElement.js';\n\nlet queue: SmartQueue;\n\n/**\n * Add a task to the main queue.\n */\nexport function addToQueue(fn: () => unknown) {\n if (features.get('blocking')) {\n fn();\n return;\n }\n\n if (!queue) {\n queue = new SmartQueue();\n }\n\n return queue.add(fn);\n}\n\nconst selectors = new Map();\n\n// Separator used for multi-component declaration in `data-component` attributeS.\nconst separator = ' ';\n\n/**\n * Get the selector for a given component.\n */\nexport function getSelector(nameOrSelector: string): string {\n const { component } = features.get('attributes');\n const prefix = features.get('prefix');\n const key = prefix + component + nameOrSelector;\n\n if (!selectors.has(key)) {\n const parts = [\n // Tag select\n `${prefix}-${dashCase(nameOrSelector)}`,\n // Single selector\n `[${component}=\"${nameOrSelector}\"]`,\n // Selector in the middle of a list of selectors\n `[${component}*=\"${separator}${nameOrSelector}${separator}\"]`,\n // Selector at the end of a list of selectors\n `[${component}$=\"${separator}${nameOrSelector}\"]`,\n // Selector at the beginning of a list of selectors\n `[${component}^=\"${nameOrSelector}${separator}\"]`,\n ];\n selectors.set(key, parts.join(','));\n }\n\n return selectors.get(key);\n}\n\n/**\n * Get a list of elements based on the name of a component.\n *\n * @param {string} nameOrSelector\n * The name or selector to used for this component.\n * @param {HTMLElement|Document} element\n * The root element on which to query the selector, defaults to `document`.\n * @return {Array<HTMLElement>}\n * A list of elements on which the component should be mounted.\n */\nexport function getComponentElements(\n nameOrSelector: string,\n element: HTMLElement | Document = document,\n): HTMLElement[] {\n const selector = getSelector(nameOrSelector);\n let elements = [];\n\n try {\n elements = Array.from(element.querySelectorAll(selector));\n // eslint-disable-next-line no-empty\n } catch {}\n\n // If no child component found with the default selector, and if the selector does not\n // start with an uppercase letter, matching a component's name, try a classic DOM selector.\n if (elements.length === 0 && nameOrSelector[0] === nameOrSelector[0].toLowerCase()) {\n elements = Array.from(element.querySelectorAll(nameOrSelector));\n }\n\n return elements;\n}\n\n/**\n * Test if an event is defined in the given config.\n */\nexport function eventIsDefinedInConfig(event: string, config: BaseConfig): boolean {\n return isArray(config.emits) && config.emits.includes(event);\n}\n\n/**\n * Test if an event can be used on the given element.\n */\nexport function eventIsNative(event: string, element: HTMLElement): boolean {\n return isDefined(element[`on${event}`]);\n}\n\n/**\n * Get the target of a given event.\n */\nexport function getEventTarget(instance: Base, event: string, config: BaseConfig): Base['$el'] {\n if (eventIsDefinedInConfig(event, config) || eventIsNative(event, instance.$el)) {\n return instance.$el;\n }\n}\n\n/**\n * Get the global instance storage.\n * We attach it to `globalThis` so it can be shared between different\n * instances of the framework.\n */\nfunction getInstancesStorage(): Set<Base> {\n return (globalThis.__JS_TOOLKIT_INSTANCES__ ??= new Set<Base>());\n}\n\n/**\n * Get the global elements storage.\n * It will hold reference to all elements with at least one component attached to it.\n */\nfunction getElementsStorage(): Set<HTMLElement & { __base__: Map<string, Base> }> {\n return (globalThis.__JS_TOOLKIT_ELEMENTS__ ??= new Set<\n HTMLElement & { __base__: Map<string, Base> }\n >());\n}\n\n/**\n * Get all mounted instances or the ones from a given component.\n * @link https://js-toolkit.studiometa.dev/api/helpers/getInstances.html\n */\nexport function getInstances(): ReadonlySet<Base>;\nexport function getInstances<T extends BaseConstructor = BaseConstructor>(\n ctor: T,\n): Set<InstanceType<T>>;\nexport function getInstances<T extends BaseConstructor = BaseConstructor>(\n ctor?: T,\n): ReadonlySet<InstanceType<T>> | ReadonlySet<Base> {\n if (isDefined(ctor)) {\n const filteredInstances = new Set<InstanceType<T>>();\n for (const instance of getInstancesStorage()) {\n if (instance instanceof ctor) {\n filteredInstances.add(instance as InstanceType<T>);\n }\n }\n return filteredInstances;\n }\n\n return new Set(getInstancesStorage());\n}\n\nexport function getElements() {\n return new Set(getElementsStorage());\n}\n\nexport function addInstance(instance: Base) {\n getInstancesStorage().add(instance);\n getElementsStorage().add(instance.$el as HTMLElement & { __base__: Map<string, Base> });\n}\n\nexport function deleteInstance(instance: Base) {\n getInstancesStorage().delete(instance);\n getElementsStorage().delete(instance.$el as HTMLElement & { __base__: Map<string, Base> });\n}\n\n/**\n * Test whether an instance is currently registered in the global storage.\n * Membership is added on `before-mounted` and removed on `after-destroyed`,\n * so this is an O(1) check for \"is this instance live\" without copying the Set.\n */\nexport function hasInstance(instance: Base): boolean {\n return getInstancesStorage().has(instance);\n}\n\nconst registryKey = '__JS_TOOLKIT_REGISTRY__';\n\nfunction registry() {\n return (globalThis[registryKey] ??= new Map<string, BaseConstructor>());\n}\n\nfunction mutationCallback() {\n addToQueue(() => {\n for (const [nameOrSelector, ctor] of registry()) {\n for (const el of getComponentElements(nameOrSelector)) {\n if (!getInstanceFromElement(el, ctor)) {\n new ctor(el).$mount();\n }\n }\n }\n });\n\n addToQueue(() => {\n for (const instance of getInstances()) {\n if (!instance.$el.isConnected) {\n instance.$terminate();\n }\n }\n });\n}\n\nexport function addToRegistry(nameOrSelector: string, ctor: BaseConstructor) {\n if (registry().has(nameOrSelector)) {\n if (isDev && registry().get(nameOrSelector) !== ctor) {\n console.warn(\n `[${nameOrSelector}] A different component is already registered under this name. ` +\n 'Registration is ignored \u2014 like `customElements.define`, a name maps to a single ' +\n 'component. Give this component a unique `config.name` (or use `withExtraConfig`, ' +\n 'which renames automatically).',\n );\n }\n return;\n }\n\n registry().set(nameOrSelector, ctor);\n\n // Add children components to the registry\n if (ctor.config?.components) {\n for (const [selector, childConstructor] of Object.entries(ctor.config?.components)) {\n if ('$isBase' in childConstructor && childConstructor.$isBase) {\n addToRegistry(selector, childConstructor);\n }\n }\n }\n\n const mutation = useMutation(document, { childList: true, subtree: true });\n if (!mutation.has(registryKey)) {\n mutation.add(registryKey, mutationCallback);\n }\n}\n\n/**\n * Find the closest instance from the given element in the given set of Base instances.\n */\nexport function findClosestInstance<T extends Base = Base>(\n element: HTMLElement,\n instances: Set<T>,\n): T {\n let closest = null;\n let minDepth = Infinity;\n\n for (const instance of instances) {\n let depth = 0;\n let el = element;\n while (el && el !== instance.$el) {\n depth++;\n el = el.parentElement;\n }\n\n if (depth < minDepth) {\n minDepth = depth;\n closest = instance;\n }\n }\n\n return closest;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiometa/js-toolkit",
3
- "version": "3.6.0",
3
+ "version": "3.6.2",
4
4
  "description": "A set of useful little bits of JavaScript to boost your project! 🚀",
5
5
  "publishConfig": {
6
6
  "access": "public"