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

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,385 +1,7 @@
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 E = Object.defineProperty;
2
+ var O = (c, e, t) => e in c ? E(c, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[e] = t;
3
+ var i = (c, e, t) => O(c, typeof e != "symbol" ? e + "" : e, t);
4
+ class V {
383
5
  /**
384
6
  * Creates a new BlacObservable instance
385
7
  * @param bloc - The Bloc instance to observe
@@ -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 ? (d.log(
37
+ "BlacObservable.subscribe: Cannot subscribe to disposed/disposing bloc.",
38
+ this.bloc,
39
+ e
40
+ ), () => {
41
+ }) : (d.log(
42
+ "BlacObservable.subscribe: Subscribing observer.",
43
+ this.bloc,
44
+ e
45
+ ), this._observers.add(e), t === _.DISPOSAL_REQUESTED && (d.log(
46
+ "BlacObservable.subscribe: Cancelling disposal due to new subscription.",
47
+ this.bloc
48
+ ), this.bloc._atomicStateTransition(
49
+ _.DISPOSAL_REQUESTED,
50
+ _.ACTIVE
51
+ )), () => {
52
+ d.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 && (d.log("BlacObservable.unsubscribe: No observers left.", this.bloc), this.bloc._consumers.size === 0 && !this.bloc._keepAlive && this.bloc._disposalState === _.ACTIVE && (d.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
@@ -429,31 +73,27 @@ class w {
429
73
  */
430
74
  notify(e, t, s) {
431
75
  this._observers.forEach((n) => {
432
- let o = !1;
76
+ let r = !1;
433
77
  if (n.dependencyArray) {
434
- const a = n.lastState, c = n.dependencyArray(e, t);
435
- if (!a)
436
- o = !0;
437
- else if (a.length !== c.length)
438
- o = !0;
78
+ const o = n.lastState, a = n.dependencyArray(
79
+ e,
80
+ t,
81
+ this.bloc
82
+ );
83
+ if (!o)
84
+ r = !0;
85
+ else if (o.length !== a.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 u = 0; u < a.length; u++)
89
+ if (!Object.is(o[u], a[u])) {
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
+ n.lastState = a;
454
94
  } else
455
- o = !0;
456
- o && n.fn(e, t, s);
95
+ r = !0;
96
+ r && n.fn(e, t, s);
457
97
  });
458
98
  }
459
99
  /**
@@ -463,21 +103,22 @@ 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 $() {
107
+ return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
468
108
  const e = Math.random() * 16 | 0;
469
- return (d === "x" ? e : e & 3 | 8).toString(16);
109
+ return (c === "x" ? e : e & 3 | 8).toString(16);
470
110
  });
471
111
  }
472
- class v {
112
+ var _ = /* @__PURE__ */ ((c) => (c.ACTIVE = "active", c.DISPOSAL_REQUESTED = "disposal_requested", c.DISPOSING = "disposing", c.DISPOSED = "disposed", c))(_ || {});
113
+ class x {
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
+ i(this, "uid", $());
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.
@@ -515,9 +156,14 @@ class v {
515
156
  i(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
161
  i(this, "_disposalState", "active");
162
+ /**
163
+ * @internal
164
+ * Timestamp when disposal was requested (for React Strict Mode grace period)
165
+ */
166
+ i(this, "_disposalRequestTime", 0);
521
167
  /**
522
168
  * @internal
523
169
  * The current state of the Bloc.
@@ -565,7 +211,7 @@ 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
217
  i(this, "_updateId", (e) => {
@@ -586,24 +232,30 @@ class v {
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
239
  i(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
252
  i(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()));
607
259
  });
608
260
  /**
609
261
  * @internal
@@ -619,110 +271,585 @@ class v {
619
271
  /**
620
272
  * @internal
621
273
  * Updates the state and notifies all observers of the change.
622
- *
274
+ *
623
275
  * @param newState The new state to be set
624
276
  * @param oldState The previous state for comparison
625
277
  * @param action Optional metadata about what caused the state change
626
278
  */
627
279
  i(this, "_pushState", (e, t, s) => {
628
- if (e === void 0) {
629
- console.warn("BlocBase._pushState: newState is undefined", this);
630
- return;
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
+ i(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 = [];
631
309
  }
632
- if (s !== void 0 && typeof s != "object" && typeof s != "function") {
633
- console.warn("BlocBase._pushState: Invalid action type", this, s);
310
+ });
311
+ this._state = e, this._observer = new V(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, n, r, o;
352
+ if (this._disposalState === e) {
353
+ const a = this._disposalState;
354
+ return this._disposalState = t, (s = globalThis.Blac) != null && s.enableLog && ((n = globalThis.Blac) == null || n.log(
355
+ `[${this._name}:${this._id}] State transition: ${a} -> ${t} (SUCCESS)`
356
+ )), {
357
+ success: !0,
358
+ currentState: t,
359
+ previousState: a
360
+ };
361
+ }
362
+ return (r = globalThis.Blac) != null && r.enableLog && ((o = globalThis.Blac) == null || o.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
+ i(x, "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
+ i(x, "keepAlive", !1);
445
+ const y = class y {
446
+ getInstance() {
447
+ return y._instance || (y._instance = new d({
448
+ __unsafe_ignore_singleton: !0
449
+ })), y._instance;
450
+ }
451
+ setInstance(e) {
452
+ y._instance = e;
453
+ }
454
+ resetInstance() {
455
+ const e = y._instance;
456
+ if (y._instance = new d({
457
+ __unsafe_ignore_singleton: !0
458
+ }), e)
459
+ for (const t of e.keepAliveBlocs)
460
+ y._instance.keepAliveBlocs.add(t), y._instance.uidRegistry.set(t.uid, t);
461
+ }
462
+ };
463
+ i(y, "_instance");
464
+ let C = y, S = new C();
465
+ function q(c) {
466
+ S = c;
467
+ }
468
+ const l = class l {
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
+ i(this, "createdAt", Date.now());
476
+ /** Map storing all registered bloc instances by their class name and ID */
477
+ i(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
+ i(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
483
+ /** Map for O(1) lookup of isolated blocs by UID */
484
+ i(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
485
+ /** Map tracking UIDs to prevent memory leaks */
486
+ i(this, "uidRegistry", /* @__PURE__ */ new Map());
487
+ /** Set of keep-alive blocs for controlled cleanup */
488
+ i(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
489
+ /** Flag to control whether changes should be posted to document */
490
+ i(this, "postChangesToDocument", !1);
491
+ /**
492
+ * Logs messages to console when logging is enabled
493
+ * @param args - Arguments to log
494
+ */
495
+ i(this, "log", (...e) => {
496
+ l.logSpy && l.logSpy(e), l.enableLog && l.logLevel, l.enableLog && l.logLevel;
497
+ });
498
+ /**
499
+ * Logs a warning message
500
+ * @param message - Warning message
501
+ * @param args - Additional arguments
502
+ */
503
+ i(this, "warn", (e, ...t) => {
504
+ l.enableLog;
505
+ });
506
+ /**
507
+ * Logs an error message
508
+ * @param message - Error message
509
+ * @param args - Additional arguments
510
+ */
511
+ i(this, "error", (e, ...t) => {
512
+ l.enableLog;
513
+ });
514
+ /**
515
+ * Resets the Blac instance to a new one, disposing non-keepAlive blocs
516
+ * from the old instance.
517
+ */
518
+ i(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((n) => {
525
+ !n._keepAlive && n._disposalState === _.ACTIVE && this.disposeBloc(n);
526
+ });
527
+ }), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), S.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
+ i(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
+ );
634
542
  return;
635
543
  }
636
- if (this._batchingEnabled) {
637
- this._pendingUpdates.push({ newState: e, oldState: t, action: s }), this._oldState = t, this._state = e;
544
+ const n = e.constructor, r = this.createBlocInstanceMapKey(e._name, e._id);
545
+ this.log(
546
+ `[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(n.isolated)}`
547
+ ), e._dispose(), n.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(r)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
548
+ });
549
+ i(this, "activateBloc", (e) => {
550
+ if (e._disposalState !== _.ACTIVE) {
551
+ this.log(
552
+ `[${e._name}:${String(e._id)}] activateBloc called on disposed bloc. Ignoring.`
553
+ );
638
554
  return;
639
555
  }
640
- this._oldState = t, this._state = e, this._observer.notify(e, t, s), this.lastUpdate = Date.now();
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
+ i(this, "getBloc", (e, t = {}) => {
573
+ const { id: s, forceNewInstance: n } = t, r = e, o = s ?? e.name;
574
+ if (this.log(`[${e.name}:${String(o)}] (getBloc) Called:`, {
575
+ options: t,
576
+ base: r
577
+ }), !n)
578
+ if (r.isolated) {
579
+ const u = this.findIsolatedBlocInstance(
580
+ e,
581
+ t.instanceRef ?? o
582
+ );
583
+ if (u)
584
+ return u;
585
+ if (t.throwIfNotFound)
586
+ throw new Error(`Isolated bloc ${e.name} not found`);
587
+ } else {
588
+ const u = this.findRegisteredBlocInstance(
589
+ e,
590
+ o
591
+ );
592
+ if (u)
593
+ return u;
594
+ if (t.throwIfNotFound)
595
+ throw new Error(`Registered bloc ${e.name} not found`);
596
+ }
597
+ const a = this.createNewBlocInstance(e, o, t);
598
+ if (this.log(
599
+ `[${e.name}:${String(o)}] (getBloc) No existing instance found. Creating new one.`,
600
+ t,
601
+ a
602
+ ), !a)
603
+ throw new Error(
604
+ `[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`
605
+ );
606
+ return a;
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
+ i(this, "getBlocOrThrow", (e, t = {}) => {
617
+ const s = e.isolated, n = t.id || e.name, r = s ? this.findIsolatedBlocInstance(e, n) : this.findRegisteredBlocInstance(e, n);
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
+ i(this, "getAllBlocs", (e, t = {}) => {
630
+ const s = [];
631
+ if (this.blocInstanceMap.forEach((n) => {
632
+ n.constructor === e && s.push(n);
633
+ }), t.searchIsolated !== !1) {
634
+ const n = this.isolatedBlocMap.get(e);
635
+ n && s.push(...n.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
+ i(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
+ });
649
+ /**
650
+ * Disposes all blocs matching a pattern
651
+ * @param predicate - Function to test each bloc for disposal
652
+ */
653
+ i(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 n of s)
659
+ e(n) && t.push(n);
660
+ t.forEach((s) => s._dispose());
641
661
  });
642
662
  /**
643
- * Enables batching for multiple state updates
644
- * @param batchFn Function to execute with batching enabled
663
+ * Gets memory usage statistics for debugging
645
664
  */
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
- }
665
+ i(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
+ i(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 l.instance;
687
+ S.setInstance(this);
664
688
  }
665
- get isIsolated() {
666
- return this._isolated;
689
+ static get instance() {
690
+ return S.getInstance();
667
691
  }
668
- get isKeepAlive() {
669
- return this._keepAlive;
692
+ static get getAllBlocs() {
693
+ return l.instance.getAllBlocs;
694
+ }
695
+ /** Get current configuration */
696
+ static get config() {
697
+ return { ...this._config };
670
698
  }
671
699
  /**
672
- * Returns the current state of the Bloc.
673
- * Use this getter to access the state in a read-only manner.
700
+ * Set or update Blac configuration
701
+ * @param config - Partial configuration to merge with existing config
702
+ * @throws Error if configuration is invalid
674
703
  */
675
- get state() {
676
- return this._state;
704
+ static setConfig(e) {
705
+ if (e.proxyDependencyTracking !== void 0 && typeof e.proxyDependencyTracking != "boolean")
706
+ throw new Error("BlacConfig.proxyDependencyTracking must be a boolean");
707
+ if (e.exposeBlacInstance !== void 0 && typeof e.exposeBlacInstance != "boolean")
708
+ throw new Error("BlacConfig.exposeBlacInstance must be a boolean");
709
+ this._config = {
710
+ ...this._config,
711
+ ...e
712
+ }, this.enableLog && this.instance.log("Blac config updated:", this._config);
713
+ }
714
+ static get log() {
715
+ return l.instance.log;
677
716
  }
678
717
  /**
679
- * @internal
680
- * Returns the name of the Bloc class for identification and debugging.
718
+ * Gets the current Blac instance
719
+ * @returns The Blac instance
681
720
  */
682
- get _name() {
683
- return this.constructor.name;
721
+ static getInstance() {
722
+ return S.getInstance();
723
+ }
724
+ static get warn() {
725
+ return l.instance.warn;
726
+ }
727
+ static get error() {
728
+ return l.instance.error;
729
+ }
730
+ static get disposeBloc() {
731
+ return l.instance.disposeBloc;
684
732
  }
685
733
  /**
686
- * @internal
687
- * Cleans up resources and removes this Bloc from the system.
688
- * Notifies the Blac manager and clears all observers.
734
+ * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
735
+ * @param blocClassName - The name of the bloc class
736
+ * @param id - The instance ID
737
+ * @returns A unique key string in the format "className:id"
689
738
  */
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");
739
+ createBlocInstanceMapKey(e, t) {
740
+ return `${e}:${String(t)}`;
693
741
  }
694
742
  /**
695
- * @internal
696
- * Sets the disposal handler for this bloc
743
+ * Unregister a bloc instance from the main registry
744
+ * @param bloc - The bloc instance to unregister
697
745
  */
698
- _setDisposalHandler(e) {
699
- this._disposalHandler = e;
746
+ unregisterBlocInstance(e) {
747
+ const t = this.createBlocInstanceMapKey(e._name, e._id);
748
+ this.blocInstanceMap.delete(t), this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e);
700
749
  }
701
750
  /**
702
- * @internal
703
- * Schedules disposal of this bloc instance if it has no consumers
751
+ * Registers a bloc instance in the main registry
752
+ * @param bloc - The bloc instance to register
704
753
  */
705
- _scheduleDisposal() {
706
- this._disposalState === "active" && this._consumers.size === 0 && !this._keepAlive && (this._disposalHandler ? this._disposalHandler(this) : this._dispose());
754
+ registerBlocInstance(e) {
755
+ const t = this.createBlocInstanceMapKey(e._name, e._id);
756
+ this.blocInstanceMap.set(t, e), this.uidRegistry.set(e.uid, e), e._keepAlive && this.keepAliveBlocs.add(e);
707
757
  }
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 {
758
+ /**
759
+ * Finds a registered bloc instance by its class and ID
760
+ * @param blocClass - The bloc class to search for
761
+ * @param id - The instance ID
762
+ * @returns The found bloc instance or undefined if not found
763
+ */
764
+ findRegisteredBlocInstance(e, t) {
765
+ if (e.isolated) return;
766
+ const n = this.createBlocInstanceMapKey(e.name, t);
767
+ return this.blocInstanceMap.get(n);
768
+ }
769
+ /**
770
+ * Registers an isolated bloc instance in the isolated registry
771
+ * @param bloc - The isolated bloc instance to register
772
+ */
773
+ registerIsolatedBlocInstance(e) {
774
+ const t = e.constructor, s = this.isolatedBlocMap.get(t);
775
+ 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);
776
+ }
777
+ /**
778
+ * Unregister an isolated bloc instance from the isolated registry
779
+ * @param bloc - The isolated bloc instance to unregister
780
+ */
781
+ unregisterIsolatedBlocInstance(e) {
782
+ const t = e.constructor, s = this.isolatedBlocMap.get(t);
783
+ let n = !1;
784
+ if (s) {
785
+ const o = s.findIndex((a) => a.uid === e.uid);
786
+ o !== -1 && (s.splice(o, 1), n = !0), s.length === 0 && this.isolatedBlocMap.delete(t);
787
+ }
788
+ const r = this.isolatedBlocIndex.delete(e.uid);
789
+ this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), n !== r && this.warn(
790
+ `[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${n}, Index removal: ${r}`
791
+ );
792
+ }
793
+ /**
794
+ * Finds an isolated bloc instance by its class and ID (O(n) lookup)
795
+ */
796
+ findIsolatedBlocInstance(e, t) {
797
+ if (!e.isolated) return;
798
+ const n = this.isolatedBlocMap.get(e);
799
+ return n ? n.find((o) => o._id === t) : void 0;
800
+ }
801
+ /**
802
+ * Finds an isolated bloc instance by UID (O(1) lookup)
803
+ */
804
+ findIsolatedBlocInstanceByUid(e) {
805
+ return this.isolatedBlocIndex.get(e);
806
+ }
807
+ /**
808
+ * Creates a new bloc instance and registers it in the appropriate registry
809
+ * @param blocClass - The bloc class to instantiate
810
+ * @param id - The instance ID
811
+ * @param props - Properties to pass to the bloc constructor
812
+ * @param instanceRef - Optional reference string for the instance
813
+ * @returns The newly created bloc instance
814
+ */
815
+ createNewBlocInstance(e, t, s = {}) {
816
+ const { props: n, instanceRef: r } = s, o = new e(n);
817
+ return o._instanceRef = r, o.props = n || null, o._updateId(t), o._setDisposalHandler((a) => this.disposeBloc(a)), o.isIsolated ? (this.registerIsolatedBlocInstance(o), o) : (this.registerBlocInstance(o), o);
818
+ }
819
+ static get activateBloc() {
820
+ return l.instance.activateBloc;
821
+ }
822
+ static get getBloc() {
823
+ return l.instance.getBloc;
824
+ }
825
+ static get getBlocOrThrow() {
826
+ return l.instance.getBlocOrThrow;
827
+ }
828
+ static get disposeKeepAliveBlocs() {
829
+ return l.instance.disposeKeepAliveBlocs;
830
+ }
831
+ static get disposeBlocs() {
832
+ return l.instance.disposeBlocs;
833
+ }
834
+ static get getMemoryStats() {
835
+ return l.instance.getMemoryStats;
836
+ }
837
+ static get validateConsumers() {
838
+ return l.instance.validateConsumers;
839
+ }
840
+ };
841
+ /** Private static configuration */
842
+ i(l, "_config", {
843
+ exposeBlacInstance: !1,
844
+ proxyDependencyTracking: !0
845
+ }), /** Flag to enable/disable logging */
846
+ i(l, "enableLog", !1), i(l, "logLevel", "warn"), i(l, "logSpy", null), i(l, "resetInstance", () => {
847
+ S.resetInstance();
848
+ });
849
+ let d = l;
850
+ class U extends x {
721
851
  constructor() {
722
852
  super(...arguments);
723
- // Stores handlers: Map<EventConstructor (subtype of A), HandlerFunction>
724
- // The handler's event parameter will be correctly typed to the specific EventConstructor
725
- // by the 'on' method's signature.
726
853
  i(this, "eventHandlers", /* @__PURE__ */ new Map());
727
854
  /**
728
855
  * @internal
@@ -751,7 +878,7 @@ class S extends v {
751
878
  * The 'event' parameter in the handler will be typed to the specific eventConstructor.
752
879
  */
753
880
  on(t, s) {
754
- this.eventHandlers.has(t) && l.warn(
881
+ this.eventHandlers.has(t) && d.warn(
755
882
  `[Bloc ${this._name}:${String(this._id)}] Handler for event '${t.name}' already registered. It will be overwritten.`
756
883
  ), this.eventHandlers.set(
757
884
  t,
@@ -782,42 +909,51 @@ class S extends v {
782
909
  async _processEvent(t) {
783
910
  const s = t.constructor, n = this.eventHandlers.get(s);
784
911
  if (n) {
785
- const o = (a) => {
786
- const c = this.state;
787
- this._pushState(a, c, t);
912
+ const r = (o) => {
913
+ const a = this.state;
914
+ this._pushState(o, a, t);
788
915
  };
789
916
  try {
790
- await n(t, o);
791
- } catch (a) {
792
- const c = t.constructor.name || "UnnamedConstructor", h = {
917
+ await n(t, r);
918
+ } catch (o) {
919
+ const a = t.constructor.name || "UnnamedConstructor", u = {
793
920
  blocName: this._name,
794
921
  blocId: String(this._id),
795
- eventType: c,
922
+ eventType: a,
796
923
  currentState: this.state,
797
924
  action: t,
798
925
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
799
926
  };
800
- if (l.error(
801
- `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${c}':`,
802
- a,
927
+ if (d.error(
928
+ `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${a}':`,
929
+ o,
803
930
  "Context:",
804
- h
805
- ), a instanceof Error && a.name === "CriticalError")
806
- throw a;
931
+ u
932
+ ), o instanceof Error && o.name === "CriticalError")
933
+ throw o;
807
934
  }
808
935
  } 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}'.`,
936
+ const r = t.constructor.name || "UnnamedConstructor";
937
+ d.warn(
938
+ `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${r}'.`,
812
939
  "Registered handlers:",
813
- Array.from(this.eventHandlers.keys()).map((a) => a.name),
940
+ Array.from(this.eventHandlers.keys()).map((o) => o.name),
814
941
  "Action was:",
815
942
  t
816
943
  );
817
944
  }
818
945
  }
819
946
  }
820
- class k extends v {
947
+ class H extends x {
948
+ /**
949
+ * @internal
950
+ * Protected method for useBloc to call
951
+ */
952
+ _updateProps(e) {
953
+ var s;
954
+ const t = this.props;
955
+ this.props = e, (s = this.onPropsChanged) == null || s.call(this, t, e);
956
+ }
821
957
  /**
822
958
  * Updates the current state and notifies all observers of the change.
823
959
  * If the new state is identical to the current state (using Object.is),
@@ -833,14 +969,14 @@ class k extends v {
833
969
  /**
834
970
  * Partially updates the current state by merging it with the provided state patch.
835
971
  * This method is only applicable when the state is an object type.
836
- *
972
+ *
837
973
  * @param statePatch - A partial state object containing only the properties to update
838
974
  * @param ignoreChangeCheck - If true, skips checking if the state has actually changed
839
975
  * @throws {TypeError} If the state is not an object type
840
976
  */
841
977
  patch(e, t = !1) {
842
978
  if (typeof this.state != "object" || this.state === null) {
843
- l.warn(
979
+ d.warn(
844
980
  "Cubit.patch: was called on a cubit where the state is not an object. This is a no-op."
845
981
  );
846
982
  return;
@@ -851,8 +987,8 @@ class k extends v {
851
987
  else
852
988
  for (const n in e)
853
989
  if (Object.prototype.hasOwnProperty.call(e, n)) {
854
- const a = this.state[n];
855
- if (!Object.is(e[n], a)) {
990
+ const o = this.state[n];
991
+ if (!Object.is(e[n], o)) {
856
992
  s = !0;
857
993
  break;
858
994
  }
@@ -863,40 +999,64 @@ class k extends v {
863
999
  });
864
1000
  }
865
1001
  }
866
- class $ {
1002
+ class N {
1003
+ constructor(e) {
1004
+ this.props = e;
1005
+ }
1006
+ }
1007
+ function j(c, e) {
1008
+ if (Object.is(c, e))
1009
+ return !0;
1010
+ if (typeof c != "object" || c === null || typeof e != "object" || e === null)
1011
+ return !1;
1012
+ const t = Object.keys(c), s = Object.keys(e);
1013
+ if (t.length !== s.length)
1014
+ return !1;
1015
+ for (let n = 0; n < t.length; n++) {
1016
+ const r = t[n];
1017
+ if (!Object.prototype.hasOwnProperty.call(e, r) || !Object.is(c[r], e[r]))
1018
+ return !1;
1019
+ }
1020
+ return !0;
1021
+ }
1022
+ class L {
867
1023
  /**
868
1024
  * Sets up a clean test environment
869
1025
  */
870
1026
  static setUp() {
871
- this.originalInstance = l.instance, l.resetInstance(), l.enableLog = !1;
1027
+ this.originalInstance = d.instance, d.resetInstance(), d.enableLog = !1;
872
1028
  }
873
1029
  /**
874
1030
  * Tears down the test environment and restores original state
875
1031
  */
876
1032
  static tearDown() {
877
- l.resetInstance();
1033
+ d.resetInstance();
878
1034
  }
879
1035
  /**
880
1036
  * Creates a test bloc with automatic cleanup
881
1037
  */
882
1038
  static createBloc(e, ...t) {
883
1039
  const s = new e(...t);
884
- return l.activateBloc(s), s;
1040
+ return d.activateBloc(s), s;
885
1041
  }
886
1042
  /**
887
1043
  * Waits for a bloc to emit a specific state
888
1044
  */
889
1045
  static async waitForState(e, t, s = 5e3) {
890
- return new Promise((n, o) => {
891
- 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));
1046
+ return new Promise((n, r) => {
1047
+ const o = setTimeout(() => {
1048
+ r(
1049
+ new Error(
1050
+ `Timeout waiting for state matching predicate after ${s}ms`
1051
+ )
1052
+ );
1053
+ }, s), a = e._observer.subscribe({
1054
+ id: `test-waiter-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
1055
+ fn: (u) => {
1056
+ t(u) && (clearTimeout(o), a(), n(u));
897
1057
  }
898
1058
  });
899
- t(e.state) && (clearTimeout(a), c(), n(e.state));
1059
+ t(e.state) && (clearTimeout(o), a(), n(e.state));
900
1060
  });
901
1061
  }
902
1062
  /**
@@ -904,34 +1064,38 @@ class $ {
904
1064
  */
905
1065
  static async expectStates(e, t, s = 5e3) {
906
1066
  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({
1067
+ return new Promise((r, o) => {
1068
+ const a = setTimeout(() => {
1069
+ o(
1070
+ new Error(
1071
+ `Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(n)}`
1072
+ )
1073
+ );
1074
+ }, s), u = e._observer.subscribe({
913
1075
  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
- ));
1076
+ fn: (p) => {
1077
+ if (n.push(p), n.length === t.length) {
1078
+ clearTimeout(a), u();
1079
+ for (let h = 0; h < t.length; h++) {
1080
+ const m = t[h], I = n[h];
1081
+ if (JSON.stringify(m) !== JSON.stringify(I)) {
1082
+ o(
1083
+ new Error(
1084
+ `State mismatch at index ${h}. Expected: ${JSON.stringify(m)}, Received: ${JSON.stringify(I)}`
1085
+ )
1086
+ );
923
1087
  return;
924
1088
  }
925
1089
  }
926
- o();
1090
+ r();
927
1091
  }
928
1092
  }
929
1093
  });
930
1094
  });
931
1095
  }
932
1096
  }
933
- i($, "originalInstance");
934
- class M extends S {
1097
+ i(L, "originalInstance");
1098
+ class Q extends U {
935
1099
  constructor(t) {
936
1100
  super(t);
937
1101
  i(this, "mockHandlers", /* @__PURE__ */ new Map());
@@ -955,7 +1119,7 @@ class M extends S {
955
1119
  return this.eventHandlers.has(t);
956
1120
  }
957
1121
  }
958
- class E extends k {
1122
+ class W extends H {
959
1123
  constructor(t) {
960
1124
  super(t);
961
1125
  i(this, "stateHistory", []);
@@ -980,16 +1144,16 @@ class E extends k {
980
1144
  this.stateHistory = [this.state];
981
1145
  }
982
1146
  }
983
- class R {
1147
+ class F {
984
1148
  constructor() {
985
1149
  i(this, "initialStats");
986
- this.initialStats = l.getMemoryStats();
1150
+ this.initialStats = d.getMemoryStats();
987
1151
  }
988
1152
  /**
989
1153
  * Check for memory leaks and return a report
990
1154
  */
991
1155
  checkForLeaks() {
992
- const e = l.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
1156
+ const e = d.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
993
1157
  Memory Leak Detection Report:
994
1158
  - Initial registered blocs: ${this.initialStats.registeredBlocs}
995
1159
  - Current registered blocs: ${e.registeredBlocs}
@@ -1006,17 +1170,419 @@ Memory Leak Detection Report:
1006
1170
  };
1007
1171
  }
1008
1172
  }
1173
+ class z {
1174
+ constructor() {
1175
+ i(this, "consumers", /* @__PURE__ */ new WeakMap());
1176
+ i(this, "registrationCount", 0);
1177
+ i(this, "activeConsumers", 0);
1178
+ }
1179
+ register(e, t) {
1180
+ this.registrationCount++, this.consumers.get(e) || this.activeConsumers++, this.consumers.set(e, {
1181
+ id: t,
1182
+ lastNotified: Date.now(),
1183
+ hasRendered: !1,
1184
+ stateAccesses: /* @__PURE__ */ new Set(),
1185
+ classAccesses: /* @__PURE__ */ new Set(),
1186
+ stateValues: /* @__PURE__ */ new Map(),
1187
+ classValues: /* @__PURE__ */ new Map(),
1188
+ accessCount: 0,
1189
+ lastAccessTime: 0,
1190
+ firstAccessTime: 0
1191
+ });
1192
+ }
1193
+ unregister(e) {
1194
+ e && this.consumers.get(e) && (this.consumers.delete(e), this.activeConsumers = Math.max(0, this.activeConsumers - 1));
1195
+ }
1196
+ trackAccess(e, t, s, n) {
1197
+ const r = this.consumers.get(e);
1198
+ if (!r) return;
1199
+ const o = Date.now();
1200
+ r.firstAccessTime || (r.firstAccessTime = o), r.accessCount++, r.lastAccessTime = o, t === "state" ? (r.stateAccesses.add(s), n !== void 0 && r.stateValues.set(s, { value: n, lastAccessTime: o })) : (r.classAccesses.add(s), n !== void 0 && r.classValues.set(s, { value: n, lastAccessTime: o }));
1201
+ }
1202
+ resetTracking(e) {
1203
+ const t = this.consumers.get(e);
1204
+ t && (t.stateAccesses.clear(), t.classAccesses.clear(), t.stateValues.clear(), t.classValues.clear(), t.accessCount = 0, t.firstAccessTime = 0);
1205
+ }
1206
+ getDependencies(e) {
1207
+ const t = this.consumers.get(e);
1208
+ return t ? {
1209
+ statePaths: Array.from(t.stateAccesses),
1210
+ classPaths: Array.from(t.classAccesses)
1211
+ } : null;
1212
+ }
1213
+ hasValuesChanged(e, t, s) {
1214
+ const n = this.consumers.get(e);
1215
+ if (!n) return !0;
1216
+ let r = !1;
1217
+ const o = Date.now();
1218
+ if (n.stateValues.size === 0 && n.classValues.size === 0 && (n.stateAccesses.size > 0 || n.classAccesses.size > 0))
1219
+ return !0;
1220
+ for (const [a, u] of n.stateValues)
1221
+ try {
1222
+ const p = this.getValueAtPath(t, a);
1223
+ p !== u.value && (n.stateValues.set(a, {
1224
+ value: p,
1225
+ lastAccessTime: o
1226
+ }), r = !0);
1227
+ } catch {
1228
+ r = !0;
1229
+ }
1230
+ for (const [a, u] of n.classValues)
1231
+ try {
1232
+ const p = this.getValueAtPath(s, a);
1233
+ p !== u.value && (n.classValues.set(a, {
1234
+ value: p,
1235
+ lastAccessTime: o
1236
+ }), r = !0);
1237
+ } catch {
1238
+ r = !0;
1239
+ }
1240
+ return r;
1241
+ }
1242
+ shouldNotifyConsumer(e, t) {
1243
+ const s = this.consumers.get(e);
1244
+ if (!s) return !1;
1245
+ for (const n of t) {
1246
+ if (s.stateAccesses.has(n) || s.classAccesses.has(n)) return !0;
1247
+ for (const r of s.stateAccesses)
1248
+ if (n.startsWith(r + ".") || r.startsWith(n + "."))
1249
+ return !0;
1250
+ }
1251
+ return !1;
1252
+ }
1253
+ updateLastNotified(e) {
1254
+ const t = this.consumers.get(e);
1255
+ t && (t.lastNotified = Date.now());
1256
+ }
1257
+ getConsumerInfo(e) {
1258
+ return this.consumers.get(e);
1259
+ }
1260
+ setHasRendered(e, t) {
1261
+ const s = this.consumers.get(e);
1262
+ s && (s.hasRendered = t);
1263
+ }
1264
+ hasConsumer(e) {
1265
+ return this.consumers.has(e);
1266
+ }
1267
+ getStats() {
1268
+ return {
1269
+ totalRegistrations: this.registrationCount,
1270
+ activeConsumers: this.activeConsumers
1271
+ };
1272
+ }
1273
+ getValueAtPath(e, t) {
1274
+ const s = t.split(".");
1275
+ let n = e;
1276
+ for (const r of s) {
1277
+ if (n == null) return;
1278
+ n = n[r];
1279
+ }
1280
+ return n;
1281
+ }
1282
+ }
1283
+ const k = /* @__PURE__ */ new WeakMap();
1284
+ let f = {
1285
+ stateProxiesCreated: 0,
1286
+ classProxiesCreated: 0,
1287
+ cacheHits: 0,
1288
+ cacheMisses: 0,
1289
+ propertyAccesses: 0,
1290
+ nestedProxiesCreated: 0,
1291
+ totalProxiesCreated: 0,
1292
+ createdAt: Date.now()
1293
+ };
1294
+ class b {
1295
+ static createStateProxy(e) {
1296
+ const { target: t, consumerRef: s, consumerTracker: n, path: r = "" } = e;
1297
+ if (!s || !n || typeof t != "object" || t === null)
1298
+ return t;
1299
+ let o = k.get(t);
1300
+ o || (o = /* @__PURE__ */ new WeakMap(), k.set(t, o));
1301
+ const a = o.get(s);
1302
+ if (a)
1303
+ return f.cacheHits++, a;
1304
+ f.cacheMisses++;
1305
+ const u = {
1306
+ get(h, m) {
1307
+ if (typeof m == "symbol" || m === "constructor")
1308
+ return Reflect.get(h, m);
1309
+ const I = r ? `${r}.${m}` : m;
1310
+ f.propertyAccesses++;
1311
+ const g = Reflect.get(h, m), w = g && typeof g === "object" && g !== null ? void 0 : g;
1312
+ if (n.trackAccess(s, "state", I, w), g && typeof g == "object" && g !== null) {
1313
+ const B = Object.getPrototypeOf(g) === Object.prototype, P = Array.isArray(g);
1314
+ if (B || P)
1315
+ return f.nestedProxiesCreated++, b.createStateProxy({
1316
+ target: g,
1317
+ consumerRef: s,
1318
+ consumerTracker: n,
1319
+ path: I
1320
+ });
1321
+ }
1322
+ return g;
1323
+ },
1324
+ has(h, m) {
1325
+ return m in h;
1326
+ },
1327
+ ownKeys(h) {
1328
+ return Reflect.ownKeys(h);
1329
+ },
1330
+ getOwnPropertyDescriptor(h, m) {
1331
+ return Reflect.getOwnPropertyDescriptor(h, m);
1332
+ },
1333
+ set() {
1334
+ return !1;
1335
+ },
1336
+ deleteProperty() {
1337
+ return !1;
1338
+ }
1339
+ }, p = new Proxy(t, u);
1340
+ return o.set(s, p), f.stateProxiesCreated++, f.totalProxiesCreated++, p;
1341
+ }
1342
+ static createClassProxy(e) {
1343
+ const { target: t, consumerRef: s, consumerTracker: n } = e;
1344
+ if (!s || !n)
1345
+ return t;
1346
+ let r = k.get(t);
1347
+ r || (r = /* @__PURE__ */ new WeakMap(), k.set(t, r));
1348
+ const o = r.get(s);
1349
+ if (o)
1350
+ return f.cacheHits++, o;
1351
+ f.cacheMisses++;
1352
+ const a = {
1353
+ get(p, h) {
1354
+ const m = Reflect.get(p, h);
1355
+ let I = !1, g = p;
1356
+ const A = /* @__PURE__ */ new WeakSet(), D = 10;
1357
+ let w = 0;
1358
+ for (; g && !I && w < D && !A.has(g); ) {
1359
+ A.add(g);
1360
+ try {
1361
+ const T = Object.getOwnPropertyDescriptor(
1362
+ g,
1363
+ h
1364
+ );
1365
+ if (T && T.get) {
1366
+ I = !0;
1367
+ break;
1368
+ }
1369
+ g = Object.getPrototypeOf(g), w++;
1370
+ } catch {
1371
+ break;
1372
+ }
1373
+ }
1374
+ if (!I)
1375
+ return m;
1376
+ f.propertyAccesses++;
1377
+ const B = m, M = B !== null && typeof B != "object" ? B : void 0;
1378
+ return n.trackAccess(
1379
+ s,
1380
+ "class",
1381
+ String(h),
1382
+ M
1383
+ ), m;
1384
+ },
1385
+ has(p, h) {
1386
+ return h in p;
1387
+ },
1388
+ ownKeys(p) {
1389
+ return Reflect.ownKeys(p);
1390
+ },
1391
+ getOwnPropertyDescriptor(p, h) {
1392
+ return Reflect.getOwnPropertyDescriptor(p, h);
1393
+ }
1394
+ }, u = new Proxy(t, a);
1395
+ return r.set(s, u), f.classProxiesCreated++, f.totalProxiesCreated++, u;
1396
+ }
1397
+ static getProxyState(e) {
1398
+ return b.createStateProxy({
1399
+ target: e.state,
1400
+ consumerRef: e.consumerRef,
1401
+ consumerTracker: e.consumerTracker
1402
+ });
1403
+ }
1404
+ static getProxyBlocInstance(e) {
1405
+ return b.createClassProxy({
1406
+ target: e.blocInstance,
1407
+ consumerRef: e.consumerRef,
1408
+ consumerTracker: e.consumerTracker
1409
+ });
1410
+ }
1411
+ static getStats() {
1412
+ const e = Date.now() - f.createdAt;
1413
+ return {
1414
+ ...f,
1415
+ totalProxies: f.stateProxiesCreated + f.classProxiesCreated,
1416
+ cacheEfficiency: f.cacheHits + f.cacheMisses > 0 ? `${(f.cacheHits / (f.cacheHits + f.cacheMisses) * 100).toFixed(1)}%` : "N/A",
1417
+ lifetime: `${e}ms`,
1418
+ proxiesPerSecond: e > 0 ? (f.totalProxiesCreated / (e / 1e3)).toFixed(2) : "N/A"
1419
+ };
1420
+ }
1421
+ static resetStats() {
1422
+ f = {
1423
+ stateProxiesCreated: 0,
1424
+ classProxiesCreated: 0,
1425
+ cacheHits: 0,
1426
+ cacheMisses: 0,
1427
+ propertyAccesses: 0,
1428
+ nestedProxiesCreated: 0,
1429
+ totalProxiesCreated: 0,
1430
+ createdAt: Date.now()
1431
+ };
1432
+ }
1433
+ }
1434
+ const v = class v {
1435
+ constructor(e, t) {
1436
+ i(this, "id", `consumer-${$()}`);
1437
+ i(this, "blocConstructor");
1438
+ i(this, "componentRef", { current: {} });
1439
+ i(this, "blocInstance");
1440
+ // Core components
1441
+ i(this, "consumerTracker");
1442
+ i(this, "lastProps");
1443
+ i(this, "unmountTime", 0);
1444
+ i(this, "mountTime", 0);
1445
+ // Dependency tracking
1446
+ i(this, "dependencyValues");
1447
+ i(this, "isUsingDependencies", !1);
1448
+ // Lifecycle state
1449
+ i(this, "hasMounted", !1);
1450
+ i(this, "mountCount", 0);
1451
+ i(this, "options");
1452
+ i(this, "createStateProxy", (e) => b.createStateProxy({
1453
+ target: e.target,
1454
+ consumerRef: this.componentRef.current,
1455
+ consumerTracker: this
1456
+ }));
1457
+ i(this, "createClassProxy", (e) => b.createClassProxy({
1458
+ target: e.target,
1459
+ consumerRef: this.componentRef.current,
1460
+ consumerTracker: this
1461
+ }));
1462
+ i(this, "createSubscription", (e) => this.blocInstance._observer.subscribe({
1463
+ id: this.id,
1464
+ fn: (s, n) => {
1465
+ var r;
1466
+ if (this.isUsingDependencies && ((r = this.options) != null && r.dependencies)) {
1467
+ const o = this.options.dependencies(this.blocInstance);
1468
+ if (!this.hasDependencyValuesChanged(
1469
+ this.dependencyValues,
1470
+ o
1471
+ ))
1472
+ return;
1473
+ this.dependencyValues = o;
1474
+ } else if (d.config.proxyDependencyTracking) {
1475
+ const o = this.consumerTracker.getConsumerInfo(
1476
+ this.componentRef.current
1477
+ );
1478
+ if (o && o.hasRendered && !this.consumerTracker.hasValuesChanged(
1479
+ this.componentRef.current,
1480
+ s,
1481
+ this.blocInstance
1482
+ ))
1483
+ return;
1484
+ } else {
1485
+ e.onChange();
1486
+ return;
1487
+ }
1488
+ e.onChange();
1489
+ }
1490
+ }));
1491
+ i(this, "mount", () => {
1492
+ var e, t;
1493
+ 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))
1494
+ try {
1495
+ this.options.onMount(this.blocInstance);
1496
+ } catch (s) {
1497
+ throw s;
1498
+ }
1499
+ });
1500
+ i(this, "unmount", () => {
1501
+ var e;
1502
+ if (this.unmountTime = Date.now(), this.consumerTracker.unregister(this.componentRef.current), this.blocInstance._removeConsumer(this.id), v.propsOwners.get(this.blocInstance) === this.id && v.propsOwners.delete(this.blocInstance), (e = this.options) != null && e.onUnmount)
1503
+ try {
1504
+ this.options.onUnmount(this.blocInstance);
1505
+ } catch {
1506
+ }
1507
+ });
1508
+ i(this, "getProxyState", (e) => this.isUsingDependencies || !d.config.proxyDependencyTracking ? e : b.getProxyState({
1509
+ state: e,
1510
+ consumerRef: this.componentRef.current,
1511
+ consumerTracker: this
1512
+ }));
1513
+ i(this, "getProxyBlocInstance", () => this.isUsingDependencies || !d.config.proxyDependencyTracking ? this.blocInstance : b.getProxyBlocInstance({
1514
+ blocInstance: this.blocInstance,
1515
+ consumerRef: this.componentRef.current,
1516
+ consumerTracker: this
1517
+ }));
1518
+ this.options = t, this.blocConstructor = e.blocConstructor, this.componentRef = e.componentRef, this.isUsingDependencies = !!(t != null && t.dependencies), this.consumerTracker = new z(), this.blocInstance = this.updateBlocInstance(), this.consumerTracker.register(e.componentRef.current, this.id), this.isUsingDependencies && (t != null && t.dependencies) && (this.dependencyValues = t.dependencies(this.blocInstance)), (t == null ? void 0 : t.props) !== void 0 && this.updateProps(t.props);
1519
+ }
1520
+ trackAccess(e, t, s, n) {
1521
+ this.consumerTracker.trackAccess(e, t, s, n);
1522
+ }
1523
+ getConsumerDependencies(e) {
1524
+ return this.consumerTracker.getDependencies(e);
1525
+ }
1526
+ shouldNotifyConsumer(e, t) {
1527
+ const s = this.consumerTracker.getConsumerInfo(e);
1528
+ return !s || !s.hasRendered ? !0 : this.consumerTracker.shouldNotifyConsumer(e, t);
1529
+ }
1530
+ updateLastNotified(e) {
1531
+ this.consumerTracker.updateLastNotified(e), this.consumerTracker.setHasRendered(e, !0);
1532
+ }
1533
+ resetConsumerTracking() {
1534
+ this.consumerTracker.resetTracking(this.componentRef.current);
1535
+ }
1536
+ updateBlocInstance() {
1537
+ var e, t;
1538
+ return this.blocInstance = d.instance.getBloc(this.blocConstructor, {
1539
+ props: (e = this.options) == null ? void 0 : e.props,
1540
+ id: (t = this.options) == null ? void 0 : t.id,
1541
+ instanceRef: this.id
1542
+ }), this.blocInstance;
1543
+ }
1544
+ // Expose calledOnMount for backward compatibility
1545
+ get calledOnMount() {
1546
+ return this.hasMounted;
1547
+ }
1548
+ updateProps(e) {
1549
+ const t = this.blocInstance;
1550
+ if (v.propsOwners.has(t) || v.propsOwners.set(t, this.id), v.propsOwners.get(t) !== this.id) {
1551
+ d.warn(
1552
+ `[BlacAdapter] Attempted to set props on ${t.constructor.name} from non-owner adapter`
1553
+ );
1554
+ return;
1555
+ }
1556
+ t._disposalState === _.DISPOSED || t._disposalState === _.DISPOSING || j(this.lastProps, e) || ("add" in t && typeof t.add == "function" ? t.add(new N(e)) : "_updateProps" in t && typeof t._updateProps == "function" && t._updateProps(e), this.lastProps = e);
1557
+ }
1558
+ hasDependencyValuesChanged(e, t) {
1559
+ if (!e || e.length !== t.length) return !0;
1560
+ for (let s = 0; s < e.length; s++)
1561
+ if (!Object.is(e[s], t[s]))
1562
+ return !0;
1563
+ return !1;
1564
+ }
1565
+ };
1566
+ // Props ownership tracking
1567
+ i(v, "propsOwners", /* @__PURE__ */ new WeakMap());
1568
+ let R = v;
1009
1569
  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
1570
+ d as Blac,
1571
+ R as BlacAdapter,
1572
+ V as BlacObservable,
1573
+ U as Bloc,
1574
+ x as BlocBase,
1575
+ _ as BlocLifecycleState,
1576
+ L as BlocTest,
1577
+ z as ConsumerTracker,
1578
+ H as Cubit,
1579
+ F as MemoryLeakDetector,
1580
+ Q as MockBloc,
1581
+ W as MockCubit,
1582
+ N as PropsUpdated,
1583
+ b as ProxyFactory,
1584
+ $ as generateUUID,
1585
+ q as setBlacInstanceManager,
1586
+ j as shallowEqual
1021
1587
  };
1022
1588
  //# sourceMappingURL=index.es.js.map