@blac/core 2.0.0-rc-3 → 2.0.0-rc-5

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/dist/index.es.js CHANGED
@@ -1,69 +1,92 @@
1
- var B = Object.defineProperty;
2
- var I = (d, e, t) => e in d ? B(d, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : d[e] = t;
3
- var s = (d, e, t) => I(d, typeof e != "symbol" ? e + "" : e, t);
4
- const o = class o {
1
+ var v = Object.defineProperty;
2
+ var w = (l, e, t) => e in l ? v(l, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[e] = t;
3
+ var n = (l, e, t) => w(l, typeof e != "symbol" ? e + "" : e, t);
4
+ const d = class d {
5
+ getInstance() {
6
+ return d._instance || (d._instance = new h({ __unsafe_ignore_singleton: !0 })), d._instance;
7
+ }
8
+ setInstance(e) {
9
+ d._instance = e;
10
+ }
11
+ resetInstance() {
12
+ const e = d._instance;
13
+ if (d._instance = new h({ __unsafe_ignore_singleton: !0 }), e)
14
+ for (const t of e.keepAliveBlocs)
15
+ d._instance.keepAliveBlocs.add(t), d._instance.uidRegistry.set(t.uid, t);
16
+ }
17
+ };
18
+ n(d, "_instance");
19
+ let _ = d, u = new _();
20
+ function b(l) {
21
+ u = l;
22
+ }
23
+ const r = class r {
5
24
  /**
6
25
  * Creates a new Blac instance.
7
26
  * @param options - Configuration options including singleton control
8
27
  */
9
28
  constructor(e = {}) {
10
29
  /** Timestamp when the instance was created */
11
- s(this, "createdAt", Date.now());
30
+ n(this, "createdAt", Date.now());
12
31
  /** Map storing all registered bloc instances by their class name and ID */
13
- s(this, "blocInstanceMap", /* @__PURE__ */ new Map());
32
+ n(this, "blocInstanceMap", /* @__PURE__ */ new Map());
14
33
  /** Map storing isolated bloc instances grouped by their constructor */
15
- s(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
34
+ n(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
35
+ /** Map for O(1) lookup of isolated blocs by UID */
36
+ n(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
37
+ /** Map tracking UIDs to prevent memory leaks */
38
+ n(this, "uidRegistry", /* @__PURE__ */ new Map());
39
+ /** Set of keep-alive blocs for controlled cleanup */
40
+ n(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
16
41
  /** Flag to control whether changes should be posted to document */
17
- s(this, "postChangesToDocument", !1);
42
+ n(this, "postChangesToDocument", !1);
18
43
  /**
19
44
  * Logs messages to console when logging is enabled
20
45
  * @param args - Arguments to log
21
46
  */
22
- s(this, "log", (...e) => {
23
- o.enableLog && console.warn(`☢️ [Blac ${this.createdAt.toString()}]`, ...e);
47
+ n(this, "log", (...e) => {
48
+ r.enableLog && console.warn(`☢️ [Blac ${this.createdAt.toString()}]`, ...e);
24
49
  });
25
50
  /**
26
51
  * Logs a warning message
27
52
  * @param message - Warning message
28
53
  * @param args - Additional arguments
29
54
  */
30
- s(this, "warn", (e, ...t) => {
31
- o.enableLog && console.warn(`🚨 [Blac ${String(o.instance.createdAt)}]`, e, ...t);
55
+ n(this, "warn", (e, ...t) => {
56
+ r.enableLog && console.warn(`🚨 [Blac ${String(r.instance.createdAt)}]`, e, ...t);
32
57
  });
33
58
  /**
34
59
  * Logs an error message
35
60
  * @param message - Error message
36
61
  * @param args - Additional arguments
37
62
  */
38
- s(this, "error", (e, ...t) => {
39
- o.enableLog && console.error(`🚨 [Blac ${String(o.instance.createdAt)}]`, e, ...t);
63
+ n(this, "error", (e, ...t) => {
64
+ r.enableLog && console.error(`🚨 [Blac ${String(r.instance.createdAt)}]`, e, ...t);
40
65
  });
41
66
  /**
42
67
  * Resets the Blac instance to a new one, disposing non-keepAlive blocs
43
68
  * from the old instance.
44
69
  */
45
- s(this, "resetInstance", () => {
70
+ n(this, "resetInstance", () => {
46
71
  this.log("Reset Blac instance");
47
72
  const e = new Map(this.blocInstanceMap), t = new Map(this.isolatedBlocMap);
48
- e.forEach((n) => {
49
- n._dispose();
50
- }), t.forEach((n) => {
51
- n.forEach((i) => {
52
- i._dispose();
73
+ e.forEach((s) => {
74
+ s._keepAlive || s._dispose();
75
+ }), t.forEach((s) => {
76
+ s.forEach((i) => {
77
+ i._keepAlive || i._dispose();
53
78
  });
54
- }), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), o.instance = new o({
55
- __unsafe_ignore_singleton: !0
56
- });
79
+ }), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), u.resetInstance();
57
80
  });
58
81
  /**
59
82
  * Disposes of a bloc instance by removing it from the appropriate registry
60
83
  * @param bloc - The bloc instance to dispose
61
84
  */
62
- s(this, "disposeBloc", (e) => {
63
- const t = e.constructor, n = this.createBlocInstanceMapKey(e._name, e._id);
64
- this.log(`[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(t.isolated)}`), t.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(n)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
85
+ n(this, "disposeBloc", (e) => {
86
+ const t = e.constructor, s = this.createBlocInstanceMapKey(e._name, e._id);
87
+ this.log(`[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(t.isolated)}`), t.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(s)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
65
88
  });
66
- s(this, "activateBloc", (e) => {
89
+ n(this, "activateBloc", (e) => {
67
90
  const t = e.constructor;
68
91
  (e.isIsolated ? this.findIsolatedBlocInstance(t, e._id) : this.findRegisteredBlocInstance(t, e._id)) || (this.log(`[${e._name}:${String(e._id)}] activateBloc called. Isolated: ${String(e.isIsolated)}`), e.isIsolated ? this.registerIsolatedBlocInstance(e) : this.registerBlocInstance(e));
69
92
  });
@@ -78,27 +101,27 @@ const o = class o {
78
101
  * - instanceRef: Optional reference string for the instance
79
102
  * @returns The bloc instance
80
103
  */
81
- s(this, "getBloc", (e, t = {}) => {
82
- const { id: n } = t, i = e, a = n ?? e.name;
104
+ n(this, "getBloc", (e, t = {}) => {
105
+ const { id: s } = t, i = e, a = s ?? e.name;
83
106
  if (i.isolated) {
84
- const l = this.findIsolatedBlocInstance(e, a);
85
- if (l)
86
- return this.log(`[${e.name}:${String(a)}] (getBloc) Found existing isolated instance.`, t), l;
107
+ const c = this.findIsolatedBlocInstance(e, a);
108
+ if (c)
109
+ return this.log(`[${e.name}:${String(a)}] (getBloc) Found existing isolated instance.`, t), c;
87
110
  if (t.throwIfNotFound)
88
111
  throw new Error(`Isolated bloc ${e.name} not found`);
89
112
  } else {
90
- const l = this.findRegisteredBlocInstance(e, a);
91
- if (l)
92
- return this.log(`[${e.name}:${String(a)}] (getBloc) Found existing registered instance.`, t), l;
113
+ const c = this.findRegisteredBlocInstance(e, a);
114
+ if (c)
115
+ return this.log(`[${e.name}:${String(a)}] (getBloc) Found existing registered instance.`, t), c;
93
116
  if (t.throwIfNotFound)
94
117
  throw new Error(`Registered bloc ${e.name} not found`);
95
118
  }
96
- const r = this.createNewBlocInstance(
119
+ const o = this.createNewBlocInstance(
97
120
  e,
98
121
  a,
99
122
  t
100
123
  );
101
- return this.log(`[${e.name}:${String(a)}] (getBloc) No existing instance found. Creating new one.`, t, r), r;
124
+ return this.log(`[${e.name}:${String(a)}] (getBloc) No existing instance found. Creating new one.`, t, o), o;
102
125
  });
103
126
  /**
104
127
  * Gets a bloc instance or throws an error if it doesn't exist
@@ -108,8 +131,8 @@ const o = class o {
108
131
  * - props: Properties to pass to the bloc constructor
109
132
  * - instanceRef: Optional reference string for the instance
110
133
  */
111
- s(this, "getBlocOrThrow", (e, t = {}) => {
112
- const n = e.isolated, i = t.id || e.name, a = n ? this.findIsolatedBlocInstance(e, i) : this.findRegisteredBlocInstance(e, i);
134
+ n(this, "getBlocOrThrow", (e, t = {}) => {
135
+ const s = e.isolated, i = t.id || e.name, a = s ? this.findIsolatedBlocInstance(e, i) : this.findRegisteredBlocInstance(e, i);
113
136
  if (a)
114
137
  return a;
115
138
  throw new Error(`Bloc ${e.name} not found`);
@@ -121,27 +144,85 @@ const o = class o {
121
144
  * - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)
122
145
  * @returns Array of matching bloc instances
123
146
  */
124
- s(this, "getAllBlocs", (e, t = {}) => {
125
- const n = [];
147
+ n(this, "getAllBlocs", (e, t = {}) => {
148
+ const s = [];
126
149
  if (this.blocInstanceMap.forEach((i) => {
127
- i.constructor === e && n.push(i);
150
+ i.constructor === e && s.push(i);
128
151
  }), t.searchIsolated !== !1) {
129
152
  const i = this.isolatedBlocMap.get(e);
130
- i && n.push(...i.map((a) => a));
153
+ i && s.push(...i.map((a) => a));
131
154
  }
132
- return n;
155
+ return s;
156
+ });
157
+ /**
158
+ * Disposes all keep-alive blocs of a specific type
159
+ * @param blocClass - The bloc class to dispose
160
+ */
161
+ n(this, "disposeKeepAliveBlocs", (e) => {
162
+ const t = [];
163
+ for (const s of this.keepAliveBlocs)
164
+ (!e || s.constructor === e) && t.push(s);
165
+ t.forEach((s) => s._dispose());
166
+ });
167
+ /**
168
+ * Disposes all blocs matching a pattern
169
+ * @param predicate - Function to test each bloc for disposal
170
+ */
171
+ n(this, "disposeBlocs", (e) => {
172
+ const t = [];
173
+ for (const s of this.blocInstanceMap.values())
174
+ e(s) && t.push(s);
175
+ for (const s of this.isolatedBlocMap.values())
176
+ for (const i of s)
177
+ e(i) && t.push(i);
178
+ t.forEach((s) => s._dispose());
179
+ });
180
+ /**
181
+ * Gets memory usage statistics for debugging
182
+ */
183
+ n(this, "getMemoryStats", () => ({
184
+ totalBlocs: this.uidRegistry.size,
185
+ registeredBlocs: this.blocInstanceMap.size,
186
+ isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce((e, t) => e + t.length, 0),
187
+ keepAliveBlocs: this.keepAliveBlocs.size,
188
+ isolatedBlocTypes: this.isolatedBlocMap.size
189
+ }));
190
+ /**
191
+ * Validates consumer references and cleans up orphaned consumers
192
+ */
193
+ n(this, "validateConsumers", () => {
194
+ for (const e of this.uidRegistry.values())
195
+ e._consumers.size === 0 && !e._keepAlive && setTimeout(() => {
196
+ e._consumers.size === 0 && !e._keepAlive && e._dispose();
197
+ }, 1e3);
133
198
  });
134
199
  const { __unsafe_ignore_singleton: t = !1 } = e;
135
200
  if (!t)
136
- return o.instance;
137
- o.instance = this;
201
+ return r.instance;
202
+ u.setInstance(this);
203
+ }
204
+ /** @deprecated Use getInstance() instead */
205
+ static get instance() {
206
+ return u.getInstance();
207
+ }
208
+ static get getAllBlocs() {
209
+ return r.instance.getAllBlocs;
210
+ }
211
+ static get log() {
212
+ return r.instance.log;
138
213
  }
139
214
  /**
140
- * Gets the singleton instance of Blac
215
+ * Gets the current Blac instance
141
216
  * @returns The Blac instance
142
217
  */
143
218
  static getInstance() {
144
- return o.instance;
219
+ return u.getInstance();
220
+ }
221
+ static get warn() {
222
+ return r.instance.warn;
223
+ }
224
+ static get error() {
225
+ return r.instance.error;
145
226
  }
146
227
  /**
147
228
  * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
@@ -158,7 +239,7 @@ const o = class o {
158
239
  */
159
240
  unregisterBlocInstance(e) {
160
241
  const t = this.createBlocInstanceMapKey(e._name, e._id);
161
- this.blocInstanceMap.delete(t);
242
+ this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
162
243
  }
163
244
  /**
164
245
  * Registers a bloc instance in the main registry
@@ -166,7 +247,7 @@ const o = class o {
166
247
  */
167
248
  registerBlocInstance(e) {
168
249
  const t = this.createBlocInstanceMapKey(e._name, e._id);
169
- this.blocInstanceMap.set(t, e);
250
+ this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
170
251
  }
171
252
  /**
172
253
  * Finds a registered bloc instance by its class and ID
@@ -184,27 +265,34 @@ const o = class o {
184
265
  * @param bloc - The isolated bloc instance to register
185
266
  */
186
267
  registerIsolatedBlocInstance(e) {
187
- const t = e.constructor, n = this.isolatedBlocMap.get(t);
188
- n ? n.push(e) : this.isolatedBlocMap.set(t, [e]);
268
+ const t = e.constructor, s = this.isolatedBlocMap.get(t);
269
+ s ? s.push(e) : this.isolatedBlocMap.set(t, [e]), this.isolatedBlocIndex.set(e.uid, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
189
270
  }
190
271
  /**
191
272
  * Unregister an isolated bloc instance from the isolated registry
192
273
  * @param bloc - The isolated bloc instance to unregister
193
274
  */
194
275
  unregisterIsolatedBlocInstance(e) {
195
- const t = e.constructor, n = this.isolatedBlocMap.get(t);
196
- if (n) {
197
- const i = n.findIndex((a) => a._id === e._id);
198
- i !== -1 && n.splice(i, 1), n.length === 0 && this.isolatedBlocMap.delete(t);
276
+ const t = e.constructor, s = this.isolatedBlocMap.get(t);
277
+ if (s) {
278
+ const i = s.findIndex((a) => a.uid === e.uid);
279
+ i !== -1 && s.splice(i, 1), s.length === 0 && this.isolatedBlocMap.delete(t);
199
280
  }
281
+ this.isolatedBlocIndex.delete(e.uid), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
200
282
  }
201
283
  /**
202
- * Finds an isolated bloc instance by its class and ID
284
+ * Finds an isolated bloc instance by its class and ID (O(n) lookup)
203
285
  */
204
286
  findIsolatedBlocInstance(e, t) {
205
287
  if (!e.isolated) return;
206
288
  const i = this.isolatedBlocMap.get(e);
207
- return i ? i.find((r) => r._id === t) : void 0;
289
+ return i ? i.find((o) => o._id === t) : void 0;
290
+ }
291
+ /**
292
+ * Finds an isolated bloc instance by UID (O(1) lookup)
293
+ */
294
+ findIsolatedBlocInstanceByUid(e) {
295
+ return this.isolatedBlocIndex.get(e);
208
296
  }
209
297
  /**
210
298
  * Creates a new bloc instance and registers it in the appropriate registry
@@ -214,24 +302,46 @@ const o = class o {
214
302
  * @param instanceRef - Optional reference string for the instance
215
303
  * @returns The newly created bloc instance
216
304
  */
217
- createNewBlocInstance(e, t, n = {}) {
218
- const { props: i, instanceRef: a } = n, r = new e(i);
219
- return r._instanceRef = a, r.props = i || null, r._updateId(t), r.isIsolated ? (this.registerIsolatedBlocInstance(r), r) : (this.registerBlocInstance(r), r);
305
+ createNewBlocInstance(e, t, s = {}) {
306
+ const { props: i, instanceRef: a } = s, o = new e(i);
307
+ return o._instanceRef = a, o.props = i || null, o._updateId(t), o._setDisposalHandler((c) => this.disposeBloc(c)), o.isIsolated ? (this.registerIsolatedBlocInstance(o), o) : (this.registerBlocInstance(o), o);
308
+ }
309
+ static get activateBloc() {
310
+ return r.instance.activateBloc;
311
+ }
312
+ static get getBloc() {
313
+ return r.instance.getBloc;
314
+ }
315
+ static get getBlocOrThrow() {
316
+ return r.instance.getBlocOrThrow;
317
+ }
318
+ static get disposeKeepAliveBlocs() {
319
+ return r.instance.disposeKeepAliveBlocs;
320
+ }
321
+ static get disposeBlocs() {
322
+ return r.instance.disposeBlocs;
323
+ }
324
+ static get getMemoryStats() {
325
+ return r.instance.getMemoryStats;
326
+ }
327
+ static get validateConsumers() {
328
+ return r.instance.validateConsumers;
220
329
  }
221
330
  };
222
- /** The singleton instance of Blac */
223
- s(o, "instance", new o()), s(o, "getAllBlocs", o.instance.getAllBlocs), /** Flag to enable/disable logging */
224
- s(o, "enableLog", !1), s(o, "log", o.instance.log), s(o, "warn", o.instance.warn), s(o, "error", o.instance.error), s(o, "resetInstance", o.instance.resetInstance), s(o, "activateBloc", o.instance.activateBloc), s(o, "getBloc", o.instance.getBloc), s(o, "getBlocOrThrow", o.instance.getBlocOrThrow);
225
- let c = o;
226
- class _ {
331
+ /** Flag to enable/disable logging */
332
+ n(r, "enableLog", !1), n(r, "resetInstance", () => {
333
+ u.resetInstance();
334
+ });
335
+ let h = r;
336
+ class m {
227
337
  /**
228
338
  * Creates a new BlacObservable instance
229
339
  * @param bloc - The Bloc instance to observe
230
340
  */
231
341
  constructor(e) {
232
342
  /** The Bloc instance this observable is associated with */
233
- s(this, "bloc");
234
- s(this, "_observers", /* @__PURE__ */ new Set());
343
+ n(this, "bloc");
344
+ n(this, "_observers", /* @__PURE__ */ new Set());
235
345
  this.bloc = e;
236
346
  }
237
347
  /**
@@ -254,8 +364,8 @@ class _ {
254
364
  * @returns A function that can be called to unsubscribe the observer
255
365
  */
256
366
  subscribe(e) {
257
- return c.log("BlacObservable.subscribe: Subscribing observer.", this.bloc, e), this._observers.add(e), e.lastState || (e.lastState = e.dependencyArray ? e.dependencyArray(this.bloc.state) : []), () => {
258
- c.log("BlacObservable.subscribe: Unsubscribing observer.", this.bloc, e), this.unsubscribe(e);
367
+ return h.log("BlacObservable.subscribe: Subscribing observer.", this.bloc, e), this._observers.add(e), e.lastState || (e.lastState = e.dependencyArray ? e.dependencyArray(this.bloc.state) : []), () => {
368
+ h.log("BlacObservable.subscribe: Unsubscribing observer.", this.bloc, e), this.unsubscribe(e);
259
369
  };
260
370
  }
261
371
  /**
@@ -263,7 +373,7 @@ class _ {
263
373
  * @param observer - The observer to unsubscribe
264
374
  */
265
375
  unsubscribe(e) {
266
- this._observers.delete(e), this.size === 0 && (c.log("BlacObservable.unsubscribe: No observers left. Disposing bloc.", this.bloc), this.bloc._dispose());
376
+ this._observers.delete(e), this.size === 0 && (h.log("BlacObservable.unsubscribe: No observers left. Disposing bloc.", this.bloc), this.bloc._dispose());
267
377
  }
268
378
  /**
269
379
  * Notifies all observers of a state change
@@ -271,23 +381,23 @@ class _ {
271
381
  * @param oldState - The previous state value
272
382
  * @param action - Optional action that triggered the state change
273
383
  */
274
- notify(e, t, n) {
384
+ notify(e, t, s) {
275
385
  this._observers.forEach((i) => {
276
386
  let a = !1;
277
387
  if (i.dependencyArray) {
278
- const r = i.lastState || [], l = i.dependencyArray(e);
279
- for (let h = 0; h < l.length; h++) {
280
- const f = l[h], p = r[h] || [];
281
- for (let u = 0; u < f.length; u++)
282
- if (!Object.is(f[u], p[u])) {
388
+ const o = i.lastState || [], c = i.dependencyArray(e);
389
+ for (let p = 0; p < c.length; p++) {
390
+ const B = c[p], I = o[p] || [];
391
+ for (let f = 0; f < B.length; f++)
392
+ if (!Object.is(B[f], I[f])) {
283
393
  a = !0;
284
394
  break;
285
395
  }
286
396
  }
287
- i.lastState = l;
397
+ i.lastState = c;
288
398
  } else
289
399
  a = !0;
290
- a && i.fn(e, t, n);
400
+ a && i.fn(e, t, s);
291
401
  });
292
402
  }
293
403
  /**
@@ -307,62 +417,57 @@ class g {
307
417
  * @param initialState The initial state value for this Bloc
308
418
  */
309
419
  constructor(e) {
310
- s(this, "uid", crypto.randomUUID());
420
+ n(this, "uid", crypto.randomUUID());
311
421
  /**
312
422
  * Defines how dependencies are selected from the state for efficient updates.
313
423
  * When provided, observers will only be notified when selected dependencies change.
314
424
  */
315
- s(this, "defaultDependencySelector");
425
+ n(this, "defaultDependencySelector");
316
426
  /**
317
427
  * @internal
318
428
  * Indicates if this specific Bloc instance is isolated from others of the same type.
319
429
  */
320
- s(this, "_isolated", !1);
430
+ n(this, "_isolated", !1);
321
431
  /**
322
432
  * @internal
323
433
  * Observable responsible for managing state listeners and notifying consumers.
324
434
  */
325
- s(this, "_observer");
326
- /**
327
- * @internal
328
- * Reference to the global Blac manager instance.
329
- */
330
- s(this, "_blac", c.getInstance());
435
+ n(this, "_observer");
331
436
  /**
332
437
  * The unique identifier for this Bloc instance.
333
438
  * Defaults to the class name, but can be customized.
334
439
  */
335
- s(this, "_id");
440
+ n(this, "_id");
336
441
  /**
337
442
  * @internal
338
443
  * Reference string used internally for tracking and debugging.
339
444
  */
340
- s(this, "_instanceRef");
445
+ n(this, "_instanceRef");
341
446
  /**
342
447
  * @internal
343
448
  * Indicates if this specific Bloc instance should be kept alive when no consumers are present.
344
449
  */
345
- s(this, "_keepAlive", !1);
450
+ n(this, "_keepAlive", !1);
346
451
  /**
347
452
  * @readonly
348
453
  * Timestamp when this Bloc instance was created, useful for debugging and performance tracking.
349
454
  */
350
- s(this, "_createdAt", Date.now());
455
+ n(this, "_createdAt", Date.now());
351
456
  /**
352
457
  * @internal
353
458
  * The current state of the Bloc.
354
459
  */
355
- s(this, "_state");
460
+ n(this, "_state");
356
461
  /**
357
462
  * @internal
358
463
  * The previous state of the Bloc, maintained for comparison and history.
359
464
  */
360
- s(this, "_oldState");
465
+ n(this, "_oldState");
361
466
  /**
362
467
  * Props passed during Bloc instance creation.
363
468
  * Can be used to configure or parameterize the Bloc's behavior.
364
469
  */
365
- s(this, "props", null);
470
+ n(this, "props", null);
366
471
  /**
367
472
  * @internal
368
473
  * Updates the Bloc instance's ID to a new value.
@@ -370,7 +475,7 @@ class g {
370
475
  *
371
476
  * @param id The new ID to assign to this Bloc instance
372
477
  */
373
- s(this, "_updateId", (e) => {
478
+ n(this, "_updateId", (e) => {
374
479
  const t = this._id;
375
480
  !e || e === t || (this._id = e);
376
481
  });
@@ -378,21 +483,27 @@ class g {
378
483
  * @internal
379
484
  * Optional function to be called when the Bloc is disposed.
380
485
  */
381
- s(this, "onDispose");
486
+ n(this, "onDispose");
382
487
  /**
383
488
  * @internal
384
489
  * Set of consumer IDs currently listening to this Bloc's state changes.
385
490
  */
386
- s(this, "_consumers", /* @__PURE__ */ new Set());
491
+ n(this, "_consumers", /* @__PURE__ */ new Set());
492
+ /**
493
+ * @internal
494
+ * WeakSet to track consumer references for cleanup validation
495
+ */
496
+ n(this, "_consumerRefs", /* @__PURE__ */ new WeakSet());
387
497
  /**
388
498
  * @internal
389
499
  * Registers a new consumer to this Bloc instance.
390
500
  * Notifies the Blac manager that a consumer has been added.
391
501
  *
392
502
  * @param consumerId The unique ID of the consumer being added
503
+ * @param consumerRef Optional reference to the consumer object for cleanup validation
393
504
  */
394
- s(this, "_addConsumer", (e) => {
395
- this._consumers.has(e) || (this._consumers.add(e), c.log("BlocBase._addConsumer", this, e));
505
+ n(this, "_addConsumer", (e, t) => {
506
+ this._consumers.has(e) || (this._consumers.add(e), t && this._consumerRefs.add(t));
396
507
  });
397
508
  /**
398
509
  * @internal
@@ -401,10 +512,25 @@ class g {
401
512
  *
402
513
  * @param consumerId The unique ID of the consumer being removed
403
514
  */
404
- s(this, "_removeConsumer", (e) => {
405
- this._consumers.has(e) && (this._consumers.delete(e), c.log("BlocBase._removeConsumer", this, e));
515
+ n(this, "_removeConsumer", (e) => {
516
+ this._consumers.has(e) && (this._consumers.delete(e), this._consumers.size === 0 && !this._keepAlive && this._scheduleDisposal());
406
517
  });
407
- s(this, "lastUpdate", Date.now());
518
+ /**
519
+ * @internal
520
+ * Handler function for disposal (can be set by Blac manager)
521
+ */
522
+ n(this, "_disposalHandler");
523
+ n(this, "lastUpdate", Date.now());
524
+ /**
525
+ * @internal
526
+ * Flag to indicate if batching is enabled for this bloc
527
+ */
528
+ n(this, "_batchingEnabled", !1);
529
+ /**
530
+ * @internal
531
+ * Pending state updates when batching is enabled
532
+ */
533
+ n(this, "_pendingUpdates", []);
408
534
  /**
409
535
  * @internal
410
536
  * Updates the state and notifies all observers of the change.
@@ -413,12 +539,42 @@ class g {
413
539
  * @param oldState The previous state for comparison
414
540
  * @param action Optional metadata about what caused the state change
415
541
  */
416
- s(this, "_pushState", (e, t, n) => {
417
- this._state = e, this._observer.notify(e, t, n), this.lastUpdate = Date.now();
542
+ n(this, "_pushState", (e, t, s) => {
543
+ if (e === void 0) {
544
+ console.warn("BlocBase._pushState: newState is undefined", this);
545
+ return;
546
+ }
547
+ if (s != null) {
548
+ const i = typeof s;
549
+ ["string", "object", "number"].includes(i) || console.warn("BlocBase._pushState: Invalid action type", this, s);
550
+ }
551
+ if (this._batchingEnabled) {
552
+ this._pendingUpdates.push({ newState: e, oldState: t, action: s });
553
+ return;
554
+ }
555
+ this._oldState = t, this._state = e, this._observer.notify(e, t, s), this.lastUpdate = Date.now();
556
+ });
557
+ /**
558
+ * Enables batching for multiple state updates
559
+ * @param batchFn Function to execute with batching enabled
560
+ */
561
+ n(this, "batch", (e) => {
562
+ const t = this._batchingEnabled;
563
+ this._batchingEnabled = !0;
564
+ try {
565
+ const s = e();
566
+ if (this._pendingUpdates.length > 0) {
567
+ const i = this._pendingUpdates[this._pendingUpdates.length - 1];
568
+ this._oldState = this._pendingUpdates[0].oldState, this._state = i.newState, this._observer.notify(i.newState, this._oldState, i.action), this.lastUpdate = Date.now(), this._pendingUpdates = [];
569
+ }
570
+ return s;
571
+ } finally {
572
+ this._batchingEnabled = t;
573
+ }
418
574
  });
419
- this._state = e, this._observer = new _(this), c.log("Bloc Created", this), this._id = this.constructor.name;
575
+ this._state = e, this._observer = new m(this), this._id = this.constructor.name;
420
576
  const t = this.constructor;
421
- this._keepAlive = t.keepAlive, this._isolated = t.isolated;
577
+ this._keepAlive = typeof t.keepAlive == "boolean" ? t.keepAlive : !1, this._isolated = typeof t.isolated == "boolean" ? t.isolated : !1;
422
578
  }
423
579
  get isIsolated() {
424
580
  return this._isolated;
@@ -447,7 +603,23 @@ class g {
447
603
  */
448
604
  _dispose() {
449
605
  var e;
450
- this._observer.clear(), (e = this.onDispose) == null || e.call(this), c.log("BlocBase._dispose", this), c.instance.disposeBloc(this);
606
+ this._consumers.clear(), this._observer.clear(), (e = this.onDispose) == null || e.call(this);
607
+ }
608
+ /**
609
+ * @internal
610
+ * Sets the disposal handler for this bloc
611
+ */
612
+ _setDisposalHandler(e) {
613
+ this._disposalHandler = e;
614
+ }
615
+ /**
616
+ * @internal
617
+ * Schedules disposal of this bloc instance if it has no consumers
618
+ */
619
+ _scheduleDisposal() {
620
+ setTimeout(() => {
621
+ this._consumers.size === 0 && !this._keepAlive && (this._disposalHandler ? this._disposalHandler(this) : this._dispose());
622
+ }, 0);
451
623
  }
452
624
  }
453
625
  /**
@@ -455,45 +627,45 @@ class g {
455
627
  * Use this when state should not be shared between components.
456
628
  * @default false
457
629
  */
458
- s(g, "isolated", !1), /**
630
+ n(g, "isolated", !1), /**
459
631
  * When true, the Bloc instance persists even when there are no active consumers.
460
632
  * Useful for maintaining state between component unmount/remount cycles.
461
633
  * @default false
462
634
  */
463
- s(g, "keepAlive", !1);
464
- class b extends g {
635
+ n(g, "keepAlive", !1);
636
+ class A extends g {
465
637
  constructor() {
466
638
  super(...arguments);
467
639
  // Stores handlers: Map<EventConstructor (subtype of A), HandlerFunction>
468
640
  // The handler's event parameter will be correctly typed to the specific EventConstructor
469
641
  // by the 'on' method's signature.
470
- s(this, "eventHandlers", /* @__PURE__ */ new Map());
642
+ n(this, "eventHandlers", /* @__PURE__ */ new Map());
471
643
  /**
472
644
  * Dispatches an action/event to the Bloc.
473
645
  * If a handler is registered for this specific event type (via 'on'), it will be invoked.
474
646
  * Asynchronous handlers are awaited.
475
647
  * @param action The action/event instance to be processed.
476
648
  */
477
- s(this, "add", async (t) => {
478
- const n = t.constructor, i = this.eventHandlers.get(n);
649
+ n(this, "add", async (t) => {
650
+ const s = t.constructor, i = this.eventHandlers.get(s);
479
651
  if (i) {
480
- const a = (r) => {
481
- const l = this.state;
482
- this._pushState(r, l, t);
652
+ const a = (o) => {
653
+ const c = this.state;
654
+ this._pushState(o, c, t);
483
655
  };
484
656
  try {
485
657
  await i(t, a);
486
- } catch (r) {
487
- c.error(
488
- `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${n.name}':`,
489
- r,
658
+ } catch (o) {
659
+ h.error(
660
+ `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${s.name}':`,
661
+ o,
490
662
  "Action:",
491
663
  t
492
664
  );
493
665
  }
494
666
  } else {
495
667
  const a = t.constructor.name || "UnnamedConstructor";
496
- c.warn(
668
+ h.warn(
497
669
  `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${a}'. Action was:`,
498
670
  t
499
671
  );
@@ -507,16 +679,16 @@ class b extends g {
507
679
  * @param handler A function that processes the event and can emit new states.
508
680
  * The 'event' parameter in the handler will be typed to the specific eventConstructor.
509
681
  */
510
- on(t, n) {
511
- this.eventHandlers.has(t) && c.warn(
682
+ on(t, s) {
683
+ this.eventHandlers.has(t) && h.warn(
512
684
  `[Bloc ${this._name}:${String(this._id)}] Handler for event '${t.name}' already registered. It will be overwritten.`
513
685
  ), this.eventHandlers.set(
514
686
  t,
515
- n
687
+ s
516
688
  );
517
689
  }
518
690
  }
519
- class m extends g {
691
+ class M extends g {
520
692
  /**
521
693
  * Updates the current state and notifies all observers of the change.
522
694
  * If the new state is identical to the current state (using Object.is),
@@ -526,8 +698,8 @@ class m extends g {
526
698
  emit(e) {
527
699
  if (Object.is(e, this.state))
528
700
  return;
529
- const t = this.state, n = e;
530
- this._pushState(n, t);
701
+ const t = this.state, s = e;
702
+ this._pushState(s, t);
531
703
  }
532
704
  /**
533
705
  * Partially updates the current state by merging it with the provided state patch.
@@ -539,34 +711,35 @@ class m extends g {
539
711
  */
540
712
  patch(e, t = !1) {
541
713
  if (typeof this.state != "object" || this.state === null) {
542
- c.warn(
714
+ h.warn(
543
715
  "Cubit.patch: was called on a cubit where the state is not an object. This is a no-op."
544
716
  );
545
717
  return;
546
718
  }
547
- let n = !1;
719
+ let s = !1;
548
720
  if (t)
549
- n = !0;
721
+ s = !0;
550
722
  else
551
723
  for (const i in e)
552
724
  if (Object.prototype.hasOwnProperty.call(e, i)) {
553
- const r = this.state[i];
554
- if (!Object.is(e[i], r)) {
555
- n = !0;
725
+ const o = this.state[i];
726
+ if (!Object.is(e[i], o)) {
727
+ s = !0;
556
728
  break;
557
729
  }
558
730
  }
559
- n && this.emit({
731
+ s && this.emit({
560
732
  ...this.state,
561
733
  ...e
562
734
  });
563
735
  }
564
736
  }
565
737
  export {
566
- c as Blac,
567
- _ as BlacObservable,
568
- b as Bloc,
738
+ h as Blac,
739
+ m as BlacObservable,
740
+ A as Bloc,
569
741
  g as BlocBase,
570
- m as Cubit
742
+ M as Cubit,
743
+ b as setBlacInstanceManager
571
744
  };
572
745
  //# sourceMappingURL=index.es.js.map