@blac/core 2.0.0-rc-7 → 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,360 +1,15 @@
1
- var m = Object.defineProperty;
2
- var y = (d, e, t) => e in d ? m(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({ __unsafe_ignore_singleton: !0 })), u._instance;
7
- }
8
- setInstance(e) {
9
- u._instance = e;
10
- }
11
- resetInstance() {
12
- const e = u._instance;
13
- if (u._instance = new l({ __unsafe_ignore_singleton: !0 }), e)
14
- for (const t of e.keepAliveBlocs)
15
- u._instance.keepAliveBlocs.add(t), u._instance.uidRegistry.set(t.uid, t);
16
- }
17
- };
18
- i(u, "_instance");
19
- let v = u, g = new v();
20
- function M(d) {
21
- g = d;
22
- }
23
- const c = class c {
24
- /**
25
- * Creates a new Blac instance.
26
- * @param options - Configuration options including singleton control
27
- */
28
- constructor(e = {}) {
29
- /** Timestamp when the instance was created */
30
- i(this, "createdAt", Date.now());
31
- /** Map storing all registered bloc instances by their class name and ID */
32
- i(this, "blocInstanceMap", /* @__PURE__ */ new Map());
33
- /** Map storing isolated bloc instances grouped by their constructor */
34
- i(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
35
- /** Map for O(1) lookup of isolated blocs by UID */
36
- i(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
37
- /** Map tracking UIDs to prevent memory leaks */
38
- i(this, "uidRegistry", /* @__PURE__ */ new Map());
39
- /** Set of keep-alive blocs for controlled cleanup */
40
- i(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
41
- /** Flag to control whether changes should be posted to document */
42
- i(this, "postChangesToDocument", !1);
43
- /**
44
- * Logs messages to console when logging is enabled
45
- * @param args - Arguments to log
46
- */
47
- i(this, "log", (...e) => {
48
- c.enableLog && console.warn(`☢️ [Blac ${this.createdAt.toString()}]`, ...e);
49
- });
50
- /**
51
- * Logs a warning message
52
- * @param message - Warning message
53
- * @param args - Additional arguments
54
- */
55
- i(this, "warn", (e, ...t) => {
56
- c.enableLog && console.warn(`🚨 [Blac ${String(c.instance.createdAt)}]`, e, ...t);
57
- });
58
- /**
59
- * Logs an error message
60
- * @param message - Error message
61
- * @param args - Additional arguments
62
- */
63
- i(this, "error", (e, ...t) => {
64
- c.enableLog && console.error(`🚨 [Blac ${String(c.instance.createdAt)}]`, e, ...t);
65
- });
66
- /**
67
- * Resets the Blac instance to a new one, disposing non-keepAlive blocs
68
- * from the old instance.
69
- */
70
- i(this, "resetInstance", () => {
71
- this.log("Reset Blac instance");
72
- const e = new Map(this.blocInstanceMap), t = new Map(this.isolatedBlocMap);
73
- e.forEach((s) => {
74
- !s._keepAlive && s._disposalState === "active" && this.disposeBloc(s);
75
- }), t.forEach((s) => {
76
- s.forEach((n) => {
77
- !n._keepAlive && n._disposalState === "active" && this.disposeBloc(n);
78
- });
79
- }), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), g.resetInstance();
80
- });
81
- /**
82
- * Disposes of a bloc instance by removing it from the appropriate registry
83
- * @param bloc - The bloc instance to dispose
84
- */
85
- i(this, "disposeBloc", (e) => {
86
- if (e._disposalState !== "active") {
87
- this.log(`[${e._name}:${String(e._id)}] disposeBloc called on already disposed bloc`);
88
- return;
89
- }
90
- const t = e.constructor, s = this.createBlocInstanceMapKey(e._name, e._id);
91
- this.log(`[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(t.isolated)}`), e._dispose(), t.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(s)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
92
- });
93
- i(this, "activateBloc", (e) => {
94
- const t = e.constructor;
95
- (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));
96
- });
97
- /**
98
- * Gets or creates a bloc instance based on the provided class and options.
99
- * If a bloc with the given ID exists, it will be returned. Otherwise, a new instance will be created.
100
- *
101
- * @param blocClass - The bloc class to get or create
102
- * @param options - Options including:
103
- * - id: The instance ID (defaults to class name if not provided)
104
- * - props: Properties to pass to the bloc constructor
105
- * - instanceRef: Optional reference string for the instance
106
- * @returns The bloc instance
107
- */
108
- i(this, "getBloc", (e, t = {}) => {
109
- const { id: s } = t, n = e, o = s ?? e.name;
110
- if (n.isolated) {
111
- const r = this.findIsolatedBlocInstance(e, o);
112
- if (r)
113
- return this.log(`[${e.name}:${String(o)}] (getBloc) Found existing isolated instance.`, t), r;
114
- if (t.throwIfNotFound)
115
- throw new Error(`Isolated bloc ${e.name} not found`);
116
- } else {
117
- const r = this.findRegisteredBlocInstance(e, o);
118
- if (r)
119
- return this.log(`[${e.name}:${String(o)}] (getBloc) Found existing registered instance.`, t), r;
120
- if (t.throwIfNotFound)
121
- throw new Error(`Registered bloc ${e.name} not found`);
122
- }
123
- const a = this.createNewBlocInstance(
124
- e,
125
- o,
126
- t
127
- );
128
- if (this.log(`[${e.name}:${String(o)}] (getBloc) No existing instance found. Creating new one.`, t, a), !a)
129
- throw new Error(`[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`);
130
- return a;
131
- });
132
- /**
133
- * Gets a bloc instance or throws an error if it doesn't exist
134
- * @param blocClass - The bloc class to get
135
- * @param options - Options including:
136
- * - id: The instance ID (defaults to class name if not provided)
137
- * - props: Properties to pass to the bloc constructor
138
- * - instanceRef: Optional reference string for the instance
139
- */
140
- i(this, "getBlocOrThrow", (e, t = {}) => {
141
- const s = e.isolated, n = t.id || e.name, o = s ? this.findIsolatedBlocInstance(e, n) : this.findRegisteredBlocInstance(e, n);
142
- if (o)
143
- return o;
144
- throw new Error(`Bloc ${e.name} not found`);
145
- });
146
- /**
147
- * Gets all instances of a specific bloc class
148
- * @param blocClass - The bloc class to search for
149
- * @param options - Options including:
150
- * - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)
151
- * @returns Array of matching bloc instances
152
- */
153
- i(this, "getAllBlocs", (e, t = {}) => {
154
- const s = [];
155
- if (this.blocInstanceMap.forEach((n) => {
156
- n.constructor === e && s.push(n);
157
- }), t.searchIsolated !== !1) {
158
- const n = this.isolatedBlocMap.get(e);
159
- n && s.push(...n.map((o) => o));
160
- }
161
- return s;
162
- });
163
- /**
164
- * Disposes all keep-alive blocs of a specific type
165
- * @param blocClass - The bloc class to dispose
166
- */
167
- i(this, "disposeKeepAliveBlocs", (e) => {
168
- const t = [];
169
- for (const s of this.keepAliveBlocs)
170
- (!e || s.constructor === e) && t.push(s);
171
- t.forEach((s) => s._dispose());
172
- });
173
- /**
174
- * Disposes all blocs matching a pattern
175
- * @param predicate - Function to test each bloc for disposal
176
- */
177
- i(this, "disposeBlocs", (e) => {
178
- const t = [];
179
- for (const s of this.blocInstanceMap.values())
180
- e(s) && t.push(s);
181
- for (const s of this.isolatedBlocMap.values())
182
- for (const n of s)
183
- e(n) && t.push(n);
184
- t.forEach((s) => s._dispose());
185
- });
186
- /**
187
- * Gets memory usage statistics for debugging
188
- */
189
- i(this, "getMemoryStats", () => ({
190
- totalBlocs: this.uidRegistry.size,
191
- registeredBlocs: this.blocInstanceMap.size,
192
- isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce((e, t) => e + t.length, 0),
193
- keepAliveBlocs: this.keepAliveBlocs.size,
194
- isolatedBlocTypes: this.isolatedBlocMap.size
195
- }));
196
- /**
197
- * Validates consumer references and cleans up orphaned consumers
198
- */
199
- i(this, "validateConsumers", () => {
200
- for (const e of this.uidRegistry.values())
201
- e._validateConsumers(), e._consumers.size === 0 && !e._keepAlive && e._disposalState === "active" && setTimeout(() => {
202
- e._consumers.size === 0 && !e._keepAlive && e._disposalState === "active" && this.disposeBloc(e);
203
- }, 1e3);
204
- });
205
- const { __unsafe_ignore_singleton: t = !1 } = e;
206
- if (!t)
207
- return c.instance;
208
- g.setInstance(this);
209
- }
210
- /** @deprecated Use getInstance() instead */
211
- static get instance() {
212
- return g.getInstance();
213
- }
214
- static get getAllBlocs() {
215
- return c.instance.getAllBlocs;
216
- }
217
- static get log() {
218
- return c.instance.log;
219
- }
220
- /**
221
- * Gets the current Blac instance
222
- * @returns The Blac instance
223
- */
224
- static getInstance() {
225
- return g.getInstance();
226
- }
227
- static get warn() {
228
- return c.instance.warn;
229
- }
230
- static get error() {
231
- return c.instance.error;
232
- }
233
- static get disposeBloc() {
234
- return c.instance.disposeBloc;
235
- }
236
- /**
237
- * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
238
- * @param blocClassName - The name of the bloc class
239
- * @param id - The instance ID
240
- * @returns A unique key string in the format "className:id"
241
- */
242
- createBlocInstanceMapKey(e, t) {
243
- return `${e}:${String(t)}`;
244
- }
245
- /**
246
- * Unregister a bloc instance from the main registry
247
- * @param bloc - The bloc instance to unregister
248
- */
249
- unregisterBlocInstance(e) {
250
- const t = this.createBlocInstanceMapKey(e._name, e._id);
251
- this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
252
- }
253
- /**
254
- * Registers a bloc instance in the main registry
255
- * @param bloc - The bloc instance to register
256
- */
257
- registerBlocInstance(e) {
258
- const t = this.createBlocInstanceMapKey(e._name, e._id);
259
- this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
260
- }
261
- /**
262
- * Finds a registered bloc instance by its class and ID
263
- * @param blocClass - The bloc class to search for
264
- * @param id - The instance ID
265
- * @returns The found bloc instance or undefined if not found
266
- */
267
- findRegisteredBlocInstance(e, t) {
268
- if (e.isolated) return;
269
- const n = this.createBlocInstanceMapKey(e.name, t);
270
- return this.blocInstanceMap.get(n);
271
- }
272
- /**
273
- * Registers an isolated bloc instance in the isolated registry
274
- * @param bloc - The isolated bloc instance to register
275
- */
276
- registerIsolatedBlocInstance(e) {
277
- const t = e.constructor, s = this.isolatedBlocMap.get(t);
278
- 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);
279
- }
280
- /**
281
- * Unregister an isolated bloc instance from the isolated registry
282
- * @param bloc - The isolated bloc instance to unregister
283
- */
284
- unregisterIsolatedBlocInstance(e) {
285
- const t = e.constructor, s = this.isolatedBlocMap.get(t);
286
- let n = !1;
287
- if (s) {
288
- const a = s.findIndex((r) => r.uid === e.uid);
289
- a !== -1 && (s.splice(a, 1), n = !0), s.length === 0 && this.isolatedBlocMap.delete(t);
290
- }
291
- const o = this.isolatedBlocIndex.delete(e.uid);
292
- this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), n !== o && this.warn(
293
- `[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${n}, Index removal: ${o}`
294
- );
295
- }
296
- /**
297
- * Finds an isolated bloc instance by its class and ID (O(n) lookup)
298
- */
299
- findIsolatedBlocInstance(e, t) {
300
- if (!e.isolated) return;
301
- const n = this.isolatedBlocMap.get(e);
302
- return n ? n.find((a) => a._id === t) : void 0;
303
- }
304
- /**
305
- * Finds an isolated bloc instance by UID (O(1) lookup)
306
- */
307
- findIsolatedBlocInstanceByUid(e) {
308
- return this.isolatedBlocIndex.get(e);
309
- }
310
- /**
311
- * Creates a new bloc instance and registers it in the appropriate registry
312
- * @param blocClass - The bloc class to instantiate
313
- * @param id - The instance ID
314
- * @param props - Properties to pass to the bloc constructor
315
- * @param instanceRef - Optional reference string for the instance
316
- * @returns The newly created bloc instance
317
- */
318
- createNewBlocInstance(e, t, s = {}) {
319
- const { props: n, instanceRef: o } = s, a = new e(n);
320
- return a._instanceRef = o, a.props = n || null, a._updateId(t), a._setDisposalHandler((r) => this.disposeBloc(r)), a.isIsolated ? (this.registerIsolatedBlocInstance(a), a) : (this.registerBlocInstance(a), a);
321
- }
322
- static get activateBloc() {
323
- return c.instance.activateBloc;
324
- }
325
- static get getBloc() {
326
- return c.instance.getBloc;
327
- }
328
- static get getBlocOrThrow() {
329
- return c.instance.getBlocOrThrow;
330
- }
331
- static get disposeKeepAliveBlocs() {
332
- return c.instance.disposeKeepAliveBlocs;
333
- }
334
- static get disposeBlocs() {
335
- return c.instance.disposeBlocs;
336
- }
337
- static get getMemoryStats() {
338
- return c.instance.getMemoryStats;
339
- }
340
- static get validateConsumers() {
341
- return c.instance.validateConsumers;
342
- }
343
- };
344
- /** Flag to enable/disable logging */
345
- i(c, "enableLog", !1), i(c, "resetInstance", () => {
346
- g.resetInstance();
347
- });
348
- let l = c;
349
- 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 {
350
5
  /**
351
6
  * Creates a new BlacObservable instance
352
7
  * @param bloc - The Bloc instance to observe
353
8
  */
354
9
  constructor(e) {
355
10
  /** The Bloc instance this observable is associated with */
356
- i(this, "bloc");
357
- i(this, "_observers", /* @__PURE__ */ new Set());
11
+ n(this, "bloc");
12
+ n(this, "_observers", /* @__PURE__ */ new Set());
358
13
  this.bloc = e;
359
14
  }
360
15
  /**
@@ -377,16 +32,38 @@ class w {
377
32
  * @returns A function that can be called to unsubscribe the observer
378
33
  */
379
34
  subscribe(e) {
380
- return l.log("BlacObservable.subscribe: Subscribing observer.", this.bloc, e), this._observers.add(e), () => {
381
- l.log("BlacObservable.subscribe: Unsubscribing observer.", this.bloc, e), this.unsubscribe(e);
382
- };
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
+ });
383
58
  }
384
59
  /**
385
60
  * Unsubscribes an observer from state changes
386
61
  * @param observer - The observer to unsubscribe
387
62
  */
388
63
  unsubscribe(e) {
389
- this._observers.delete(e), this.size === 0 && l.log("BlacObservable.unsubscribe: No observers left.", this.bloc);
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()));
390
67
  }
391
68
  /**
392
69
  * Notifies all observers of a state change
@@ -395,32 +72,28 @@ class w {
395
72
  * @param action - Optional action that triggered the state change
396
73
  */
397
74
  notify(e, t, s) {
398
- this._observers.forEach((n) => {
399
- let o = !1;
400
- if (n.dependencyArray) {
401
- const a = n.lastState, r = n.dependencyArray(e);
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
+ );
402
83
  if (!a)
403
- o = !0;
404
- else if (a.length !== r.length)
405
- o = !0;
84
+ r = !0;
85
+ else if (a.length !== o.length)
86
+ r = !0;
406
87
  else
407
- for (let h = 0; h < r.length; h++) {
408
- const _ = r[h], p = a[h] || [];
409
- if (_.length !== p.length) {
410
- o = !0;
88
+ for (let l = 0; l < o.length; l++)
89
+ if (!Object.is(a[l], o[l])) {
90
+ r = !0;
411
91
  break;
412
92
  }
413
- for (let f = 0; f < _.length; f++)
414
- if (!Object.is(_[f], p[f])) {
415
- o = !0;
416
- break;
417
- }
418
- if (o) break;
419
- }
420
- n.lastState = r;
93
+ i.lastState = o;
421
94
  } else
422
- o = !0;
423
- o && n.fn(e, t, s);
95
+ r = !0;
96
+ r && i.fn(e, t, s);
424
97
  });
425
98
  }
426
99
  /**
@@ -430,97 +103,103 @@ class w {
430
103
  this._observers.clear();
431
104
  }
432
105
  }
433
- function S() {
434
- 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) {
435
108
  const e = Math.random() * 16 | 0;
436
- return (d === "x" ? e : e & 3 | 8).toString(16);
109
+ return (u === "x" ? e : e & 3 | 8).toString(16);
437
110
  });
438
111
  }
439
- class B {
112
+ var _ = /* @__PURE__ */ ((u) => (u.ACTIVE = "active", u.DISPOSAL_REQUESTED = "disposal_requested", u.DISPOSING = "disposing", u.DISPOSED = "disposed", u))(_ || {});
113
+ class k {
440
114
  /**
441
115
  * Creates a new BlocBase instance with the given initial state.
442
116
  * Sets up the observer, registers with the Blac manager, and initializes addons.
443
- *
117
+ *
444
118
  * @param initialState The initial state value for this Bloc
445
119
  */
446
120
  constructor(e) {
447
- i(this, "uid", S());
121
+ n(this, "uid", R());
448
122
  /**
449
123
  * Defines how dependencies are selected from the state for efficient updates.
450
124
  * When provided, observers will only be notified when selected dependencies change.
451
125
  */
452
- i(this, "defaultDependencySelector");
126
+ n(this, "defaultDependencySelector");
453
127
  /**
454
128
  * @internal
455
129
  * Indicates if this specific Bloc instance is isolated from others of the same type.
456
130
  */
457
- i(this, "_isolated", !1);
131
+ n(this, "_isolated", !1);
458
132
  /**
459
133
  * @internal
460
134
  * Observable responsible for managing state listeners and notifying consumers.
461
135
  */
462
- i(this, "_observer");
136
+ n(this, "_observer");
463
137
  /**
464
138
  * The unique identifier for this Bloc instance.
465
139
  * Defaults to the class name, but can be customized.
466
140
  */
467
- i(this, "_id");
141
+ n(this, "_id");
468
142
  /**
469
143
  * @internal
470
144
  * Reference string used internally for tracking and debugging.
471
145
  */
472
- i(this, "_instanceRef");
146
+ n(this, "_instanceRef");
473
147
  /**
474
148
  * @internal
475
149
  * Indicates if this specific Bloc instance should be kept alive when no consumers are present.
476
150
  */
477
- i(this, "_keepAlive", !1);
151
+ n(this, "_keepAlive", !1);
478
152
  /**
479
153
  * @readonly
480
154
  * Timestamp when this Bloc instance was created, useful for debugging and performance tracking.
481
155
  */
482
- i(this, "_createdAt", Date.now());
156
+ n(this, "_createdAt", Date.now());
483
157
  /**
484
158
  * @internal
485
- * Disposal state to prevent race conditions
159
+ * Atomic disposal state to prevent race conditions
486
160
  */
487
- 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);
488
167
  /**
489
168
  * @internal
490
169
  * The current state of the Bloc.
491
170
  */
492
- i(this, "_state");
171
+ n(this, "_state");
493
172
  /**
494
173
  * @internal
495
174
  * The previous state of the Bloc, maintained for comparison and history.
496
175
  */
497
- i(this, "_oldState");
176
+ n(this, "_oldState");
498
177
  /**
499
178
  * Props passed during Bloc instance creation.
500
179
  * Can be used to configure or parameterize the Bloc's behavior.
501
180
  */
502
- i(this, "props", null);
181
+ n(this, "props", null);
503
182
  /**
504
183
  * @internal
505
184
  * Flag to prevent batching race conditions
506
185
  */
507
- i(this, "_batchingLock", !1);
186
+ n(this, "_batchingLock", !1);
508
187
  /**
509
188
  * @internal
510
189
  * Pending batched updates
511
190
  */
512
- i(this, "_pendingUpdates", []);
191
+ n(this, "_pendingUpdates", []);
513
192
  /**
514
193
  * @internal
515
194
  * Map of consumer IDs to their WeakRef objects for proper cleanup
516
195
  */
517
- i(this, "_consumerRefs", /* @__PURE__ */ new Map());
196
+ n(this, "_consumerRefs", /* @__PURE__ */ new Map());
518
197
  /**
519
198
  * @internal
520
199
  * Validates that all consumer references are still alive
521
200
  * Removes dead consumers automatically
522
201
  */
523
- i(this, "_validateConsumers", () => {
202
+ n(this, "_validateConsumers", () => {
524
203
  const e = [];
525
204
  for (const [t, s] of this._consumerRefs)
526
205
  s.deref() === void 0 && e.push(t);
@@ -532,10 +211,10 @@ class B {
532
211
  * @internal
533
212
  * Updates the Bloc instance's ID to a new value.
534
213
  * Only updates if the new ID is defined and different from the current one.
535
- *
214
+ *
536
215
  * @param id The new ID to assign to this Bloc instance
537
216
  */
538
- i(this, "_updateId", (e) => {
217
+ n(this, "_updateId", (e) => {
539
218
  const t = this._id;
540
219
  !e || e === t || (this._id = e);
541
220
  });
@@ -543,168 +222,631 @@ class B {
543
222
  * @internal
544
223
  * Optional function to be called when the Bloc is disposed.
545
224
  */
546
- i(this, "onDispose");
225
+ n(this, "onDispose");
547
226
  /**
548
227
  * @internal
549
228
  * Set of consumer IDs currently listening to this Bloc's state changes.
550
229
  */
551
- i(this, "_consumers", /* @__PURE__ */ new Set());
230
+ n(this, "_consumers", /* @__PURE__ */ new Set());
552
231
  /**
553
232
  * @internal
554
233
  * Registers a new consumer to this Bloc instance.
555
234
  * Notifies the Blac manager that a consumer has been added.
556
- *
235
+ *
557
236
  * @param consumerId The unique ID of the consumer being added
558
237
  * @param consumerRef Optional reference to the consumer object for cleanup validation
559
238
  */
560
- i(this, "_addConsumer", (e, t) => {
561
- this._disposalState === "active" && (this._consumers.has(e) || (this._consumers.add(e), t && this._consumerRefs.set(e, new WeakRef(t))));
239
+ n(this, "_addConsumer", (e, t) => {
240
+ var s;
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);
562
244
  });
563
245
  /**
564
246
  * @internal
565
247
  * Unregisters a consumer from this Bloc instance.
566
248
  * Notifies the Blac manager that a consumer has been removed.
567
- *
249
+ *
568
250
  * @param consumerId The unique ID of the consumer being removed
569
251
  */
570
- i(this, "_removeConsumer", (e) => {
571
- this._consumers.has(e) && (this._consumers.delete(e), this._consumerRefs.delete(e), this._consumers.size === 0 && !this._keepAlive && this._disposalState === "active" && this._scheduleDisposal());
252
+ n(this, "_removeConsumer", (e) => {
253
+ var t, s;
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()));
572
259
  });
573
260
  /**
574
261
  * @internal
575
262
  * Handler function for disposal (can be set by Blac manager)
576
263
  */
577
- i(this, "_disposalHandler");
578
- i(this, "lastUpdate", Date.now());
264
+ n(this, "_disposalHandler");
265
+ n(this, "lastUpdate", Date.now());
579
266
  /**
580
267
  * @internal
581
268
  * Flag to indicate if batching is enabled for this bloc
582
269
  */
583
- i(this, "_batchingEnabled", !1);
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;
638
+ });
639
+ /**
640
+ * Disposes all keep-alive blocs of a specific type
641
+ * @param blocClass - The bloc class to dispose
642
+ */
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
+ });
584
649
  /**
585
- * @internal
586
- * Updates the state and notifies all observers of the change.
587
- *
588
- * @param newState The new state to be set
589
- * @param oldState The previous state for comparison
590
- * @param action Optional metadata about what caused the state change
650
+ * Disposes all blocs matching a pattern
651
+ * @param predicate - Function to test each bloc for disposal
591
652
  */
592
- i(this, "_pushState", (e, t, s) => {
593
- if (e === void 0) {
594
- console.warn("BlocBase._pushState: newState is undefined", this);
595
- return;
596
- }
597
- if (s !== void 0 && typeof s != "object" && typeof s != "function") {
598
- console.warn("BlocBase._pushState: Invalid action type", this, s);
599
- return;
600
- }
601
- if (this._batchingEnabled) {
602
- this._pendingUpdates.push({ newState: e, oldState: t, action: s }), this._oldState = t, this._state = e;
603
- return;
604
- }
605
- this._oldState = t, this._state = e, this._observer.notify(e, t, s), this.lastUpdate = Date.now();
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());
606
661
  });
607
662
  /**
608
- * Enables batching for multiple state updates
609
- * @param batchFn Function to execute with batching enabled
663
+ * Gets memory usage statistics for debugging
610
664
  */
611
- i(this, "batch", (e) => {
612
- if (this._batchingLock)
613
- return e();
614
- this._batchingLock = !0, this._batchingEnabled = !0, this._pendingUpdates = [];
615
- try {
616
- const t = e();
617
- if (this._pendingUpdates.length > 0) {
618
- const s = this._pendingUpdates[this._pendingUpdates.length - 1];
619
- this._observer.notify(s.newState, s.oldState, s.action), this.lastUpdate = Date.now();
620
- }
621
- return t;
622
- } finally {
623
- this._batchingEnabled = !1, this._batchingLock = !1, this._pendingUpdates = [];
624
- }
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
+ }));
675
+ /**
676
+ * Validates consumer references and cleans up orphaned consumers
677
+ */
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);
625
683
  });
626
- this._state = e, this._observer = new w(this), this._id = this.constructor.name;
627
- const t = this.constructor;
628
- 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);
629
688
  }
630
- get isIsolated() {
631
- return this._isolated;
689
+ static get instance() {
690
+ return b.getInstance();
632
691
  }
633
- get isKeepAlive() {
634
- return this._keepAlive;
692
+ static get getAllBlocs() {
693
+ return c.instance.getAllBlocs;
694
+ }
695
+ static get log() {
696
+ return c.instance.log;
635
697
  }
636
698
  /**
637
- * Returns the current state of the Bloc.
638
- * Use this getter to access the state in a read-only manner.
699
+ * Gets the current Blac instance
700
+ * @returns The Blac instance
639
701
  */
640
- get state() {
641
- 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;
642
713
  }
643
714
  /**
644
- * @internal
645
- * 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"
646
719
  */
647
- get _name() {
648
- return this.constructor.name;
720
+ createBlocInstanceMapKey(e, t) {
721
+ return `${e}:${String(t)}`;
649
722
  }
650
723
  /**
651
- * @internal
652
- * Cleans up resources and removes this Bloc from the system.
653
- * 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
654
726
  */
655
- _dispose() {
656
- var e;
657
- 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);
658
730
  }
659
731
  /**
660
- * @internal
661
- * Sets the disposal handler for this bloc
732
+ * Registers a bloc instance in the main registry
733
+ * @param bloc - The bloc instance to register
662
734
  */
663
- _setDisposalHandler(e) {
664
- 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);
665
738
  }
666
739
  /**
667
- * @internal
668
- * 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
669
744
  */
670
- _scheduleDisposal() {
671
- 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);
672
749
  }
673
- }
674
- /**
675
- * When true, every consumer will receive its own unique instance of this Bloc.
676
- * Use this when state should not be shared between components.
677
- * @default false
678
- */
679
- i(B, "isolated", !1), /**
680
- * When true, the Bloc instance persists even when there are no active consumers.
681
- * Useful for maintaining state between component unmount/remount cycles.
682
- * @default false
683
- */
684
- i(B, "keepAlive", !1);
685
- class b extends B {
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 {
686
828
  constructor() {
687
829
  super(...arguments);
688
830
  // Stores handlers: Map<EventConstructor (subtype of A), HandlerFunction>
689
831
  // The handler's event parameter will be correctly typed to the specific EventConstructor
690
832
  // by the 'on' method's signature.
691
- i(this, "eventHandlers", /* @__PURE__ */ new Map());
833
+ n(this, "eventHandlers", /* @__PURE__ */ new Map());
692
834
  /**
693
835
  * @internal
694
836
  * Event queue to ensure sequential processing of async events
695
837
  */
696
- i(this, "_eventQueue", []);
838
+ n(this, "_eventQueue", []);
697
839
  /**
698
840
  * @internal
699
841
  * Flag indicating if an event is currently being processed
700
842
  */
701
- i(this, "_isProcessingEvent", !1);
843
+ n(this, "_isProcessingEvent", !1);
702
844
  /**
703
845
  * Dispatches an action/event to the Bloc.
704
846
  * Events are queued and processed sequentially to prevent race conditions.
705
847
  * @param action The action/event instance to be processed.
706
848
  */
707
- i(this, "add", async (t) => {
849
+ n(this, "add", async (t) => {
708
850
  this._eventQueue.push(t), this._isProcessingEvent || await this._processEventQueue();
709
851
  });
710
852
  }
@@ -716,7 +858,7 @@ class b extends B {
716
858
  * The 'event' parameter in the handler will be typed to the specific eventConstructor.
717
859
  */
718
860
  on(t, s) {
719
- this.eventHandlers.has(t) && l.warn(
861
+ this.eventHandlers.has(t) && f.warn(
720
862
  `[Bloc ${this._name}:${String(this._id)}] Handler for event '${t.name}' already registered. It will be overwritten.`
721
863
  ), this.eventHandlers.set(
722
864
  t,
@@ -745,35 +887,35 @@ class b extends B {
745
887
  * Processes a single event
746
888
  */
747
889
  async _processEvent(t) {
748
- const s = t.constructor, n = this.eventHandlers.get(s);
749
- if (n) {
750
- const o = (a) => {
751
- const r = this.state;
752
- this._pushState(a, r, 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);
753
895
  };
754
896
  try {
755
- await n(t, o);
897
+ await i(t, r);
756
898
  } catch (a) {
757
- const r = t.constructor.name || "UnnamedConstructor", h = {
899
+ const o = t.constructor.name || "UnnamedConstructor", l = {
758
900
  blocName: this._name,
759
901
  blocId: String(this._id),
760
- eventType: r,
902
+ eventType: o,
761
903
  currentState: this.state,
762
904
  action: t,
763
905
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
764
906
  };
765
- if (l.error(
766
- `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${r}':`,
907
+ if (f.error(
908
+ `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${o}':`,
767
909
  a,
768
910
  "Context:",
769
- h
911
+ l
770
912
  ), a instanceof Error && a.name === "CriticalError")
771
913
  throw a;
772
914
  }
773
915
  } else {
774
- const o = t.constructor.name || "UnnamedConstructor";
775
- l.warn(
776
- `[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}'.`,
777
919
  "Registered handlers:",
778
920
  Array.from(this.eventHandlers.keys()).map((a) => a.name),
779
921
  "Action was:",
@@ -782,7 +924,7 @@ class b extends B {
782
924
  }
783
925
  }
784
926
  }
785
- class k extends B {
927
+ class V extends k {
786
928
  /**
787
929
  * Updates the current state and notifies all observers of the change.
788
930
  * If the new state is identical to the current state (using Object.is),
@@ -798,14 +940,14 @@ class k extends B {
798
940
  /**
799
941
  * Partially updates the current state by merging it with the provided state patch.
800
942
  * This method is only applicable when the state is an object type.
801
- *
943
+ *
802
944
  * @param statePatch - A partial state object containing only the properties to update
803
945
  * @param ignoreChangeCheck - If true, skips checking if the state has actually changed
804
946
  * @throws {TypeError} If the state is not an object type
805
947
  */
806
948
  patch(e, t = !1) {
807
949
  if (typeof this.state != "object" || this.state === null) {
808
- l.warn(
950
+ f.warn(
809
951
  "Cubit.patch: was called on a cubit where the state is not an object. This is a no-op."
810
952
  );
811
953
  return;
@@ -814,10 +956,10 @@ class k extends B {
814
956
  if (t)
815
957
  s = !0;
816
958
  else
817
- for (const n in e)
818
- if (Object.prototype.hasOwnProperty.call(e, n)) {
819
- const a = this.state[n];
820
- 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)) {
821
963
  s = !0;
822
964
  break;
823
965
  }
@@ -828,78 +970,86 @@ class k extends B {
828
970
  });
829
971
  }
830
972
  }
831
- class x {
973
+ class U {
832
974
  /**
833
975
  * Sets up a clean test environment
834
976
  */
835
977
  static setUp() {
836
- this.originalInstance = l.instance, l.resetInstance(), l.enableLog = !1;
978
+ this.originalInstance = f.instance, f.resetInstance(), f.enableLog = !1;
837
979
  }
838
980
  /**
839
981
  * Tears down the test environment and restores original state
840
982
  */
841
983
  static tearDown() {
842
- l.resetInstance();
984
+ f.resetInstance();
843
985
  }
844
986
  /**
845
987
  * Creates a test bloc with automatic cleanup
846
988
  */
847
989
  static createBloc(e, ...t) {
848
990
  const s = new e(...t);
849
- return l.activateBloc(s), s;
991
+ return f.activateBloc(s), s;
850
992
  }
851
993
  /**
852
994
  * Waits for a bloc to emit a specific state
853
995
  */
854
996
  static async waitForState(e, t, s = 5e3) {
855
- return new Promise((n, o) => {
997
+ return new Promise((i, r) => {
856
998
  const a = setTimeout(() => {
857
- o(new Error(`Timeout waiting for state matching predicate after ${s}ms`));
858
- }, s), r = e._observer.subscribe({
859
- id: `test-waiter-${crypto.randomUUID()}`,
860
- fn: (h) => {
861
- t(h) && (clearTimeout(a), r(), 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));
862
1008
  }
863
1009
  });
864
- t(e.state) && (clearTimeout(a), r(), n(e.state));
1010
+ t(e.state) && (clearTimeout(a), o(), i(e.state));
865
1011
  });
866
1012
  }
867
1013
  /**
868
1014
  * Expects a bloc to emit specific states in order
869
1015
  */
870
1016
  static async expectStates(e, t, s = 5e3) {
871
- const n = [];
872
- return new Promise((o, a) => {
873
- const r = setTimeout(() => {
874
- a(new Error(
875
- `Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(n)}`
876
- ));
877
- }, 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({
878
1026
  id: `test-expecter-${crypto.randomUUID()}`,
879
- fn: (_) => {
880
- if (n.push(_), n.length === t.length) {
881
- clearTimeout(r), h();
882
- for (let p = 0; p < t.length; p++) {
883
- const f = t[p], I = n[p];
884
- if (JSON.stringify(f) !== JSON.stringify(I)) {
885
- a(new Error(
886
- `State mismatch at index ${p}. Expected: ${JSON.stringify(f)}, Received: ${JSON.stringify(I)}`
887
- ));
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
+ );
888
1038
  return;
889
1039
  }
890
1040
  }
891
- o();
1041
+ r();
892
1042
  }
893
1043
  }
894
1044
  });
895
1045
  });
896
1046
  }
897
1047
  }
898
- i(x, "originalInstance");
899
- class A extends b {
1048
+ n(U, "originalInstance");
1049
+ class z extends O {
900
1050
  constructor(t) {
901
1051
  super(t);
902
- i(this, "mockHandlers", /* @__PURE__ */ new Map());
1052
+ n(this, "mockHandlers", /* @__PURE__ */ new Map());
903
1053
  }
904
1054
  /**
905
1055
  * Mock an event handler for testing
@@ -920,10 +1070,10 @@ class A extends b {
920
1070
  return this.eventHandlers.has(t);
921
1071
  }
922
1072
  }
923
- class E extends k {
1073
+ class j extends V {
924
1074
  constructor(t) {
925
1075
  super(t);
926
- i(this, "stateHistory", []);
1076
+ n(this, "stateHistory", []);
927
1077
  this.stateHistory.push(t);
928
1078
  }
929
1079
  /**
@@ -945,16 +1095,16 @@ class E extends k {
945
1095
  this.stateHistory = [this.state];
946
1096
  }
947
1097
  }
948
- class R {
1098
+ class K {
949
1099
  constructor() {
950
- i(this, "initialStats");
951
- this.initialStats = l.getMemoryStats();
1100
+ n(this, "initialStats");
1101
+ this.initialStats = f.getMemoryStats();
952
1102
  }
953
1103
  /**
954
1104
  * Check for memory leaks and return a report
955
1105
  */
956
1106
  checkForLeaks() {
957
- 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 = `
958
1108
  Memory Leak Detection Report:
959
1109
  - Initial registered blocs: ${this.initialStats.registeredBlocs}
960
1110
  - Current registered blocs: ${e.registeredBlocs}
@@ -971,17 +1121,400 @@ Memory Leak Detection Report:
971
1121
  };
972
1122
  }
973
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
+ }
974
1503
  export {
975
- l as Blac,
976
- w as BlacObservable,
977
- b as Bloc,
978
- B as BlocBase,
979
- x as BlocTest,
980
- k as Cubit,
981
- R as MemoryLeakDetector,
982
- A as MockBloc,
983
- E as MockCubit,
984
- S as generateUUID,
985
- M 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
986
1519
  };
987
1520
  //# sourceMappingURL=index.es.js.map