@blac/core 2.0.0-rc-8 → 2.0.0-rc-10

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,393 +1,15 @@
1
- var I = Object.defineProperty;
2
- var y = (d, e, t) => e in d ? I(d, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : d[e] = t;
3
- var i = (d, e, t) => y(d, typeof e != "symbol" ? e + "" : e, t);
4
- const u = class u {
5
- getInstance() {
6
- return u._instance || (u._instance = new l({
7
- __unsafe_ignore_singleton: !0
8
- })), u._instance;
9
- }
10
- setInstance(e) {
11
- u._instance = e;
12
- }
13
- resetInstance() {
14
- const e = u._instance;
15
- if (u._instance = new l({
16
- __unsafe_ignore_singleton: !0
17
- }), e)
18
- for (const t of e.keepAliveBlocs)
19
- u._instance.keepAliveBlocs.add(t), u._instance.uidRegistry.set(t.uid, t);
20
- }
21
- };
22
- i(u, "_instance");
23
- let B = u, g = new B();
24
- function A(d) {
25
- g = d;
26
- }
27
- const r = class r {
28
- /**
29
- * Creates a new Blac instance.
30
- * @param options - Configuration options including singleton control
31
- */
32
- constructor(e = {}) {
33
- /** Timestamp when the instance was created */
34
- i(this, "createdAt", Date.now());
35
- /** Map storing all registered bloc instances by their class name and ID */
36
- i(this, "blocInstanceMap", /* @__PURE__ */ new Map());
37
- /** Map storing isolated bloc instances grouped by their constructor */
38
- // TODO: BlocConstructor<any> is required here for type inference to work correctly.
39
- // Using BlocConstructor<BlocBase<unknown>> would break type inference when storing
40
- // different bloc types in the same map. The 'any' allows proper polymorphic storage
41
- // while maintaining type safety at usage sites through the BlocConstructor constraint.
42
- i(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
43
- /** Map for O(1) lookup of isolated blocs by UID */
44
- i(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
45
- /** Map tracking UIDs to prevent memory leaks */
46
- i(this, "uidRegistry", /* @__PURE__ */ new Map());
47
- /** Set of keep-alive blocs for controlled cleanup */
48
- i(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
49
- /** Flag to control whether changes should be posted to document */
50
- i(this, "postChangesToDocument", !1);
51
- /**
52
- * Logs messages to console when logging is enabled
53
- * @param args - Arguments to log
54
- */
55
- i(this, "log", (...e) => {
56
- r.enableLog && r.logLevel === "warn" && console.warn(`☢️ [Blac ${this.createdAt.toString()}]`, ...e), r.enableLog && r.logLevel === "log" && console.log(`☢️ [Blac ${this.createdAt.toString()}]`, ...e);
57
- });
58
- /**
59
- * Logs a warning message
60
- * @param message - Warning message
61
- * @param args - Additional arguments
62
- */
63
- i(this, "warn", (e, ...t) => {
64
- r.enableLog && console.warn(
65
- `🚨 [Blac ${String(r.instance.createdAt)}]`,
66
- e,
67
- ...t
68
- );
69
- });
70
- /**
71
- * Logs an error message
72
- * @param message - Error message
73
- * @param args - Additional arguments
74
- */
75
- i(this, "error", (e, ...t) => {
76
- r.enableLog && console.error(
77
- `🚨 [Blac ${String(r.instance.createdAt)}]`,
78
- e,
79
- ...t
80
- );
81
- });
82
- /**
83
- * Resets the Blac instance to a new one, disposing non-keepAlive blocs
84
- * from the old instance.
85
- */
86
- i(this, "resetInstance", () => {
87
- this.log("Reset Blac instance");
88
- const e = new Map(this.blocInstanceMap), t = new Map(this.isolatedBlocMap);
89
- e.forEach((s) => {
90
- !s._keepAlive && s._disposalState === "active" && this.disposeBloc(s);
91
- }), t.forEach((s) => {
92
- s.forEach((n) => {
93
- !n._keepAlive && n._disposalState === "active" && this.disposeBloc(n);
94
- });
95
- }), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), g.resetInstance();
96
- });
97
- /**
98
- * Disposes of a bloc instance by removing it from the appropriate registry
99
- * @param bloc - The bloc instance to dispose
100
- */
101
- i(this, "disposeBloc", (e) => {
102
- if (e._disposalState !== "active") {
103
- this.log(
104
- `[${e._name}:${String(e._id)}] disposeBloc called on already disposed bloc`
105
- );
106
- return;
107
- }
108
- const t = e.constructor, s = this.createBlocInstanceMapKey(e._name, e._id);
109
- this.log(
110
- `[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(t.isolated)}`
111
- ), e._dispose(), t.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(s)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
112
- });
113
- i(this, "activateBloc", (e) => {
114
- if (e._disposalState !== "active") {
115
- this.log(
116
- `[${e._name}:${String(e._id)}] activateBloc called on disposed bloc. Ignoring.`
117
- );
118
- return;
119
- }
120
- const t = e.constructor;
121
- (e.isIsolated ? this.findIsolatedBlocInstance(t, e._id) : this.findRegisteredBlocInstance(t, e._id)) || (this.log(
122
- `[${e._name}:${String(e._id)}] activateBloc called. Isolated: ${String(e.isIsolated)}`
123
- ), e.isIsolated ? this.registerIsolatedBlocInstance(e) : this.registerBlocInstance(e));
124
- });
125
- /**
126
- * Gets or creates a bloc instance based on the provided class and options.
127
- * If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.
128
- *
129
- * @param blocClass - The bloc class to get or create
130
- * @param options - Options including:
131
- * - id: The instance ID (defaults to class name if not provided)
132
- * - props: Properties to pass to the bloc constructor
133
- * - instanceRef: Optional reference string for the instance
134
- * @returns The bloc instance
135
- */
136
- i(this, "getBloc", (e, t = {}) => {
137
- const { id: s } = t, n = e, o = s ?? e.name;
138
- if (n.isolated) {
139
- const c = this.findIsolatedBlocInstance(e, o);
140
- if (c)
141
- return c;
142
- if (t.throwIfNotFound)
143
- throw new Error(`Isolated bloc ${e.name} not found`);
144
- } else {
145
- const c = this.findRegisteredBlocInstance(e, o);
146
- if (c)
147
- return c;
148
- if (t.throwIfNotFound)
149
- throw new Error(`Registered bloc ${e.name} not found`);
150
- }
151
- const a = this.createNewBlocInstance(e, o, t);
152
- if (this.log(
153
- `[${e.name}:${String(o)}] (getBloc) No existing instance found. Creating new one.`,
154
- t,
155
- a
156
- ), !a)
157
- throw new Error(
158
- `[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`
159
- );
160
- return a;
161
- });
162
- /**
163
- * Gets a bloc instance or throws an error if it doesn't exist
164
- * @param blocClass - The bloc class to get
165
- * @param options - Options including:
166
- * - id: The instance ID (defaults to class name if not provided)
167
- * - props: Properties to pass to the bloc constructor
168
- * - instanceRef: Optional reference string for the instance
169
- */
170
- i(this, "getBlocOrThrow", (e, t = {}) => {
171
- const s = e.isolated, n = t.id || e.name, o = s ? this.findIsolatedBlocInstance(e, n) : this.findRegisteredBlocInstance(e, n);
172
- if (o)
173
- return o;
174
- throw new Error(`Bloc ${e.name} not found`);
175
- });
176
- /**
177
- * Gets all instances of a specific bloc class
178
- * @param blocClass - The bloc class to search for
179
- * @param options - Options including:
180
- * - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)
181
- * @returns Array of matching bloc instances
182
- */
183
- i(this, "getAllBlocs", (e, t = {}) => {
184
- const s = [];
185
- if (this.blocInstanceMap.forEach((n) => {
186
- n.constructor === e && s.push(n);
187
- }), t.searchIsolated !== !1) {
188
- const n = this.isolatedBlocMap.get(e);
189
- n && s.push(...n.map((o) => o));
190
- }
191
- return s;
192
- });
193
- /**
194
- * Disposes all keep-alive blocs of a specific type
195
- * @param blocClass - The bloc class to dispose
196
- */
197
- i(this, "disposeKeepAliveBlocs", (e) => {
198
- const t = [];
199
- for (const s of this.keepAliveBlocs)
200
- (!e || s.constructor === e) && t.push(s);
201
- t.forEach((s) => s._dispose());
202
- });
203
- /**
204
- * Disposes all blocs matching a pattern
205
- * @param predicate - Function to test each bloc for disposal
206
- */
207
- i(this, "disposeBlocs", (e) => {
208
- const t = [];
209
- for (const s of this.blocInstanceMap.values())
210
- e(s) && t.push(s);
211
- for (const s of this.isolatedBlocMap.values())
212
- for (const n of s)
213
- e(n) && t.push(n);
214
- t.forEach((s) => s._dispose());
215
- });
216
- /**
217
- * Gets memory usage statistics for debugging
218
- */
219
- i(this, "getMemoryStats", () => ({
220
- totalBlocs: this.uidRegistry.size,
221
- registeredBlocs: this.blocInstanceMap.size,
222
- isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce(
223
- (e, t) => e + t.length,
224
- 0
225
- ),
226
- keepAliveBlocs: this.keepAliveBlocs.size,
227
- isolatedBlocTypes: this.isolatedBlocMap.size
228
- }));
229
- /**
230
- * Validates consumer references and cleans up orphaned consumers
231
- */
232
- i(this, "validateConsumers", () => {
233
- for (const e of this.uidRegistry.values())
234
- e._validateConsumers(), e._consumers.size === 0 && !e._keepAlive && e._disposalState === "active" && setTimeout(() => {
235
- e._consumers.size === 0 && !e._keepAlive && e._disposalState === "active" && this.disposeBloc(e);
236
- }, 1e3);
237
- });
238
- const { __unsafe_ignore_singleton: t = !1 } = e;
239
- if (!t)
240
- return r.instance;
241
- g.setInstance(this);
242
- }
243
- /** @deprecated Use getInstance() instead */
244
- static get instance() {
245
- return g.getInstance();
246
- }
247
- static get getAllBlocs() {
248
- return r.instance.getAllBlocs;
249
- }
250
- static get log() {
251
- return r.instance.log;
252
- }
253
- /**
254
- * Gets the current Blac instance
255
- * @returns The Blac instance
256
- */
257
- static getInstance() {
258
- return g.getInstance();
259
- }
260
- static get warn() {
261
- return r.instance.warn;
262
- }
263
- static get error() {
264
- return r.instance.error;
265
- }
266
- static get disposeBloc() {
267
- return r.instance.disposeBloc;
268
- }
269
- /**
270
- * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
271
- * @param blocClassName - The name of the bloc class
272
- * @param id - The instance ID
273
- * @returns A unique key string in the format "className:id"
274
- */
275
- createBlocInstanceMapKey(e, t) {
276
- return `${e}:${String(t)}`;
277
- }
278
- /**
279
- * Unregister a bloc instance from the main registry
280
- * @param bloc - The bloc instance to unregister
281
- */
282
- unregisterBlocInstance(e) {
283
- const t = this.createBlocInstanceMapKey(e._name, e._id);
284
- this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
285
- }
286
- /**
287
- * Registers a bloc instance in the main registry
288
- * @param bloc - The bloc instance to register
289
- */
290
- registerBlocInstance(e) {
291
- const t = this.createBlocInstanceMapKey(e._name, e._id);
292
- this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
293
- }
294
- /**
295
- * Finds a registered bloc instance by its class and ID
296
- * @param blocClass - The bloc class to search for
297
- * @param id - The instance ID
298
- * @returns The found bloc instance or undefined if not found
299
- */
300
- findRegisteredBlocInstance(e, t) {
301
- if (e.isolated) return;
302
- const n = this.createBlocInstanceMapKey(e.name, t);
303
- return this.blocInstanceMap.get(n);
304
- }
305
- /**
306
- * Registers an isolated bloc instance in the isolated registry
307
- * @param bloc - The isolated bloc instance to register
308
- */
309
- registerIsolatedBlocInstance(e) {
310
- const t = e.constructor, s = this.isolatedBlocMap.get(t);
311
- 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);
312
- }
313
- /**
314
- * Unregister an isolated bloc instance from the isolated registry
315
- * @param bloc - The isolated bloc instance to unregister
316
- */
317
- unregisterIsolatedBlocInstance(e) {
318
- const t = e.constructor, s = this.isolatedBlocMap.get(t);
319
- let n = !1;
320
- if (s) {
321
- const a = s.findIndex((c) => c.uid === e.uid);
322
- a !== -1 && (s.splice(a, 1), n = !0), s.length === 0 && this.isolatedBlocMap.delete(t);
323
- }
324
- const o = this.isolatedBlocIndex.delete(e.uid);
325
- this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), n !== o && this.warn(
326
- `[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${n}, Index removal: ${o}`
327
- );
328
- }
329
- /**
330
- * Finds an isolated bloc instance by its class and ID (O(n) lookup)
331
- */
332
- findIsolatedBlocInstance(e, t) {
333
- if (!e.isolated) return;
334
- const n = this.isolatedBlocMap.get(e);
335
- return n ? n.find((a) => a._id === t) : void 0;
336
- }
337
- /**
338
- * Finds an isolated bloc instance by UID (O(1) lookup)
339
- */
340
- findIsolatedBlocInstanceByUid(e) {
341
- return this.isolatedBlocIndex.get(e);
342
- }
343
- /**
344
- * Creates a new bloc instance and registers it in the appropriate registry
345
- * @param blocClass - The bloc class to instantiate
346
- * @param id - The instance ID
347
- * @param props - Properties to pass to the bloc constructor
348
- * @param instanceRef - Optional reference string for the instance
349
- * @returns The newly created bloc instance
350
- */
351
- createNewBlocInstance(e, t, s = {}) {
352
- const { props: n, instanceRef: o } = s, a = new e(n);
353
- return a._instanceRef = o, a.props = n || null, a._updateId(t), a._setDisposalHandler((c) => this.disposeBloc(c)), a.isIsolated ? (this.registerIsolatedBlocInstance(a), a) : (this.registerBlocInstance(a), a);
354
- }
355
- static get activateBloc() {
356
- return r.instance.activateBloc;
357
- }
358
- static get getBloc() {
359
- return r.instance.getBloc;
360
- }
361
- static get getBlocOrThrow() {
362
- return r.instance.getBlocOrThrow;
363
- }
364
- static get disposeKeepAliveBlocs() {
365
- return r.instance.disposeKeepAliveBlocs;
366
- }
367
- static get disposeBlocs() {
368
- return r.instance.disposeBlocs;
369
- }
370
- static get getMemoryStats() {
371
- return r.instance.getMemoryStats;
372
- }
373
- static get validateConsumers() {
374
- return r.instance.validateConsumers;
375
- }
376
- };
377
- /** Flag to enable/disable logging */
378
- i(r, "enableLog", !1), i(r, "logLevel", "warn"), i(r, "resetInstance", () => {
379
- g.resetInstance();
380
- });
381
- let l = r;
382
- class w {
1
+ var M = Object.defineProperty;
2
+ var P = (u, e, t) => e in u ? M(u, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : u[e] = t;
3
+ var n = (u, e, t) => P(u, typeof e != "symbol" ? e + "" : e, t);
4
+ class E {
383
5
  /**
384
6
  * Creates a new BlacObservable instance
385
7
  * @param bloc - The Bloc instance to observe
386
8
  */
387
9
  constructor(e) {
388
10
  /** The Bloc instance this observable is associated with */
389
- i(this, "bloc");
390
- i(this, "_observers", /* @__PURE__ */ new Set());
11
+ n(this, "bloc");
12
+ n(this, "_observers", /* @__PURE__ */ new Set());
391
13
  this.bloc = e;
392
14
  }
393
15
  /**
@@ -410,16 +32,38 @@ class w {
410
32
  * @returns A function that can be called to unsubscribe the observer
411
33
  */
412
34
  subscribe(e) {
413
- return l.log("BlacObservable.subscribe: Subscribing observer.", this.bloc, e), this._observers.add(e), () => {
414
- l.log("BlacObservable.subscribe: Unsubscribing observer.", this.bloc, e), this.unsubscribe(e);
415
- };
35
+ const t = this.bloc._disposalState;
36
+ return t === _.DISPOSED || t === _.DISPOSING ? (f.log(
37
+ "BlacObservable.subscribe: Cannot subscribe to disposed/disposing bloc.",
38
+ this.bloc,
39
+ e
40
+ ), () => {
41
+ }) : (f.log(
42
+ "BlacObservable.subscribe: Subscribing observer.",
43
+ this.bloc,
44
+ e
45
+ ), this._observers.add(e), t === _.DISPOSAL_REQUESTED && (f.log(
46
+ "BlacObservable.subscribe: Cancelling disposal due to new subscription.",
47
+ this.bloc
48
+ ), this.bloc._atomicStateTransition(
49
+ _.DISPOSAL_REQUESTED,
50
+ _.ACTIVE
51
+ )), () => {
52
+ f.log(
53
+ "BlacObservable.subscribe: Unsubscribing observer.",
54
+ this.bloc,
55
+ e
56
+ ), this.unsubscribe(e);
57
+ });
416
58
  }
417
59
  /**
418
60
  * Unsubscribes an observer from state changes
419
61
  * @param observer - The observer to unsubscribe
420
62
  */
421
63
  unsubscribe(e) {
422
- this._observers.delete(e), this.size === 0 && (l.log("BlacObservable.unsubscribe: No observers left.", this.bloc), this.bloc._consumers.size === 0 && !this.bloc._keepAlive && this.bloc._disposalState === "active" && (l.log(`[${this.bloc._name}:${this.bloc._id}] No observers or consumers left. Scheduling disposal.`), this.bloc._scheduleDisposal()));
64
+ this._observers.delete(e), this.size === 0 && (f.log("BlacObservable.unsubscribe: No observers left.", this.bloc), this.bloc._consumers.size === 0 && !this.bloc._keepAlive && this.bloc._disposalState === _.ACTIVE && (f.log(
65
+ `[${this.bloc._name}:${this.bloc._id}] No observers or consumers left. Scheduling disposal.`
66
+ ), this.bloc._scheduleDisposal()));
423
67
  }
424
68
  /**
425
69
  * Notifies all observers of a state change
@@ -428,32 +72,28 @@ class w {
428
72
  * @param action - Optional action that triggered the state change
429
73
  */
430
74
  notify(e, t, s) {
431
- this._observers.forEach((n) => {
432
- let o = !1;
433
- if (n.dependencyArray) {
434
- const a = n.lastState, c = n.dependencyArray(e, t);
75
+ this._observers.forEach((i) => {
76
+ let r = !1;
77
+ if (i.dependencyArray) {
78
+ const a = i.lastState, o = i.dependencyArray(
79
+ e,
80
+ t,
81
+ this.bloc
82
+ );
435
83
  if (!a)
436
- o = !0;
437
- else if (a.length !== c.length)
438
- o = !0;
84
+ r = !0;
85
+ else if (a.length !== o.length)
86
+ r = !0;
439
87
  else
440
- for (let h = 0; h < c.length; h++) {
441
- const _ = a[h] || [], p = c[h] || [];
442
- if (_.length !== p.length) {
443
- o = !0;
88
+ for (let l = 0; l < o.length; l++)
89
+ if (!Object.is(a[l], o[l])) {
90
+ r = !0;
444
91
  break;
445
92
  }
446
- for (let f = 0; f < p.length; f++)
447
- if (!Object.is(_[f], p[f])) {
448
- o = !0;
449
- break;
450
- }
451
- if (o) break;
452
- }
453
- n.lastState = c;
93
+ i.lastState = o;
454
94
  } else
455
- o = !0;
456
- o && n.fn(e, t, s);
95
+ r = !0;
96
+ r && i.fn(e, t, s);
457
97
  });
458
98
  }
459
99
  /**
@@ -463,97 +103,103 @@ class w {
463
103
  this._observers.clear();
464
104
  }
465
105
  }
466
- function b() {
467
- return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(d) {
106
+ function R() {
107
+ return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(u) {
468
108
  const e = Math.random() * 16 | 0;
469
- return (d === "x" ? e : e & 3 | 8).toString(16);
109
+ return (u === "x" ? e : e & 3 | 8).toString(16);
470
110
  });
471
111
  }
472
- class v {
112
+ var _ = /* @__PURE__ */ ((u) => (u.ACTIVE = "active", u.DISPOSAL_REQUESTED = "disposal_requested", u.DISPOSING = "disposing", u.DISPOSED = "disposed", u))(_ || {});
113
+ class k {
473
114
  /**
474
115
  * Creates a new BlocBase instance with the given initial state.
475
116
  * Sets up the observer, registers with the Blac manager, and initializes addons.
476
- *
117
+ *
477
118
  * @param initialState The initial state value for this Bloc
478
119
  */
479
120
  constructor(e) {
480
- i(this, "uid", b());
121
+ n(this, "uid", R());
481
122
  /**
482
123
  * Defines how dependencies are selected from the state for efficient updates.
483
124
  * When provided, observers will only be notified when selected dependencies change.
484
125
  */
485
- i(this, "defaultDependencySelector");
126
+ n(this, "defaultDependencySelector");
486
127
  /**
487
128
  * @internal
488
129
  * Indicates if this specific Bloc instance is isolated from others of the same type.
489
130
  */
490
- i(this, "_isolated", !1);
131
+ n(this, "_isolated", !1);
491
132
  /**
492
133
  * @internal
493
134
  * Observable responsible for managing state listeners and notifying consumers.
494
135
  */
495
- i(this, "_observer");
136
+ n(this, "_observer");
496
137
  /**
497
138
  * The unique identifier for this Bloc instance.
498
139
  * Defaults to the class name, but can be customized.
499
140
  */
500
- i(this, "_id");
141
+ n(this, "_id");
501
142
  /**
502
143
  * @internal
503
144
  * Reference string used internally for tracking and debugging.
504
145
  */
505
- i(this, "_instanceRef");
146
+ n(this, "_instanceRef");
506
147
  /**
507
148
  * @internal
508
149
  * Indicates if this specific Bloc instance should be kept alive when no consumers are present.
509
150
  */
510
- i(this, "_keepAlive", !1);
151
+ n(this, "_keepAlive", !1);
511
152
  /**
512
153
  * @readonly
513
154
  * Timestamp when this Bloc instance was created, useful for debugging and performance tracking.
514
155
  */
515
- i(this, "_createdAt", Date.now());
156
+ n(this, "_createdAt", Date.now());
516
157
  /**
517
158
  * @internal
518
- * Disposal state to prevent race conditions
159
+ * Atomic disposal state to prevent race conditions
519
160
  */
520
- i(this, "_disposalState", "active");
161
+ n(this, "_disposalState", "active");
162
+ /**
163
+ * @internal
164
+ * Timestamp when disposal was requested (for React Strict Mode grace period)
165
+ */
166
+ n(this, "_disposalRequestTime", 0);
521
167
  /**
522
168
  * @internal
523
169
  * The current state of the Bloc.
524
170
  */
525
- i(this, "_state");
171
+ n(this, "_state");
526
172
  /**
527
173
  * @internal
528
174
  * The previous state of the Bloc, maintained for comparison and history.
529
175
  */
530
- i(this, "_oldState");
176
+ n(this, "_oldState");
531
177
  /**
532
178
  * Props passed during Bloc instance creation.
533
179
  * Can be used to configure or parameterize the Bloc's behavior.
534
180
  */
535
- i(this, "props", null);
181
+ n(this, "props", null);
536
182
  /**
537
183
  * @internal
538
184
  * Flag to prevent batching race conditions
539
185
  */
540
- i(this, "_batchingLock", !1);
186
+ n(this, "_batchingLock", !1);
541
187
  /**
542
188
  * @internal
543
189
  * Pending batched updates
544
190
  */
545
- i(this, "_pendingUpdates", []);
191
+ n(this, "_pendingUpdates", []);
546
192
  /**
547
193
  * @internal
548
194
  * Map of consumer IDs to their WeakRef objects for proper cleanup
549
195
  */
550
- i(this, "_consumerRefs", /* @__PURE__ */ new Map());
196
+ n(this, "_consumerRefs", /* @__PURE__ */ new Map());
551
197
  /**
552
198
  * @internal
553
199
  * Validates that all consumer references are still alive
554
200
  * Removes dead consumers automatically
555
201
  */
556
- i(this, "_validateConsumers", () => {
202
+ n(this, "_validateConsumers", () => {
557
203
  const e = [];
558
204
  for (const [t, s] of this._consumerRefs)
559
205
  s.deref() === void 0 && e.push(t);
@@ -565,10 +211,10 @@ class v {
565
211
  * @internal
566
212
  * Updates the Bloc instance's ID to a new value.
567
213
  * Only updates if the new ID is defined and different from the current one.
568
- *
214
+ *
569
215
  * @param id The new ID to assign to this Bloc instance
570
216
  */
571
- i(this, "_updateId", (e) => {
217
+ n(this, "_updateId", (e) => {
572
218
  const t = this._id;
573
219
  !e || e === t || (this._id = e);
574
220
  });
@@ -576,170 +222,631 @@ class v {
576
222
  * @internal
577
223
  * Optional function to be called when the Bloc is disposed.
578
224
  */
579
- i(this, "onDispose");
225
+ n(this, "onDispose");
580
226
  /**
581
227
  * @internal
582
228
  * Set of consumer IDs currently listening to this Bloc's state changes.
583
229
  */
584
- i(this, "_consumers", /* @__PURE__ */ new Set());
230
+ n(this, "_consumers", /* @__PURE__ */ new Set());
585
231
  /**
586
232
  * @internal
587
233
  * Registers a new consumer to this Bloc instance.
588
234
  * Notifies the Blac manager that a consumer has been added.
589
- *
235
+ *
590
236
  * @param consumerId The unique ID of the consumer being added
591
237
  * @param consumerRef Optional reference to the consumer object for cleanup validation
592
238
  */
593
- i(this, "_addConsumer", (e, t) => {
239
+ n(this, "_addConsumer", (e, t) => {
594
240
  var s;
595
- this._disposalState === "active" && (this._consumers.has(e) || (this._consumers.add(e), t && this._consumerRefs.set(e, new WeakRef(t)), (s = globalThis.Blac) == null || s.log(`[${this._name}:${this._id}] Consumer added. Total consumers: ${this._consumers.size}`)));
241
+ return this._disposalState !== "active" ? !1 : (this._consumers.has(e) || (this._consumers.add(e), t && this._consumerRefs.set(e, new WeakRef(t)), (s = globalThis.Blac) == null || s.log(
242
+ `[${this._name}:${this._id}] Consumer added. Total consumers: ${this._consumers.size}`
243
+ )), !0);
596
244
  });
597
245
  /**
598
246
  * @internal
599
247
  * Unregisters a consumer from this Bloc instance.
600
248
  * Notifies the Blac manager that a consumer has been removed.
601
- *
249
+ *
602
250
  * @param consumerId The unique ID of the consumer being removed
603
251
  */
604
- i(this, "_removeConsumer", (e) => {
252
+ n(this, "_removeConsumer", (e) => {
605
253
  var t, s;
606
- this._consumers.has(e) && (this._consumers.delete(e), this._consumerRefs.delete(e), (t = globalThis.Blac) == null || t.log(`[${this._name}:${this._id}] Consumer removed. Remaining consumers: ${this._consumers.size}, keepAlive: ${this._keepAlive}`), this._consumers.size === 0 && !this._keepAlive && this._disposalState === "active" && ((s = globalThis.Blac) == null || s.log(`[${this._name}:${this._id}] No consumers left and not keep-alive. Scheduling disposal.`), this._scheduleDisposal()));
254
+ this._consumers.has(e) && (this._consumers.delete(e), this._consumerRefs.delete(e), (t = globalThis.Blac) == null || t.log(
255
+ `[${this._name}:${this._id}] Consumer removed. Remaining consumers: ${this._consumers.size}, keepAlive: ${this._keepAlive}`
256
+ ), this._consumers.size === 0 && !this._keepAlive && this._disposalState === "active" && ((s = globalThis.Blac) == null || s.log(
257
+ `[${this._name}:${this._id}] No consumers left and not keep-alive. Scheduling disposal.`
258
+ ), this._scheduleDisposal()));
259
+ });
260
+ /**
261
+ * @internal
262
+ * Handler function for disposal (can be set by Blac manager)
263
+ */
264
+ n(this, "_disposalHandler");
265
+ n(this, "lastUpdate", Date.now());
266
+ /**
267
+ * @internal
268
+ * Flag to indicate if batching is enabled for this bloc
269
+ */
270
+ n(this, "_batchingEnabled", !1);
271
+ /**
272
+ * @internal
273
+ * Updates the state and notifies all observers of the change.
274
+ *
275
+ * @param newState The new state to be set
276
+ * @param oldState The previous state for comparison
277
+ * @param action Optional metadata about what caused the state change
278
+ */
279
+ n(this, "_pushState", (e, t, s) => {
280
+ if (e !== void 0 && !(s !== void 0 && typeof s != "object" && typeof s != "function")) {
281
+ if (this._batchingEnabled) {
282
+ this._pendingUpdates.push({ newState: e, oldState: t, action: s }), this._oldState = t, this._state = e;
283
+ return;
284
+ }
285
+ this._oldState = t, this._state = e, this._observer.notify(e, t, s), this.lastUpdate = Date.now();
286
+ }
287
+ });
288
+ /**
289
+ * Enables batching for multiple state updates
290
+ * @param batchFn Function to execute with batching enabled
291
+ */
292
+ n(this, "batch", (e) => {
293
+ if (this._batchingLock)
294
+ return e();
295
+ this._batchingLock = !0, this._batchingEnabled = !0, this._pendingUpdates = [];
296
+ try {
297
+ const t = e();
298
+ if (this._pendingUpdates.length > 0) {
299
+ const s = this._pendingUpdates[this._pendingUpdates.length - 1];
300
+ this._observer.notify(
301
+ s.newState,
302
+ s.oldState,
303
+ s.action
304
+ ), this.lastUpdate = Date.now();
305
+ }
306
+ return t;
307
+ } finally {
308
+ this._batchingEnabled = !1, this._batchingLock = !1, this._pendingUpdates = [];
309
+ }
310
+ });
311
+ this._state = e, this._observer = new E(this), this._id = this.constructor.name;
312
+ const t = this.constructor;
313
+ this._keepAlive = typeof t.keepAlive == "boolean" ? t.keepAlive : !1, this._isolated = typeof t.isolated == "boolean" ? t.isolated : !1;
314
+ }
315
+ get isIsolated() {
316
+ return this._isolated;
317
+ }
318
+ get isKeepAlive() {
319
+ return this._keepAlive;
320
+ }
321
+ /**
322
+ * Returns the current state of the Bloc.
323
+ * Use this getter to access the state in a read-only manner.
324
+ * Returns the state even during transitional lifecycle states for React compatibility.
325
+ */
326
+ get state() {
327
+ return this._disposalState === "disposed" ? this._state : this._state;
328
+ }
329
+ /**
330
+ * Returns whether this Bloc instance has been disposed.
331
+ * @returns true if the bloc is in DISPOSED state
332
+ */
333
+ get isDisposed() {
334
+ return this._disposalState === "disposed";
335
+ }
336
+ /**
337
+ * @internal
338
+ * Returns the name of the Bloc class for identification and debugging.
339
+ */
340
+ get _name() {
341
+ return this.constructor.name;
342
+ }
343
+ /**
344
+ * @internal
345
+ * Performs atomic state transition using compare-and-swap semantics
346
+ * @param expectedState The expected current state
347
+ * @param newState The desired new state
348
+ * @returns Result indicating success/failure and state information
349
+ */
350
+ _atomicStateTransition(e, t) {
351
+ var s, i, r, a;
352
+ if (this._disposalState === e) {
353
+ const o = this._disposalState;
354
+ return this._disposalState = t, (s = globalThis.Blac) != null && s.enableLog && ((i = globalThis.Blac) == null || i.log(
355
+ `[${this._name}:${this._id}] State transition: ${o} -> ${t} (SUCCESS)`
356
+ )), {
357
+ success: !0,
358
+ currentState: t,
359
+ previousState: o
360
+ };
361
+ }
362
+ return (r = globalThis.Blac) != null && r.enableLog && ((a = globalThis.Blac) == null || a.log(
363
+ `[${this._name}:${this._id}] State transition failed: expected ${e}, current ${this._disposalState}`
364
+ )), {
365
+ success: !1,
366
+ currentState: this._disposalState,
367
+ previousState: e
368
+ };
369
+ }
370
+ /**
371
+ * @internal
372
+ * Cleans up resources and removes this Bloc from the system.
373
+ * Notifies the Blac manager and clears all observers.
374
+ */
375
+ _dispose() {
376
+ var t;
377
+ let e = this._atomicStateTransition(
378
+ "active",
379
+ "disposing"
380
+ /* DISPOSING */
381
+ );
382
+ if (e.success || (e = this._atomicStateTransition(
383
+ "disposal_requested",
384
+ "disposing"
385
+ /* DISPOSING */
386
+ )), !e.success)
387
+ return !1;
388
+ try {
389
+ return this._consumers.clear(), this._consumerRefs.clear(), this._observer.clear(), (t = this.onDispose) == null || t.call(this), this._atomicStateTransition(
390
+ "disposing",
391
+ "disposed"
392
+ /* DISPOSED */
393
+ ).success;
394
+ } catch (s) {
395
+ throw this._disposalState = "active", s;
396
+ }
397
+ }
398
+ /**
399
+ * @internal
400
+ * Sets the disposal handler for this bloc
401
+ */
402
+ _setDisposalHandler(e) {
403
+ this._disposalHandler = e;
404
+ }
405
+ /**
406
+ * @internal
407
+ * Schedules disposal of this bloc instance if it has no consumers
408
+ * Uses atomic state transitions to prevent race conditions
409
+ */
410
+ _scheduleDisposal() {
411
+ if (!this._atomicStateTransition(
412
+ "active",
413
+ "disposal_requested"
414
+ /* DISPOSAL_REQUESTED */
415
+ ).success)
416
+ return;
417
+ if (!(this._consumers.size === 0 && !this._keepAlive)) {
418
+ this._atomicStateTransition(
419
+ "disposal_requested",
420
+ "active"
421
+ /* ACTIVE */
422
+ );
423
+ return;
424
+ }
425
+ this._disposalRequestTime = Date.now(), queueMicrotask(() => {
426
+ this._consumers.size === 0 && !this._keepAlive && this._observer.size === 0 && this._disposalState === "disposal_requested" ? this._disposalHandler ? this._disposalHandler(this) : this._dispose() : this._atomicStateTransition(
427
+ "disposal_requested",
428
+ "active"
429
+ /* ACTIVE */
430
+ );
431
+ });
432
+ }
433
+ }
434
+ /**
435
+ * When true, every consumer will receive its own unique instance of this Bloc.
436
+ * Use this when state should not be shared between components.
437
+ * @default false
438
+ */
439
+ n(k, "isolated", !1), /**
440
+ * When true, the Bloc instance persists even when there are no active consumers.
441
+ * Useful for maintaining state between component unmount/remount cycles.
442
+ * @default false
443
+ */
444
+ n(k, "keepAlive", !1);
445
+ const I = class I {
446
+ getInstance() {
447
+ return I._instance || (I._instance = new f({
448
+ __unsafe_ignore_singleton: !0
449
+ })), I._instance;
450
+ }
451
+ setInstance(e) {
452
+ I._instance = e;
453
+ }
454
+ resetInstance() {
455
+ const e = I._instance;
456
+ if (I._instance = new f({
457
+ __unsafe_ignore_singleton: !0
458
+ }), e)
459
+ for (const t of e.keepAliveBlocs)
460
+ I._instance.keepAliveBlocs.add(t), I._instance.uidRegistry.set(t.uid, t);
461
+ }
462
+ };
463
+ n(I, "_instance");
464
+ let T = I, b = new T();
465
+ function L(u) {
466
+ b = u;
467
+ }
468
+ const c = class c {
469
+ /**
470
+ * Creates a new Blac instance.
471
+ * @param options - Configuration options including singleton control
472
+ */
473
+ constructor(e = {}) {
474
+ /** Timestamp when the instance was created */
475
+ n(this, "createdAt", Date.now());
476
+ /** Map storing all registered bloc instances by their class name and ID */
477
+ n(this, "blocInstanceMap", /* @__PURE__ */ new Map());
478
+ /** Map storing isolated bloc instances grouped by their constructor */
479
+ // Using BlocConstructor<BlocBase<unknown>> would break type inference when storing
480
+ // different bloc types in the same map. The 'any' allows proper polymorphic storage
481
+ // while maintaining type safety at usage sites through the BlocConstructor constraint.
482
+ n(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
483
+ /** Map for O(1) lookup of isolated blocs by UID */
484
+ n(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
485
+ /** Map tracking UIDs to prevent memory leaks */
486
+ n(this, "uidRegistry", /* @__PURE__ */ new Map());
487
+ /** Set of keep-alive blocs for controlled cleanup */
488
+ n(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
489
+ /** Flag to control whether changes should be posted to document */
490
+ n(this, "postChangesToDocument", !1);
491
+ /**
492
+ * Logs messages to console when logging is enabled
493
+ * @param args - Arguments to log
494
+ */
495
+ n(this, "log", (...e) => {
496
+ c.logSpy && c.logSpy(e), c.enableLog && c.logLevel, c.enableLog && c.logLevel;
497
+ });
498
+ /**
499
+ * Logs a warning message
500
+ * @param message - Warning message
501
+ * @param args - Additional arguments
502
+ */
503
+ n(this, "warn", (e, ...t) => {
504
+ c.enableLog;
505
+ });
506
+ /**
507
+ * Logs an error message
508
+ * @param message - Error message
509
+ * @param args - Additional arguments
510
+ */
511
+ n(this, "error", (e, ...t) => {
512
+ c.enableLog;
513
+ });
514
+ /**
515
+ * Resets the Blac instance to a new one, disposing non-keepAlive blocs
516
+ * from the old instance.
517
+ */
518
+ n(this, "resetInstance", () => {
519
+ this.log("Reset Blac instance");
520
+ const e = new Map(this.blocInstanceMap), t = new Map(this.isolatedBlocMap);
521
+ e.forEach((s) => {
522
+ !s._keepAlive && s._disposalState === _.ACTIVE && this.disposeBloc(s);
523
+ }), t.forEach((s) => {
524
+ s.forEach((i) => {
525
+ !i._keepAlive && i._disposalState === _.ACTIVE && this.disposeBloc(i);
526
+ });
527
+ }), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), b.resetInstance();
528
+ });
529
+ /**
530
+ * Disposes of a bloc instance by removing it from the appropriate registry
531
+ * @param bloc - The bloc instance to dispose
532
+ */
533
+ n(this, "disposeBloc", (e) => {
534
+ const t = e._disposalState;
535
+ if (![
536
+ _.ACTIVE,
537
+ _.DISPOSAL_REQUESTED
538
+ ].includes(t)) {
539
+ this.log(
540
+ `[${e._name}:${String(e._id)}] disposeBloc called on bloc in invalid state: ${t}`
541
+ );
542
+ return;
543
+ }
544
+ const i = e.constructor, r = this.createBlocInstanceMapKey(e._name, e._id);
545
+ this.log(
546
+ `[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(i.isolated)}`
547
+ ), e._dispose(), i.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(r)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
548
+ });
549
+ n(this, "activateBloc", (e) => {
550
+ if (e._disposalState !== _.ACTIVE) {
551
+ this.log(
552
+ `[${e._name}:${String(e._id)}] activateBloc called on disposed bloc. Ignoring.`
553
+ );
554
+ return;
555
+ }
556
+ const t = e.constructor;
557
+ (e.isIsolated ? this.findIsolatedBlocInstance(t, e._id) : this.findRegisteredBlocInstance(t, e._id)) || (this.log(
558
+ `[${e._name}:${String(e._id)}] activateBloc called. Isolated: ${String(e.isIsolated)}`
559
+ ), e.isIsolated ? this.registerIsolatedBlocInstance(e) : this.registerBlocInstance(e));
560
+ });
561
+ /**
562
+ * Gets or creates a bloc instance based on the provided class and options.
563
+ * If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.
564
+ *
565
+ * @param blocClass - The bloc class to get or create
566
+ * @param options - Options including:
567
+ * - id: The instance ID (defaults to class name if not provided)
568
+ * - props: Properties to pass to the bloc constructor
569
+ * - instanceRef: Optional reference string for the instance
570
+ * @returns The bloc instance
571
+ */
572
+ n(this, "getBloc", (e, t = {}) => {
573
+ const { id: s, forceNewInstance: i } = t, r = e, a = s ?? e.name;
574
+ if (this.log(`[${e.name}:${String(a)}] (getBloc) Called:`, {
575
+ options: t,
576
+ base: r
577
+ }), !i)
578
+ if (r.isolated) {
579
+ const l = this.findIsolatedBlocInstance(
580
+ e,
581
+ t.instanceRef ?? a
582
+ );
583
+ if (l)
584
+ return l;
585
+ if (t.throwIfNotFound)
586
+ throw new Error(`Isolated bloc ${e.name} not found`);
587
+ } else {
588
+ const l = this.findRegisteredBlocInstance(
589
+ e,
590
+ a
591
+ );
592
+ if (l)
593
+ return l;
594
+ if (t.throwIfNotFound)
595
+ throw new Error(`Registered bloc ${e.name} not found`);
596
+ }
597
+ const o = this.createNewBlocInstance(e, a, t);
598
+ if (this.log(
599
+ `[${e.name}:${String(a)}] (getBloc) No existing instance found. Creating new one.`,
600
+ t,
601
+ o
602
+ ), !o)
603
+ throw new Error(
604
+ `[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`
605
+ );
606
+ return o;
607
+ });
608
+ /**
609
+ * Gets a bloc instance or throws an error if it doesn't exist
610
+ * @param blocClass - The bloc class to get
611
+ * @param options - Options including:
612
+ * - id: The instance ID (defaults to class name if not provided)
613
+ * - props: Properties to pass to the bloc constructor
614
+ * - instanceRef: Optional reference string for the instance
615
+ */
616
+ n(this, "getBlocOrThrow", (e, t = {}) => {
617
+ const s = e.isolated, i = t.id || e.name, r = s ? this.findIsolatedBlocInstance(e, i) : this.findRegisteredBlocInstance(e, i);
618
+ if (r)
619
+ return r;
620
+ throw new Error(`Bloc ${e.name} not found`);
621
+ });
622
+ /**
623
+ * Gets all instances of a specific bloc class
624
+ * @param blocClass - The bloc class to search for
625
+ * @param options - Options including:
626
+ * - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)
627
+ * @returns Array of matching bloc instances
628
+ */
629
+ n(this, "getAllBlocs", (e, t = {}) => {
630
+ const s = [];
631
+ if (this.blocInstanceMap.forEach((i) => {
632
+ i.constructor === e && s.push(i);
633
+ }), t.searchIsolated !== !1) {
634
+ const i = this.isolatedBlocMap.get(e);
635
+ i && s.push(...i.map((r) => r));
636
+ }
637
+ return s;
607
638
  });
608
639
  /**
609
- * @internal
610
- * Handler function for disposal (can be set by Blac manager)
640
+ * Disposes all keep-alive blocs of a specific type
641
+ * @param blocClass - The bloc class to dispose
611
642
  */
612
- i(this, "_disposalHandler");
613
- i(this, "lastUpdate", Date.now());
643
+ n(this, "disposeKeepAliveBlocs", (e) => {
644
+ const t = [];
645
+ for (const s of this.keepAliveBlocs)
646
+ (!e || s.constructor === e) && t.push(s);
647
+ t.forEach((s) => s._dispose());
648
+ });
614
649
  /**
615
- * @internal
616
- * Flag to indicate if batching is enabled for this bloc
650
+ * Disposes all blocs matching a pattern
651
+ * @param predicate - Function to test each bloc for disposal
617
652
  */
618
- i(this, "_batchingEnabled", !1);
653
+ n(this, "disposeBlocs", (e) => {
654
+ const t = [];
655
+ for (const s of this.blocInstanceMap.values())
656
+ e(s) && t.push(s);
657
+ for (const s of this.isolatedBlocMap.values())
658
+ for (const i of s)
659
+ e(i) && t.push(i);
660
+ t.forEach((s) => s._dispose());
661
+ });
619
662
  /**
620
- * @internal
621
- * Updates the state and notifies all observers of the change.
622
- *
623
- * @param newState The new state to be set
624
- * @param oldState The previous state for comparison
625
- * @param action Optional metadata about what caused the state change
663
+ * Gets memory usage statistics for debugging
626
664
  */
627
- i(this, "_pushState", (e, t, s) => {
628
- if (e === void 0) {
629
- console.warn("BlocBase._pushState: newState is undefined", this);
630
- return;
631
- }
632
- if (s !== void 0 && typeof s != "object" && typeof s != "function") {
633
- console.warn("BlocBase._pushState: Invalid action type", this, s);
634
- return;
635
- }
636
- if (this._batchingEnabled) {
637
- this._pendingUpdates.push({ newState: e, oldState: t, action: s }), this._oldState = t, this._state = e;
638
- return;
639
- }
640
- this._oldState = t, this._state = e, this._observer.notify(e, t, s), this.lastUpdate = Date.now();
641
- });
665
+ n(this, "getMemoryStats", () => ({
666
+ totalBlocs: this.uidRegistry.size,
667
+ registeredBlocs: this.blocInstanceMap.size,
668
+ isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce(
669
+ (e, t) => e + t.length,
670
+ 0
671
+ ),
672
+ keepAliveBlocs: this.keepAliveBlocs.size,
673
+ isolatedBlocTypes: this.isolatedBlocMap.size
674
+ }));
642
675
  /**
643
- * Enables batching for multiple state updates
644
- * @param batchFn Function to execute with batching enabled
676
+ * Validates consumer references and cleans up orphaned consumers
645
677
  */
646
- i(this, "batch", (e) => {
647
- if (this._batchingLock)
648
- return e();
649
- this._batchingLock = !0, this._batchingEnabled = !0, this._pendingUpdates = [];
650
- try {
651
- const t = e();
652
- if (this._pendingUpdates.length > 0) {
653
- const s = this._pendingUpdates[this._pendingUpdates.length - 1];
654
- this._observer.notify(s.newState, s.oldState, s.action), this.lastUpdate = Date.now();
655
- }
656
- return t;
657
- } finally {
658
- this._batchingEnabled = !1, this._batchingLock = !1, this._pendingUpdates = [];
659
- }
678
+ n(this, "validateConsumers", () => {
679
+ for (const e of this.uidRegistry.values())
680
+ e._validateConsumers(), e._consumers.size === 0 && !e._keepAlive && e._disposalState === _.ACTIVE && setTimeout(() => {
681
+ e._consumers.size === 0 && !e._keepAlive && e._disposalState === _.ACTIVE && this.disposeBloc(e);
682
+ }, 1e3);
660
683
  });
661
- this._state = e, this._observer = new w(this), this._id = this.constructor.name;
662
- const t = this.constructor;
663
- this._keepAlive = typeof t.keepAlive == "boolean" ? t.keepAlive : !1, this._isolated = typeof t.isolated == "boolean" ? t.isolated : !1;
684
+ const { __unsafe_ignore_singleton: t = !1 } = e;
685
+ if (!t)
686
+ return c.instance;
687
+ b.setInstance(this);
664
688
  }
665
- get isIsolated() {
666
- return this._isolated;
689
+ static get instance() {
690
+ return b.getInstance();
667
691
  }
668
- get isKeepAlive() {
669
- return this._keepAlive;
692
+ static get getAllBlocs() {
693
+ return c.instance.getAllBlocs;
694
+ }
695
+ static get log() {
696
+ return c.instance.log;
670
697
  }
671
698
  /**
672
- * Returns the current state of the Bloc.
673
- * Use this getter to access the state in a read-only manner.
699
+ * Gets the current Blac instance
700
+ * @returns The Blac instance
674
701
  */
675
- get state() {
676
- return this._state;
702
+ static getInstance() {
703
+ return b.getInstance();
704
+ }
705
+ static get warn() {
706
+ return c.instance.warn;
707
+ }
708
+ static get error() {
709
+ return c.instance.error;
710
+ }
711
+ static get disposeBloc() {
712
+ return c.instance.disposeBloc;
677
713
  }
678
714
  /**
679
- * @internal
680
- * Returns the name of the Bloc class for identification and debugging.
715
+ * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
716
+ * @param blocClassName - The name of the bloc class
717
+ * @param id - The instance ID
718
+ * @returns A unique key string in the format "className:id"
681
719
  */
682
- get _name() {
683
- return this.constructor.name;
720
+ createBlocInstanceMapKey(e, t) {
721
+ return `${e}:${String(t)}`;
684
722
  }
685
723
  /**
686
- * @internal
687
- * Cleans up resources and removes this Bloc from the system.
688
- * Notifies the Blac manager and clears all observers.
724
+ * Unregister a bloc instance from the main registry
725
+ * @param bloc - The bloc instance to unregister
689
726
  */
690
- _dispose() {
691
- var e;
692
- this._disposalState === "active" && (this._disposalState = "disposing", this._consumers.clear(), this._consumerRefs.clear(), this._observer.clear(), (e = this.onDispose) == null || e.call(this), this._disposalState = "disposed");
727
+ unregisterBlocInstance(e) {
728
+ const t = this.createBlocInstanceMapKey(e._name, e._id);
729
+ this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
693
730
  }
694
731
  /**
695
- * @internal
696
- * Sets the disposal handler for this bloc
732
+ * Registers a bloc instance in the main registry
733
+ * @param bloc - The bloc instance to register
697
734
  */
698
- _setDisposalHandler(e) {
699
- this._disposalHandler = e;
735
+ registerBlocInstance(e) {
736
+ const t = this.createBlocInstanceMapKey(e._name, e._id);
737
+ this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
700
738
  }
701
739
  /**
702
- * @internal
703
- * Schedules disposal of this bloc instance if it has no consumers
740
+ * Finds a registered bloc instance by its class and ID
741
+ * @param blocClass - The bloc class to search for
742
+ * @param id - The instance ID
743
+ * @returns The found bloc instance or undefined if not found
704
744
  */
705
- _scheduleDisposal() {
706
- this._disposalState === "active" && this._consumers.size === 0 && !this._keepAlive && (this._disposalHandler ? this._disposalHandler(this) : this._dispose());
745
+ findRegisteredBlocInstance(e, t) {
746
+ if (e.isolated) return;
747
+ const i = this.createBlocInstanceMapKey(e.name, t);
748
+ return this.blocInstanceMap.get(i);
707
749
  }
708
- }
709
- /**
710
- * When true, every consumer will receive its own unique instance of this Bloc.
711
- * Use this when state should not be shared between components.
712
- * @default false
713
- */
714
- i(v, "isolated", !1), /**
715
- * When true, the Bloc instance persists even when there are no active consumers.
716
- * Useful for maintaining state between component unmount/remount cycles.
717
- * @default false
718
- */
719
- i(v, "keepAlive", !1);
720
- class S extends v {
750
+ /**
751
+ * Registers an isolated bloc instance in the isolated registry
752
+ * @param bloc - The isolated bloc instance to register
753
+ */
754
+ registerIsolatedBlocInstance(e) {
755
+ const t = e.constructor, s = this.isolatedBlocMap.get(t);
756
+ 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);
757
+ }
758
+ /**
759
+ * Unregister an isolated bloc instance from the isolated registry
760
+ * @param bloc - The isolated bloc instance to unregister
761
+ */
762
+ unregisterIsolatedBlocInstance(e) {
763
+ const t = e.constructor, s = this.isolatedBlocMap.get(t);
764
+ let i = !1;
765
+ if (s) {
766
+ const a = s.findIndex((o) => o.uid === e.uid);
767
+ a !== -1 && (s.splice(a, 1), i = !0), s.length === 0 && this.isolatedBlocMap.delete(t);
768
+ }
769
+ const r = this.isolatedBlocIndex.delete(e.uid);
770
+ this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), i !== r && this.warn(
771
+ `[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${i}, Index removal: ${r}`
772
+ );
773
+ }
774
+ /**
775
+ * Finds an isolated bloc instance by its class and ID (O(n) lookup)
776
+ */
777
+ findIsolatedBlocInstance(e, t) {
778
+ if (!e.isolated) return;
779
+ const i = this.isolatedBlocMap.get(e);
780
+ return i ? i.find((a) => a._id === t) : void 0;
781
+ }
782
+ /**
783
+ * Finds an isolated bloc instance by UID (O(1) lookup)
784
+ */
785
+ findIsolatedBlocInstanceByUid(e) {
786
+ return this.isolatedBlocIndex.get(e);
787
+ }
788
+ /**
789
+ * Creates a new bloc instance and registers it in the appropriate registry
790
+ * @param blocClass - The bloc class to instantiate
791
+ * @param id - The instance ID
792
+ * @param props - Properties to pass to the bloc constructor
793
+ * @param instanceRef - Optional reference string for the instance
794
+ * @returns The newly created bloc instance
795
+ */
796
+ createNewBlocInstance(e, t, s = {}) {
797
+ const { props: i, instanceRef: r } = s, a = new e(i);
798
+ return a._instanceRef = r, a.props = i || null, a._updateId(t), a._setDisposalHandler((o) => this.disposeBloc(o)), a.isIsolated ? (this.registerIsolatedBlocInstance(a), a) : (this.registerBlocInstance(a), a);
799
+ }
800
+ static get activateBloc() {
801
+ return c.instance.activateBloc;
802
+ }
803
+ static get getBloc() {
804
+ return c.instance.getBloc;
805
+ }
806
+ static get getBlocOrThrow() {
807
+ return c.instance.getBlocOrThrow;
808
+ }
809
+ static get disposeKeepAliveBlocs() {
810
+ return c.instance.disposeKeepAliveBlocs;
811
+ }
812
+ static get disposeBlocs() {
813
+ return c.instance.disposeBlocs;
814
+ }
815
+ static get getMemoryStats() {
816
+ return c.instance.getMemoryStats;
817
+ }
818
+ static get validateConsumers() {
819
+ return c.instance.validateConsumers;
820
+ }
821
+ };
822
+ /** Flag to enable/disable logging */
823
+ n(c, "enableLog", !1), n(c, "logLevel", "warn"), n(c, "logSpy", null), n(c, "resetInstance", () => {
824
+ b.resetInstance();
825
+ });
826
+ let f = c;
827
+ class O extends k {
721
828
  constructor() {
722
829
  super(...arguments);
723
830
  // Stores handlers: Map<EventConstructor (subtype of A), HandlerFunction>
724
831
  // The handler's event parameter will be correctly typed to the specific EventConstructor
725
832
  // by the 'on' method's signature.
726
- i(this, "eventHandlers", /* @__PURE__ */ new Map());
833
+ n(this, "eventHandlers", /* @__PURE__ */ new Map());
727
834
  /**
728
835
  * @internal
729
836
  * Event queue to ensure sequential processing of async events
730
837
  */
731
- i(this, "_eventQueue", []);
838
+ n(this, "_eventQueue", []);
732
839
  /**
733
840
  * @internal
734
841
  * Flag indicating if an event is currently being processed
735
842
  */
736
- i(this, "_isProcessingEvent", !1);
843
+ n(this, "_isProcessingEvent", !1);
737
844
  /**
738
845
  * Dispatches an action/event to the Bloc.
739
846
  * Events are queued and processed sequentially to prevent race conditions.
740
847
  * @param action The action/event instance to be processed.
741
848
  */
742
- i(this, "add", async (t) => {
849
+ n(this, "add", async (t) => {
743
850
  this._eventQueue.push(t), this._isProcessingEvent || await this._processEventQueue();
744
851
  });
745
852
  }
@@ -751,7 +858,7 @@ class S extends v {
751
858
  * The 'event' parameter in the handler will be typed to the specific eventConstructor.
752
859
  */
753
860
  on(t, s) {
754
- this.eventHandlers.has(t) && l.warn(
861
+ this.eventHandlers.has(t) && f.warn(
755
862
  `[Bloc ${this._name}:${String(this._id)}] Handler for event '${t.name}' already registered. It will be overwritten.`
756
863
  ), this.eventHandlers.set(
757
864
  t,
@@ -780,35 +887,35 @@ class S extends v {
780
887
  * Processes a single event
781
888
  */
782
889
  async _processEvent(t) {
783
- const s = t.constructor, n = this.eventHandlers.get(s);
784
- if (n) {
785
- const o = (a) => {
786
- const c = this.state;
787
- this._pushState(a, c, t);
890
+ const s = t.constructor, i = this.eventHandlers.get(s);
891
+ if (i) {
892
+ const r = (a) => {
893
+ const o = this.state;
894
+ this._pushState(a, o, t);
788
895
  };
789
896
  try {
790
- await n(t, o);
897
+ await i(t, r);
791
898
  } catch (a) {
792
- const c = t.constructor.name || "UnnamedConstructor", h = {
899
+ const o = t.constructor.name || "UnnamedConstructor", l = {
793
900
  blocName: this._name,
794
901
  blocId: String(this._id),
795
- eventType: c,
902
+ eventType: o,
796
903
  currentState: this.state,
797
904
  action: t,
798
905
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
799
906
  };
800
- if (l.error(
801
- `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${c}':`,
907
+ if (f.error(
908
+ `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${o}':`,
802
909
  a,
803
910
  "Context:",
804
- h
911
+ l
805
912
  ), a instanceof Error && a.name === "CriticalError")
806
913
  throw a;
807
914
  }
808
915
  } else {
809
- const o = t.constructor.name || "UnnamedConstructor";
810
- l.warn(
811
- `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${o}'.`,
916
+ const r = t.constructor.name || "UnnamedConstructor";
917
+ f.warn(
918
+ `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${r}'.`,
812
919
  "Registered handlers:",
813
920
  Array.from(this.eventHandlers.keys()).map((a) => a.name),
814
921
  "Action was:",
@@ -817,7 +924,7 @@ class S extends v {
817
924
  }
818
925
  }
819
926
  }
820
- class k extends v {
927
+ class V extends k {
821
928
  /**
822
929
  * Updates the current state and notifies all observers of the change.
823
930
  * If the new state is identical to the current state (using Object.is),
@@ -833,14 +940,14 @@ class k extends v {
833
940
  /**
834
941
  * Partially updates the current state by merging it with the provided state patch.
835
942
  * This method is only applicable when the state is an object type.
836
- *
943
+ *
837
944
  * @param statePatch - A partial state object containing only the properties to update
838
945
  * @param ignoreChangeCheck - If true, skips checking if the state has actually changed
839
946
  * @throws {TypeError} If the state is not an object type
840
947
  */
841
948
  patch(e, t = !1) {
842
949
  if (typeof this.state != "object" || this.state === null) {
843
- l.warn(
950
+ f.warn(
844
951
  "Cubit.patch: was called on a cubit where the state is not an object. This is a no-op."
845
952
  );
846
953
  return;
@@ -849,10 +956,10 @@ class k extends v {
849
956
  if (t)
850
957
  s = !0;
851
958
  else
852
- for (const n in e)
853
- if (Object.prototype.hasOwnProperty.call(e, n)) {
854
- const a = this.state[n];
855
- if (!Object.is(e[n], a)) {
959
+ for (const i in e)
960
+ if (Object.prototype.hasOwnProperty.call(e, i)) {
961
+ const a = this.state[i];
962
+ if (!Object.is(e[i], a)) {
856
963
  s = !0;
857
964
  break;
858
965
  }
@@ -863,78 +970,86 @@ class k extends v {
863
970
  });
864
971
  }
865
972
  }
866
- class $ {
973
+ class U {
867
974
  /**
868
975
  * Sets up a clean test environment
869
976
  */
870
977
  static setUp() {
871
- this.originalInstance = l.instance, l.resetInstance(), l.enableLog = !1;
978
+ this.originalInstance = f.instance, f.resetInstance(), f.enableLog = !1;
872
979
  }
873
980
  /**
874
981
  * Tears down the test environment and restores original state
875
982
  */
876
983
  static tearDown() {
877
- l.resetInstance();
984
+ f.resetInstance();
878
985
  }
879
986
  /**
880
987
  * Creates a test bloc with automatic cleanup
881
988
  */
882
989
  static createBloc(e, ...t) {
883
990
  const s = new e(...t);
884
- return l.activateBloc(s), s;
991
+ return f.activateBloc(s), s;
885
992
  }
886
993
  /**
887
994
  * Waits for a bloc to emit a specific state
888
995
  */
889
996
  static async waitForState(e, t, s = 5e3) {
890
- return new Promise((n, o) => {
997
+ return new Promise((i, r) => {
891
998
  const a = setTimeout(() => {
892
- o(new Error(`Timeout waiting for state matching predicate after ${s}ms`));
893
- }, s), c = e._observer.subscribe({
894
- id: `test-waiter-${crypto.randomUUID()}`,
895
- fn: (h) => {
896
- t(h) && (clearTimeout(a), c(), n(h));
999
+ r(
1000
+ new Error(
1001
+ `Timeout waiting for state matching predicate after ${s}ms`
1002
+ )
1003
+ );
1004
+ }, s), o = e._observer.subscribe({
1005
+ id: `test-waiter-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
1006
+ fn: (l) => {
1007
+ t(l) && (clearTimeout(a), o(), i(l));
897
1008
  }
898
1009
  });
899
- t(e.state) && (clearTimeout(a), c(), n(e.state));
1010
+ t(e.state) && (clearTimeout(a), o(), i(e.state));
900
1011
  });
901
1012
  }
902
1013
  /**
903
1014
  * Expects a bloc to emit specific states in order
904
1015
  */
905
1016
  static async expectStates(e, t, s = 5e3) {
906
- const n = [];
907
- return new Promise((o, a) => {
908
- const c = setTimeout(() => {
909
- a(new Error(
910
- `Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(n)}`
911
- ));
912
- }, s), h = e._observer.subscribe({
1017
+ const i = [];
1018
+ return new Promise((r, a) => {
1019
+ const o = setTimeout(() => {
1020
+ a(
1021
+ new Error(
1022
+ `Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(i)}`
1023
+ )
1024
+ );
1025
+ }, s), l = e._observer.subscribe({
913
1026
  id: `test-expecter-${crypto.randomUUID()}`,
914
- fn: (_) => {
915
- if (n.push(_), n.length === t.length) {
916
- clearTimeout(c), h();
917
- for (let p = 0; p < t.length; p++) {
918
- const f = t[p], m = n[p];
919
- if (JSON.stringify(f) !== JSON.stringify(m)) {
920
- a(new Error(
921
- `State mismatch at index ${p}. Expected: ${JSON.stringify(f)}, Received: ${JSON.stringify(m)}`
922
- ));
1027
+ fn: (p) => {
1028
+ if (i.push(p), i.length === t.length) {
1029
+ clearTimeout(o), l();
1030
+ for (let d = 0; d < t.length; d++) {
1031
+ const m = t[d], v = i[d];
1032
+ if (JSON.stringify(m) !== JSON.stringify(v)) {
1033
+ a(
1034
+ new Error(
1035
+ `State mismatch at index ${d}. Expected: ${JSON.stringify(m)}, Received: ${JSON.stringify(v)}`
1036
+ )
1037
+ );
923
1038
  return;
924
1039
  }
925
1040
  }
926
- o();
1041
+ r();
927
1042
  }
928
1043
  }
929
1044
  });
930
1045
  });
931
1046
  }
932
1047
  }
933
- i($, "originalInstance");
934
- class M extends S {
1048
+ n(U, "originalInstance");
1049
+ class z extends O {
935
1050
  constructor(t) {
936
1051
  super(t);
937
- i(this, "mockHandlers", /* @__PURE__ */ new Map());
1052
+ n(this, "mockHandlers", /* @__PURE__ */ new Map());
938
1053
  }
939
1054
  /**
940
1055
  * Mock an event handler for testing
@@ -955,10 +1070,10 @@ class M extends S {
955
1070
  return this.eventHandlers.has(t);
956
1071
  }
957
1072
  }
958
- class E extends k {
1073
+ class j extends V {
959
1074
  constructor(t) {
960
1075
  super(t);
961
- i(this, "stateHistory", []);
1076
+ n(this, "stateHistory", []);
962
1077
  this.stateHistory.push(t);
963
1078
  }
964
1079
  /**
@@ -980,16 +1095,16 @@ class E extends k {
980
1095
  this.stateHistory = [this.state];
981
1096
  }
982
1097
  }
983
- class R {
1098
+ class K {
984
1099
  constructor() {
985
- i(this, "initialStats");
986
- this.initialStats = l.getMemoryStats();
1100
+ n(this, "initialStats");
1101
+ this.initialStats = f.getMemoryStats();
987
1102
  }
988
1103
  /**
989
1104
  * Check for memory leaks and return a report
990
1105
  */
991
1106
  checkForLeaks() {
992
- const e = l.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
1107
+ const e = f.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
993
1108
  Memory Leak Detection Report:
994
1109
  - Initial registered blocs: ${this.initialStats.registeredBlocs}
995
1110
  - Current registered blocs: ${e.registeredBlocs}
@@ -1006,17 +1121,400 @@ Memory Leak Detection Report:
1006
1121
  };
1007
1122
  }
1008
1123
  }
1124
+ class H {
1125
+ constructor() {
1126
+ n(this, "consumers", /* @__PURE__ */ new WeakMap());
1127
+ n(this, "registrationCount", 0);
1128
+ n(this, "activeConsumers", 0);
1129
+ }
1130
+ register(e, t) {
1131
+ this.registrationCount++, this.consumers.get(e) || this.activeConsumers++, this.consumers.set(e, {
1132
+ id: t,
1133
+ lastNotified: Date.now(),
1134
+ hasRendered: !1,
1135
+ stateAccesses: /* @__PURE__ */ new Set(),
1136
+ classAccesses: /* @__PURE__ */ new Set(),
1137
+ stateValues: /* @__PURE__ */ new Map(),
1138
+ classValues: /* @__PURE__ */ new Map(),
1139
+ accessCount: 0,
1140
+ lastAccessTime: 0,
1141
+ firstAccessTime: 0
1142
+ });
1143
+ }
1144
+ unregister(e) {
1145
+ e && this.consumers.get(e) && (this.consumers.delete(e), this.activeConsumers = Math.max(0, this.activeConsumers - 1));
1146
+ }
1147
+ trackAccess(e, t, s, i) {
1148
+ const r = this.consumers.get(e);
1149
+ if (!r) return;
1150
+ const a = Date.now();
1151
+ r.firstAccessTime || (r.firstAccessTime = a), r.accessCount++, r.lastAccessTime = a, t === "state" ? (r.stateAccesses.add(s), i !== void 0 && r.stateValues.set(s, { value: i, lastAccessTime: a })) : (r.classAccesses.add(s), i !== void 0 && r.classValues.set(s, { value: i, lastAccessTime: a }));
1152
+ }
1153
+ resetTracking(e) {
1154
+ const t = this.consumers.get(e);
1155
+ t && (t.stateAccesses.clear(), t.classAccesses.clear(), t.stateValues.clear(), t.classValues.clear(), t.accessCount = 0, t.firstAccessTime = 0);
1156
+ }
1157
+ getDependencies(e) {
1158
+ const t = this.consumers.get(e);
1159
+ return t ? {
1160
+ statePaths: Array.from(t.stateAccesses),
1161
+ classPaths: Array.from(t.classAccesses)
1162
+ } : null;
1163
+ }
1164
+ hasValuesChanged(e, t, s) {
1165
+ const i = this.consumers.get(e);
1166
+ if (!i) return !0;
1167
+ let r = !1;
1168
+ const a = Date.now();
1169
+ if (i.stateValues.size === 0 && i.classValues.size === 0 && (i.stateAccesses.size > 0 || i.classAccesses.size > 0))
1170
+ return !0;
1171
+ for (const [o, l] of i.stateValues)
1172
+ try {
1173
+ const p = this.getValueAtPath(t, o);
1174
+ p !== l.value && (i.stateValues.set(o, {
1175
+ value: p,
1176
+ lastAccessTime: a
1177
+ }), r = !0);
1178
+ } catch {
1179
+ r = !0;
1180
+ }
1181
+ for (const [o, l] of i.classValues)
1182
+ try {
1183
+ const p = this.getValueAtPath(s, o);
1184
+ p !== l.value && (i.classValues.set(o, {
1185
+ value: p,
1186
+ lastAccessTime: a
1187
+ }), r = !0);
1188
+ } catch {
1189
+ r = !0;
1190
+ }
1191
+ return r;
1192
+ }
1193
+ shouldNotifyConsumer(e, t) {
1194
+ const s = this.consumers.get(e);
1195
+ if (!s) return !1;
1196
+ for (const i of t) {
1197
+ if (s.stateAccesses.has(i) || s.classAccesses.has(i)) return !0;
1198
+ for (const r of s.stateAccesses)
1199
+ if (i.startsWith(r + ".") || r.startsWith(i + "."))
1200
+ return !0;
1201
+ }
1202
+ return !1;
1203
+ }
1204
+ updateLastNotified(e) {
1205
+ const t = this.consumers.get(e);
1206
+ t && (t.lastNotified = Date.now());
1207
+ }
1208
+ getConsumerInfo(e) {
1209
+ return this.consumers.get(e);
1210
+ }
1211
+ setHasRendered(e, t) {
1212
+ const s = this.consumers.get(e);
1213
+ s && (s.hasRendered = t);
1214
+ }
1215
+ hasConsumer(e) {
1216
+ return this.consumers.has(e);
1217
+ }
1218
+ getStats() {
1219
+ return {
1220
+ totalRegistrations: this.registrationCount,
1221
+ activeConsumers: this.activeConsumers
1222
+ };
1223
+ }
1224
+ getValueAtPath(e, t) {
1225
+ const s = t.split(".");
1226
+ let i = e;
1227
+ for (const r of s) {
1228
+ if (i == null) return;
1229
+ i = i[r];
1230
+ }
1231
+ return i;
1232
+ }
1233
+ }
1234
+ const w = /* @__PURE__ */ new WeakMap();
1235
+ let h = {
1236
+ stateProxiesCreated: 0,
1237
+ classProxiesCreated: 0,
1238
+ cacheHits: 0,
1239
+ cacheMisses: 0,
1240
+ propertyAccesses: 0,
1241
+ nestedProxiesCreated: 0,
1242
+ totalProxiesCreated: 0,
1243
+ createdAt: Date.now()
1244
+ };
1245
+ class y {
1246
+ static createStateProxy(e) {
1247
+ const { target: t, consumerRef: s, consumerTracker: i, path: r = "" } = e;
1248
+ if (!s || !i || typeof t != "object" || t === null)
1249
+ return t;
1250
+ let a = w.get(t);
1251
+ a || (a = /* @__PURE__ */ new WeakMap(), w.set(t, a));
1252
+ const o = a.get(s);
1253
+ if (o)
1254
+ return h.cacheHits++, o;
1255
+ h.cacheMisses++;
1256
+ const l = {
1257
+ get(d, m) {
1258
+ if (typeof m == "symbol" || m === "constructor")
1259
+ return Reflect.get(d, m);
1260
+ const v = r ? `${r}.${m}` : m;
1261
+ h.propertyAccesses++;
1262
+ const g = Reflect.get(d, m), S = g && typeof g === "object" && g !== null ? void 0 : g;
1263
+ if (i.trackAccess(s, "state", v, S), g && typeof g == "object" && g !== null) {
1264
+ const B = Object.getPrototypeOf(g) === Object.prototype, D = Array.isArray(g);
1265
+ if (B || D)
1266
+ return h.nestedProxiesCreated++, y.createStateProxy({
1267
+ target: g,
1268
+ consumerRef: s,
1269
+ consumerTracker: i,
1270
+ path: v
1271
+ });
1272
+ }
1273
+ return g;
1274
+ },
1275
+ has(d, m) {
1276
+ return m in d;
1277
+ },
1278
+ ownKeys(d) {
1279
+ return Reflect.ownKeys(d);
1280
+ },
1281
+ getOwnPropertyDescriptor(d, m) {
1282
+ return Reflect.getOwnPropertyDescriptor(d, m);
1283
+ },
1284
+ set() {
1285
+ return !1;
1286
+ },
1287
+ deleteProperty() {
1288
+ return !1;
1289
+ }
1290
+ }, p = new Proxy(t, l);
1291
+ return a.set(s, p), h.stateProxiesCreated++, h.totalProxiesCreated++, p;
1292
+ }
1293
+ static createClassProxy(e) {
1294
+ const { target: t, consumerRef: s, consumerTracker: i } = e;
1295
+ if (!s || !i)
1296
+ return t;
1297
+ let r = w.get(t);
1298
+ r || (r = /* @__PURE__ */ new WeakMap(), w.set(t, r));
1299
+ const a = r.get(s);
1300
+ if (a)
1301
+ return h.cacheHits++, a;
1302
+ h.cacheMisses++;
1303
+ const o = {
1304
+ get(p, d) {
1305
+ const m = Reflect.get(p, d);
1306
+ let v = !1, g = p;
1307
+ const A = /* @__PURE__ */ new WeakSet(), C = 10;
1308
+ let S = 0;
1309
+ for (; g && !v && S < C && !A.has(g); ) {
1310
+ A.add(g);
1311
+ try {
1312
+ const x = Object.getOwnPropertyDescriptor(
1313
+ g,
1314
+ d
1315
+ );
1316
+ if (x && x.get) {
1317
+ v = !0;
1318
+ break;
1319
+ }
1320
+ g = Object.getPrototypeOf(g), S++;
1321
+ } catch {
1322
+ break;
1323
+ }
1324
+ }
1325
+ if (!v)
1326
+ return m;
1327
+ h.propertyAccesses++;
1328
+ const B = m, $ = B !== null && typeof B != "object" ? B : void 0;
1329
+ return i.trackAccess(
1330
+ s,
1331
+ "class",
1332
+ String(d),
1333
+ $
1334
+ ), m;
1335
+ },
1336
+ has(p, d) {
1337
+ return d in p;
1338
+ },
1339
+ ownKeys(p) {
1340
+ return Reflect.ownKeys(p);
1341
+ },
1342
+ getOwnPropertyDescriptor(p, d) {
1343
+ return Reflect.getOwnPropertyDescriptor(p, d);
1344
+ }
1345
+ }, l = new Proxy(t, o);
1346
+ return r.set(s, l), h.classProxiesCreated++, h.totalProxiesCreated++, l;
1347
+ }
1348
+ static getProxyState(e) {
1349
+ return y.createStateProxy({
1350
+ target: e.state,
1351
+ consumerRef: e.consumerRef,
1352
+ consumerTracker: e.consumerTracker
1353
+ });
1354
+ }
1355
+ static getProxyBlocInstance(e) {
1356
+ return y.createClassProxy({
1357
+ target: e.blocInstance,
1358
+ consumerRef: e.consumerRef,
1359
+ consumerTracker: e.consumerTracker
1360
+ });
1361
+ }
1362
+ static getStats() {
1363
+ const e = Date.now() - h.createdAt;
1364
+ return {
1365
+ ...h,
1366
+ totalProxies: h.stateProxiesCreated + h.classProxiesCreated,
1367
+ cacheEfficiency: h.cacheHits + h.cacheMisses > 0 ? `${(h.cacheHits / (h.cacheHits + h.cacheMisses) * 100).toFixed(1)}%` : "N/A",
1368
+ lifetime: `${e}ms`,
1369
+ proxiesPerSecond: e > 0 ? (h.totalProxiesCreated / (e / 1e3)).toFixed(2) : "N/A"
1370
+ };
1371
+ }
1372
+ static resetStats() {
1373
+ h = {
1374
+ stateProxiesCreated: 0,
1375
+ classProxiesCreated: 0,
1376
+ cacheHits: 0,
1377
+ cacheMisses: 0,
1378
+ propertyAccesses: 0,
1379
+ nestedProxiesCreated: 0,
1380
+ totalProxiesCreated: 0,
1381
+ createdAt: Date.now()
1382
+ };
1383
+ }
1384
+ }
1385
+ class q {
1386
+ constructor(e, t) {
1387
+ n(this, "id", `consumer-${R()}`);
1388
+ n(this, "blocConstructor");
1389
+ n(this, "componentRef", { current: {} });
1390
+ n(this, "blocInstance");
1391
+ // Core components
1392
+ n(this, "consumerTracker");
1393
+ n(this, "unmountTime", 0);
1394
+ n(this, "mountTime", 0);
1395
+ // Dependency tracking
1396
+ n(this, "dependencyValues");
1397
+ n(this, "isUsingDependencies", !1);
1398
+ // Lifecycle state
1399
+ n(this, "hasMounted", !1);
1400
+ n(this, "mountCount", 0);
1401
+ n(this, "options");
1402
+ n(this, "createStateProxy", (e) => y.createStateProxy({
1403
+ target: e.target,
1404
+ consumerRef: this.componentRef.current,
1405
+ consumerTracker: this
1406
+ }));
1407
+ n(this, "createClassProxy", (e) => y.createClassProxy({
1408
+ target: e.target,
1409
+ consumerRef: this.componentRef.current,
1410
+ consumerTracker: this
1411
+ }));
1412
+ n(this, "createSubscription", (e) => this.blocInstance._observer.subscribe({
1413
+ id: this.id,
1414
+ fn: (s, i) => {
1415
+ var r;
1416
+ if (this.isUsingDependencies && ((r = this.options) != null && r.dependencies)) {
1417
+ const a = this.options.dependencies(this.blocInstance);
1418
+ if (!this.hasDependencyValuesChanged(
1419
+ this.dependencyValues,
1420
+ a
1421
+ ))
1422
+ return;
1423
+ this.dependencyValues = a;
1424
+ } else {
1425
+ const a = this.consumerTracker.getConsumerInfo(
1426
+ this.componentRef.current
1427
+ );
1428
+ if (a && a.hasRendered && !this.consumerTracker.hasValuesChanged(
1429
+ this.componentRef.current,
1430
+ s,
1431
+ this.blocInstance
1432
+ ))
1433
+ return;
1434
+ }
1435
+ e.onChange();
1436
+ }
1437
+ }));
1438
+ n(this, "mount", () => {
1439
+ var e, t;
1440
+ if (this.isUsingDependencies && ((e = this.options) != null && e.dependencies) && (this.dependencyValues = this.options.dependencies(this.blocInstance)), this.mountCount++, this.blocInstance._addConsumer(this.id, this.componentRef.current), !this.hasMounted && (this.hasMounted = !0, this.mountTime = Date.now(), (t = this.options) != null && t.onMount))
1441
+ try {
1442
+ this.options.onMount(this.blocInstance);
1443
+ } catch (s) {
1444
+ throw s;
1445
+ }
1446
+ });
1447
+ n(this, "unmount", () => {
1448
+ var e;
1449
+ if (this.unmountTime = Date.now(), this.consumerTracker.unregister(this.componentRef.current), this.blocInstance._removeConsumer(this.id), (e = this.options) != null && e.onUnmount)
1450
+ try {
1451
+ this.options.onUnmount(this.blocInstance);
1452
+ } catch {
1453
+ }
1454
+ });
1455
+ n(this, "getProxyState", (e) => this.isUsingDependencies ? e : y.getProxyState({
1456
+ state: e,
1457
+ consumerRef: this.componentRef.current,
1458
+ consumerTracker: this
1459
+ }));
1460
+ n(this, "getProxyBlocInstance", () => this.isUsingDependencies ? this.blocInstance : y.getProxyBlocInstance({
1461
+ blocInstance: this.blocInstance,
1462
+ consumerRef: this.componentRef.current,
1463
+ consumerTracker: this
1464
+ }));
1465
+ this.options = t, this.blocConstructor = e.blocConstructor, this.componentRef = e.componentRef, this.isUsingDependencies = !!(t != null && t.dependencies), this.consumerTracker = new H(), this.blocInstance = this.updateBlocInstance(), this.consumerTracker.register(e.componentRef.current, this.id), this.isUsingDependencies && (t != null && t.dependencies) && (this.dependencyValues = t.dependencies(this.blocInstance));
1466
+ }
1467
+ trackAccess(e, t, s, i) {
1468
+ this.consumerTracker.trackAccess(e, t, s, i);
1469
+ }
1470
+ getConsumerDependencies(e) {
1471
+ return this.consumerTracker.getDependencies(e);
1472
+ }
1473
+ shouldNotifyConsumer(e, t) {
1474
+ const s = this.consumerTracker.getConsumerInfo(e);
1475
+ return !s || !s.hasRendered ? !0 : this.consumerTracker.shouldNotifyConsumer(e, t);
1476
+ }
1477
+ updateLastNotified(e) {
1478
+ this.consumerTracker.updateLastNotified(e), this.consumerTracker.setHasRendered(e, !0);
1479
+ }
1480
+ resetConsumerTracking() {
1481
+ this.consumerTracker.resetTracking(this.componentRef.current);
1482
+ }
1483
+ updateBlocInstance() {
1484
+ var e, t;
1485
+ return this.blocInstance = f.instance.getBloc(this.blocConstructor, {
1486
+ props: (e = this.options) == null ? void 0 : e.props,
1487
+ id: (t = this.options) == null ? void 0 : t.id,
1488
+ instanceRef: this.id
1489
+ }), this.blocInstance;
1490
+ }
1491
+ // Expose calledOnMount for backward compatibility
1492
+ get calledOnMount() {
1493
+ return this.hasMounted;
1494
+ }
1495
+ hasDependencyValuesChanged(e, t) {
1496
+ if (!e || e.length !== t.length) return !0;
1497
+ for (let s = 0; s < e.length; s++)
1498
+ if (!Object.is(e[s], t[s]))
1499
+ return !0;
1500
+ return !1;
1501
+ }
1502
+ }
1009
1503
  export {
1010
- l as Blac,
1011
- w as BlacObservable,
1012
- S as Bloc,
1013
- v as BlocBase,
1014
- $ as BlocTest,
1015
- k as Cubit,
1016
- R as MemoryLeakDetector,
1017
- M as MockBloc,
1018
- E as MockCubit,
1019
- b as generateUUID,
1020
- A as setBlacInstanceManager
1504
+ f as Blac,
1505
+ q as BlacAdapter,
1506
+ E as BlacObservable,
1507
+ O as Bloc,
1508
+ k as BlocBase,
1509
+ _ as BlocLifecycleState,
1510
+ U as BlocTest,
1511
+ H as ConsumerTracker,
1512
+ V as Cubit,
1513
+ K as MemoryLeakDetector,
1514
+ z as MockBloc,
1515
+ j as MockCubit,
1516
+ y as ProxyFactory,
1517
+ R as generateUUID,
1518
+ L as setBlacInstanceManager
1021
1519
  };
1022
1520
  //# sourceMappingURL=index.es.js.map