@studiometa/js-toolkit 3.4.1 → 3.4.3

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.d.ts CHANGED
@@ -60,19 +60,23 @@ export declare class Base<T extends BaseProps = BaseProps> {
60
60
  */
61
61
  static readonly $isBase: true;
62
62
  /**
63
- * The instance parent.
63
+ * Config.
64
+ * @link https://js-toolkit.studiometa.dev/api/configuration.html
64
65
  */
65
- $parent: T['$parent'] & Base;
66
+ static config: BaseConfig;
66
67
  /**
67
68
  * The instance id.
69
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#id
68
70
  */
69
71
  $id: string;
70
72
  /**
71
73
  * The root element.
74
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#el
72
75
  */
73
76
  $el: T['$el'] & BaseEl;
74
77
  /**
75
78
  * The state of the component.
79
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#isMounted
76
80
  */
77
81
  $isMounted: boolean;
78
82
  /**
@@ -87,42 +91,72 @@ export declare class Base<T extends BaseProps = BaseProps> {
87
91
  __eventHandlers: Map<string, Set<EventListenerOrEventListenerObject>>;
88
92
  /**
89
93
  * Get the root instance of the app.
94
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#root
90
95
  */
91
96
  get $root(): Base;
97
+ /**
98
+ * The parent instance if the current instance is registered as a child component in a parent component.
99
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#parent
100
+ */
101
+ get $parent(): T['$parent'] & Base | null;
92
102
  /**
93
103
  * Merge configuration with the parents' configurations.
94
104
  * @private
95
105
  */
96
106
  get __config(): BaseConfig;
107
+ /**
108
+ * The normalized config of the component.
109
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#config
110
+ */
97
111
  get $config(): BaseConfig;
98
- static config: BaseConfig;
99
112
  __services: ServicesManager;
113
+ /**
114
+ * Services.
115
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#services
116
+ */
100
117
  get $services(): ServicesManager;
101
118
  __refs: RefsManager<T['$refs'] & BaseRefs>;
119
+ /**
120
+ * Refs.
121
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#refs
122
+ */
102
123
  get $refs(): T['$refs'] & BaseRefs;
103
124
  __options: OptionsManager<T['$options'] & BaseOptions>;
125
+ /**
126
+ * Options.
127
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#options
128
+ */
104
129
  get $options(): T['$options'] & BaseOptions;
105
130
  __children: ChildrenManager<T['$children'] & BaseChildren>;
131
+ /**
132
+ * Children.
133
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#children
134
+ */
106
135
  get $children(): T['$children'] & BaseChildren;
107
136
  __events: EventsManager;
108
137
  /**
109
138
  * Small helper to log stuff.
139
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#log-content
110
140
  */
111
141
  get $log(): (...args: unknown[]) => void;
112
142
  /**
113
143
  * Small helper to make warning easier.
144
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#warn-content
114
145
  */
115
146
  get $warn(): (...args: unknown[]) => void;
116
147
  /**
117
148
  * Small helper to debug information.
149
+ * @internal
118
150
  */
119
151
  get __debug(): (...args: unknown[]) => void;
120
152
  /**
121
153
  * Get manager constructors.
154
+ * @internal
122
155
  */
123
156
  get __managers(): Managers;
124
157
  /**
125
158
  * Call an instance method and emit corresponding events.
159
+ * @internal
126
160
  */
127
161
  __callMethod(method: string, ...args: unknown[]): unknown;
128
162
  /**
@@ -130,28 +164,34 @@ export declare class Base<T extends BaseProps = BaseProps> {
130
164
  *
131
165
  * @param {string} event The event's name.
132
166
  * @return {boolean} Wether the given event has been bound or not.
167
+ * @internal
133
168
  */
134
169
  __hasEvent(event: string): boolean;
135
170
  /**
136
171
  * Class constructor where all the magic takes place.
137
172
  *
138
173
  * @param {HTMLElement} element The component's root element dd.
174
+ * @link https://js-toolkit.studiometa.dev/api/instantiation.html
139
175
  */
140
176
  constructor(element: HTMLElement);
141
177
  /**
142
178
  * Trigger the `mounted` callback.
179
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#mount
143
180
  */
144
181
  $mount(): Promise<this>;
145
182
  /**
146
183
  * Update the instance children.
184
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#update
147
185
  */
148
186
  $update(): Promise<this>;
149
187
  /**
150
188
  * Trigger the `destroyed` callback.
189
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#destroy
151
190
  */
152
191
  $destroy(): Promise<this>;
153
192
  /**
154
193
  * Terminate a child instance when it is not needed anymore.
194
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#terminate
155
195
  */
156
196
  $terminate(): Promise<void>;
157
197
  /**
@@ -159,6 +199,7 @@ export declare class Base<T extends BaseProps = BaseProps> {
159
199
  *
160
200
  * @param {string} event The event name.
161
201
  * @return {void}
202
+ * @internal
162
203
  */
163
204
  __addEmits(event: string): void;
164
205
  /**
@@ -166,6 +207,7 @@ export declare class Base<T extends BaseProps = BaseProps> {
166
207
  *
167
208
  * @param {string} event The event name.
168
209
  * @return {void}
210
+ * @internal
169
211
  */
170
212
  __removeEmits(event: string): void;
171
213
  /**
@@ -179,6 +221,7 @@ export declare class Base<T extends BaseProps = BaseProps> {
179
221
  * Options for the `removeEventListener` method.
180
222
  * @return {() => void}
181
223
  * A function to unbind the listener.
224
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#on-event-callback-options
182
225
  */
183
226
  $on(event: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): () => void;
184
227
  /**
@@ -191,6 +234,7 @@ export declare class Base<T extends BaseProps = BaseProps> {
191
234
  * @param {boolean|EventListenerOptions} [options]
192
235
  * Options for the `removeEventListener` method.
193
236
  * @return {void}
237
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#off-event-callback-options
194
238
  */
195
239
  $off(event: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
196
240
  /**
@@ -199,10 +243,12 @@ export declare class Base<T extends BaseProps = BaseProps> {
199
243
  * @param {string} event Name of the event.
200
244
  * @param {any[]} args The arguments to apply to the functions bound to this event.
201
245
  * @return {void}
246
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#emit-event-args
202
247
  */
203
248
  $emit(event: string | Event, ...args: unknown[]): void;
204
249
  /**
205
250
  * Register and mount all instances of the component.
251
+ * @link https://js-toolkit.studiometa.dev/api/static-methods.html#register-nameorselector-string
206
252
  */
207
253
  static $register<T extends BaseProps = BaseProps, U extends typeof Base<T> = typeof Base<T>>(this: U, nameOrSelector?: string): Promise<InstanceType<U>>[];
208
254
  }
package/Base/Base.js CHANGED
@@ -4,7 +4,9 @@ import {
4
4
  addToQueue,
5
5
  addInstance,
6
6
  deleteInstance,
7
- addToRegistry
7
+ addToRegistry,
8
+ getInstances,
9
+ findClosestInstance
8
10
  } from "./utils.js";
9
11
  import {
10
12
  ChildrenManager,
@@ -22,19 +24,43 @@ class Base {
22
24
  */
23
25
  static $isBase = true;
24
26
  /**
25
- * The instance parent.
27
+ * Config.
28
+ * @link https://js-toolkit.studiometa.dev/api/configuration.html
26
29
  */
27
- $parent = null;
30
+ static config = {
31
+ name: "Base",
32
+ emits: [
33
+ // hook events
34
+ "before-mounted",
35
+ "mounted",
36
+ "after-mounted",
37
+ "updated",
38
+ "before-destroyed",
39
+ "destroyed",
40
+ "after-destroyed",
41
+ "terminated",
42
+ // default services' events
43
+ "ticked",
44
+ "scrolled",
45
+ "resized",
46
+ "moved",
47
+ "loaded",
48
+ "keyed"
49
+ ]
50
+ };
28
51
  /**
29
52
  * The instance id.
53
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#id
30
54
  */
31
55
  $id;
32
56
  /**
33
57
  * The root element.
58
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#el
34
59
  */
35
60
  $el;
36
61
  /**
37
62
  * The state of the component.
63
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#isMounted
38
64
  */
39
65
  $isMounted = false;
40
66
  /**
@@ -49,6 +75,7 @@ class Base {
49
75
  __eventHandlers = /* @__PURE__ */ new Map();
50
76
  /**
51
77
  * Get the root instance of the app.
78
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#root
52
79
  */
53
80
  get $root() {
54
81
  if (!this.$parent) {
@@ -64,6 +91,21 @@ class Base {
64
91
  }
65
92
  return root;
66
93
  }
94
+ /**
95
+ * The parent instance if the current instance is registered as a child component in a parent component.
96
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#parent
97
+ */
98
+ get $parent() {
99
+ const parents = /* @__PURE__ */ new Set();
100
+ for (const instance of getInstances()) {
101
+ if (!instance.$config.components) continue;
102
+ if (Object.values(instance.$config.components).includes(this.constructor) && instance.$el.contains(this.$el)) {
103
+ parents.add(instance);
104
+ }
105
+ }
106
+ const closest = findClosestInstance(this.$el, parents);
107
+ return closest ?? null;
108
+ }
67
109
  /**
68
110
  * Merge configuration with the parents' configurations.
69
111
  * @private
@@ -86,64 +128,70 @@ class Base {
86
128
  config.components = config.components ?? {};
87
129
  return config;
88
130
  }
131
+ /**
132
+ * The normalized config of the component.
133
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#config
134
+ */
89
135
  get $config() {
90
136
  return this.__config;
91
137
  }
92
- static config = {
93
- name: "Base",
94
- emits: [
95
- // hook events
96
- "before-mounted",
97
- "mounted",
98
- "updated",
99
- "destroyed",
100
- "terminated",
101
- // default services' events
102
- "ticked",
103
- "scrolled",
104
- "resized",
105
- "moved",
106
- "loaded",
107
- "keyed"
108
- ]
109
- };
110
138
  __services;
139
+ /**
140
+ * Services.
141
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#services
142
+ */
111
143
  get $services() {
112
144
  return this.__services;
113
145
  }
114
146
  __refs;
147
+ /**
148
+ * Refs.
149
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#refs
150
+ */
115
151
  get $refs() {
116
152
  return this.__refs.props;
117
153
  }
118
154
  __options;
155
+ /**
156
+ * Options.
157
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#options
158
+ */
119
159
  get $options() {
120
160
  return this.__options.props;
121
161
  }
122
162
  __children;
163
+ /**
164
+ * Children.
165
+ * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#children
166
+ */
123
167
  get $children() {
124
168
  return this.__children.props;
125
169
  }
126
170
  __events;
127
171
  /**
128
172
  * Small helper to log stuff.
173
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#log-content
129
174
  */
130
175
  get $log() {
131
176
  return this.$options.log ? window.console.log.bind(window, `[${this.$id}]`) : noop;
132
177
  }
133
178
  /**
134
179
  * Small helper to make warning easier.
180
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#warn-content
135
181
  */
136
182
  get $warn() {
137
183
  return this.$options.log ? window.console.warn.bind(window, `[${this.$id}]`) : noop;
138
184
  }
139
185
  /**
140
186
  * Small helper to debug information.
187
+ * @internal
141
188
  */
142
189
  get __debug() {
143
190
  return isDev && this.$options.debug ? window.console.log.bind(window, `[debug] [${this.$id}]`) : noop;
144
191
  }
145
192
  /**
146
193
  * Get manager constructors.
194
+ * @internal
147
195
  */
148
196
  get __managers() {
149
197
  return {
@@ -156,6 +204,7 @@ class Base {
156
204
  }
157
205
  /**
158
206
  * Call an instance method and emit corresponding events.
207
+ * @internal
159
208
  */
160
209
  __callMethod(method, ...args) {
161
210
  if (isDev) {
@@ -175,6 +224,7 @@ class Base {
175
224
  *
176
225
  * @param {string} event The event's name.
177
226
  * @return {boolean} Wether the given event has been bound or not.
227
+ * @internal
178
228
  */
179
229
  __hasEvent(event) {
180
230
  const eventHandlers = this.__eventHandlers.get(event);
@@ -184,6 +234,7 @@ class Base {
184
234
  * Class constructor where all the magic takes place.
185
235
  *
186
236
  * @param {HTMLElement} element The component's root element dd.
237
+ * @link https://js-toolkit.studiometa.dev/api/instantiation.html
187
238
  */
188
239
  constructor(element) {
189
240
  if (!element) {
@@ -208,10 +259,10 @@ class Base {
208
259
  for (const service of ["Options", "Services", "Events", "Refs", "Children"]) {
209
260
  this[`__${service.toLowerCase()}`] = new this.__managers[`${service}Manager`](this);
210
261
  }
211
- this.$on("mounted", () => {
262
+ this.$on("before-mounted", () => {
212
263
  addInstance(this);
213
264
  });
214
- this.$on("destroyed", () => {
265
+ this.$on("after-destroyed", () => {
215
266
  deleteInstance(this);
216
267
  });
217
268
  if (isDev) {
@@ -220,6 +271,7 @@ class Base {
220
271
  }
221
272
  /**
222
273
  * Trigger the `mounted` callback.
274
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#mount
223
275
  */
224
276
  async $mount() {
225
277
  if (this.$isMounted || this.__isMounting) {
@@ -242,10 +294,12 @@ class Base {
242
294
  this.__callMethod("mounted");
243
295
  });
244
296
  this.__isMounting = false;
297
+ this.$emit("after-mounted");
245
298
  return this;
246
299
  }
247
300
  /**
248
301
  * Update the instance children.
302
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#update
249
303
  */
250
304
  async $update() {
251
305
  if (isDev) {
@@ -267,6 +321,7 @@ class Base {
267
321
  }
268
322
  /**
269
323
  * Trigger the `destroyed` callback.
324
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#destroy
270
325
  */
271
326
  async $destroy() {
272
327
  if (!this.$isMounted) {
@@ -275,6 +330,7 @@ class Base {
275
330
  if (isDev) {
276
331
  this.__debug("$destroy");
277
332
  }
333
+ this.$emit("before-destroyed");
278
334
  this.$isMounted = false;
279
335
  await Promise.all([
280
336
  addToQueue(() => this.__events.unbindRootElement()),
@@ -283,10 +339,12 @@ class Base {
283
339
  addToQueue(() => this.__children.destroyAll())
284
340
  ]);
285
341
  await addToQueue(() => this.__callMethod("destroyed"));
342
+ this.$emit("after-destroyed");
286
343
  return this;
287
344
  }
288
345
  /**
289
346
  * Terminate a child instance when it is not needed anymore.
347
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#terminate
290
348
  */
291
349
  async $terminate() {
292
350
  if (isDev) {
@@ -306,6 +364,7 @@ class Base {
306
364
  *
307
365
  * @param {string} event The event name.
308
366
  * @return {void}
367
+ * @internal
309
368
  */
310
369
  __addEmits(event) {
311
370
  const ctor = this.constructor;
@@ -320,6 +379,7 @@ class Base {
320
379
  *
321
380
  * @param {string} event The event name.
322
381
  * @return {void}
382
+ * @internal
323
383
  */
324
384
  __removeEmits(event) {
325
385
  const ctor = this.constructor;
@@ -337,6 +397,7 @@ class Base {
337
397
  * Options for the `removeEventListener` method.
338
398
  * @return {() => void}
339
399
  * A function to unbind the listener.
400
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#on-event-callback-options
340
401
  */
341
402
  $on(event, listener, options) {
342
403
  if (isDev) {
@@ -373,6 +434,7 @@ class Base {
373
434
  * @param {boolean|EventListenerOptions} [options]
374
435
  * Options for the `removeEventListener` method.
375
436
  * @return {void}
437
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#off-event-callback-options
376
438
  */
377
439
  $off(event, listener, options) {
378
440
  if (isDev) {
@@ -388,6 +450,7 @@ class Base {
388
450
  * @param {string} event Name of the event.
389
451
  * @param {any[]} args The arguments to apply to the functions bound to this event.
390
452
  * @return {void}
453
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#emit-event-args
391
454
  */
392
455
  $emit(event, ...args) {
393
456
  if (isDev) {
@@ -399,6 +462,7 @@ class Base {
399
462
  }
400
463
  /**
401
464
  * Register and mount all instances of the component.
465
+ * @link https://js-toolkit.studiometa.dev/api/static-methods.html#register-nameorselector-string
402
466
  */
403
467
  static $register(nameOrSelector) {
404
468
  addToRegistry(nameOrSelector ?? this.config.name, this);
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} 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 { 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 * The instance parent.\n */\n $parent: T['$parent'] & Base = null;\n\n /**\n * The instance id.\n */\n $id: string;\n\n /**\n * The root element.\n */\n $el: T['$el'] & BaseEl;\n\n /**\n * The state of the component.\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 */\n get $root(): Base {\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 * 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 get $config() {\n return this.__config;\n }\n\n static config: BaseConfig = {\n name: 'Base',\n emits: [\n // hook events\n 'before-mounted',\n 'mounted',\n 'updated',\n 'destroyed',\n 'terminated',\n // default services' events\n 'ticked',\n 'scrolled',\n 'resized',\n 'moved',\n 'loaded',\n 'keyed',\n ],\n };\n\n __services: ServicesManager;\n\n get $services(): ServicesManager {\n return this.__services;\n }\n\n __refs: RefsManager<T['$refs'] & BaseRefs>;\n\n get $refs(): T['$refs'] & BaseRefs {\n return this.__refs.props;\n }\n\n __options: OptionsManager<T['$options'] & BaseOptions>;\n\n get $options(): T['$options'] & BaseOptions {\n return this.__options.props;\n }\n\n __children: ChildrenManager<T['$children'] & BaseChildren>;\n\n get $children(): T['$children'] & BaseChildren {\n return this.__children.props;\n }\n\n __events: EventsManager;\n\n /**\n * Small helper to log stuff.\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 */\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 */\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 */\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 */\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 */\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 */\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('mounted', () => {\n addInstance(this);\n });\n this.$on('destroyed', () => {\n deleteInstance(this);\n });\n\n if (isDev) {\n this.__debug('constructor', this);\n }\n }\n\n /**\n * Trigger the `mounted` callback.\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\n return this;\n }\n\n /**\n * Update the instance children.\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 */\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.$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 return this;\n }\n\n /**\n * Terminate a child instance when it is not needed anymore.\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 */\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 */\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 */\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 */\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 */\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 */\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 getInstances,\n findClosestInstance,\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 { 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 * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#root\n */\n get $root(): Base {\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 * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#parent\n */\n get $parent(): T['$parent'] & Base | null {\n const parents = new Set<T['$parent'] & Base>();\n\n for (const instance of getInstances()) {\n if (!instance.$config.components) continue;\n\n if (\n Object.values(instance.$config.components).includes(this.constructor) &&\n instance.$el.contains(this.$el)\n ) {\n parents.add(instance);\n }\n }\n\n const closest = findClosestInstance(this.$el, parents);\n\n return closest ?? 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 * @link https://js-toolkit.studiometa.dev/api/instance-properties.html#children\n */\n get $children(): T['$children'] & BaseChildren {\n return this.__children.props;\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
  }
@@ -113,7 +113,6 @@ class ChildrenManager extends AbstractManager {
113
113
  return el.__base__.get(ctor.config.name);
114
114
  }
115
115
  const child = new ctor(el);
116
- Object.defineProperty(child, "$parent", { get: () => this.__base });
117
116
  return child;
118
117
  }
119
118
  const promise = asyncComponentPromise ? asyncComponentPromise.promise : ComponentClass(this.__base);
@@ -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 Object.defineProperty(child, '$parent', { get: () => this.__base });\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 __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/types.d.ts CHANGED
@@ -5,18 +5,22 @@ export type BaseEventHookParams<T extends Event = Event> = EventManagerCallbackP
5
5
  export interface BaseInterface {
6
6
  /**
7
7
  * Trigger the `mounted` callback.
8
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#mount
8
9
  */
9
10
  $mount?(): Promise<this>;
10
11
  /**
11
12
  * Update the instance children.
13
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#update
12
14
  */
13
15
  $update?(): Promise<this>;
14
16
  /**
15
17
  * Trigger the `destroyed` callback.
18
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#destroy
16
19
  */
17
20
  $destroy?(): Promise<this>;
18
21
  /**
19
22
  * Terminate a child instance when it is not needed anymore.
23
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#terminate
20
24
  */
21
25
  $terminate?(): Promise<void>;
22
26
  /**
@@ -26,6 +30,7 @@ export interface BaseInterface {
26
30
  * @param listener Function to be called.
27
31
  * @param [options] Options for the `removeEventListener` method.
28
32
  * @return A function to unbind the listener.
33
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#on-event-callback-options
29
34
  */
30
35
  $on(event: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): () => void;
31
36
  /**
@@ -34,6 +39,7 @@ export interface BaseInterface {
34
39
  * @param event Name of the event.
35
40
  * @param listener Function to be removed.
36
41
  * @param [options] Options for the `removeEventListener` method.
42
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#off-event-callback-options
37
43
  */
38
44
  $off(event: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
39
45
  /**
@@ -41,6 +47,7 @@ export interface BaseInterface {
41
47
  *
42
48
  * @param event Name of the event.
43
49
  * @param args The arguments to apply to the functions bound to this event.
50
+ * @link https://js-toolkit.studiometa.dev/api/instance-methods.html#emit-event-args
44
51
  */
45
52
  $emit(event: string | Event, ...args: unknown[]): void;
46
53
  /**
package/Base/utils.d.ts CHANGED
@@ -36,6 +36,13 @@ export declare function getEventTarget(instance: Base, event: string, config: Ba
36
36
  */
37
37
  export declare function getInstances(): Set<Base>;
38
38
  export declare function getInstances<T extends BaseConstructor = BaseConstructor>(ctor: T): Set<InstanceType<T>>;
39
+ export declare function getElements(): Set<HTMLElement & {
40
+ __base__: Map<string, Base>;
41
+ }>;
39
42
  export declare function addInstance(instance: Base): void;
40
43
  export declare function deleteInstance(instance: Base): void;
41
44
  export declare function addToRegistry(nameOrSelector: string, ctor: BaseConstructor): void;
45
+ /**
46
+ * Find the closest instance from the given element in the given set of Base instances.
47
+ */
48
+ export declare function findClosestInstance<T extends Base = Base>(element: HTMLElement, instances: Set<T>): T;
package/Base/utils.js CHANGED
@@ -62,6 +62,9 @@ function getEventTarget(instance, event, config) {
62
62
  function getInstancesStorage() {
63
63
  return globalThis.__JS_TOOLKIT_INSTANCES__ ??= /* @__PURE__ */ new Set();
64
64
  }
65
+ function getElementsStorage() {
66
+ return globalThis.__JS_TOOLKIT_ELEMENTS__ ??= /* @__PURE__ */ new Set();
67
+ }
65
68
  function getInstances(ctor) {
66
69
  if (isDefined(ctor)) {
67
70
  const filteredInstances = /* @__PURE__ */ new Set();
@@ -75,11 +78,16 @@ function getInstances(ctor) {
75
78
  return new Set(getInstancesStorage());
76
79
  }
77
80
  }
81
+ function getElements() {
82
+ return new Set(getElementsStorage());
83
+ }
78
84
  function addInstance(instance) {
79
85
  getInstancesStorage().add(instance);
86
+ getElementsStorage().add(instance.$el);
80
87
  }
81
88
  function deleteInstance(instance) {
82
89
  getInstancesStorage().delete(instance);
90
+ getElementsStorage().delete(instance.$el);
83
91
  }
84
92
  const registryKey = "__JS_TOOLKIT_REGISTRY__";
85
93
  function registry() {
@@ -120,6 +128,23 @@ function addToRegistry(nameOrSelector, ctor) {
120
128
  mutation.add(registryKey, mutationCallback);
121
129
  }
122
130
  }
131
+ function findClosestInstance(element, instances) {
132
+ let closest = null;
133
+ let minDepth = Infinity;
134
+ for (const instance of instances) {
135
+ let depth = 0;
136
+ let el = element;
137
+ while (el && el !== instance.$el) {
138
+ depth++;
139
+ el = el.parentElement;
140
+ }
141
+ if (depth < minDepth) {
142
+ minDepth = depth;
143
+ closest = instance;
144
+ }
145
+ }
146
+ return closest;
147
+ }
123
148
  export {
124
149
  addInstance,
125
150
  addToQueue,
@@ -127,7 +152,9 @@ export {
127
152
  deleteInstance,
128
153
  eventIsDefinedInConfig,
129
154
  eventIsNative,
155
+ findClosestInstance,
130
156
  getComponentElements,
157
+ getElements,
131
158
  getEventTarget,
132
159
  getInstances,
133
160
  getSelector
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 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(): Set<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): Set<InstanceType<T>> | Set<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 } else {\n return new Set(getInstancesStorage());\n }\n}\n\nexport function addInstance(instance: Base) {\n getInstancesStorage().add(instance);\n}\n\nexport function deleteInstance(instance: Base) {\n getInstancesStorage().delete(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"],
5
- "mappings": "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",
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<HTMLElement & { __base__: Map<string, Base>}>());\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(): Set<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): Set<InstanceType<T>> | Set<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 } else {\n return new Set(getInstancesStorage());\n }\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\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>(element: HTMLElement, instances: Set<T>): 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/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export declare const version: "3.4.1";
1
+ export declare const version: "3.4.3";
2
2
  export * from './Base/index.js';
3
3
  export * from './Base/types.js';
4
4
  export * from './decorators/index.js';
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "3.4.1";
1
+ const version = "3.4.3";
2
2
  export * from "./Base/index.js";
3
3
  export * from "./Base/types.js";
4
4
  export * from "./decorators/index.js";
package/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../packages/js-toolkit/index.ts"],
4
- "sourcesContent": ["export const version = '3.4.1' as const;\n\nexport * from './Base/index.js';\nexport * from './Base/types.js';\nexport * from './decorators/index.js';\nexport * from './helpers/index.js';\nexport * from './services/index.js';\n"],
4
+ "sourcesContent": ["export const version = '3.4.3' as const;\n\nexport * from './Base/index.js';\nexport * from './Base/types.js';\nexport * from './decorators/index.js';\nexport * from './helpers/index.js';\nexport * from './services/index.js';\n"],
5
5
  "mappings": "AAAO,MAAM,UAAU;AAEvB,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studiometa/js-toolkit",
3
- "version": "3.4.1",
3
+ "version": "3.4.3",
4
4
  "description": "A set of useful little bits of JavaScript to boost your project! 🚀",
5
5
  "publishConfig": {
6
6
  "access": "public"