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

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,15 +1,15 @@
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 {
1
+ var R = Object.defineProperty;
2
+ var O = (c, e, t) => e in c ? R(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 H {
5
5
  /**
6
6
  * Creates a new BlacObservable instance
7
7
  * @param bloc - The Bloc instance to observe
8
8
  */
9
9
  constructor(e) {
10
10
  /** The Bloc instance this observable is associated with */
11
- n(this, "bloc");
12
- n(this, "_observers", /* @__PURE__ */ new Set());
11
+ i(this, "bloc");
12
+ i(this, "_observers", /* @__PURE__ */ new Set());
13
13
  this.bloc = e;
14
14
  }
15
15
  /**
@@ -33,23 +33,23 @@ class E {
33
33
  */
34
34
  subscribe(e) {
35
35
  const t = this.bloc._disposalState;
36
- return t === _.DISPOSED || t === _.DISPOSING ? (f.log(
36
+ return t === y.DISPOSED || t === y.DISPOSING ? (u.log(
37
37
  "BlacObservable.subscribe: Cannot subscribe to disposed/disposing bloc.",
38
38
  this.bloc,
39
39
  e
40
40
  ), () => {
41
- }) : (f.log(
41
+ }) : (u.log(
42
42
  "BlacObservable.subscribe: Subscribing observer.",
43
43
  this.bloc,
44
44
  e
45
- ), this._observers.add(e), t === _.DISPOSAL_REQUESTED && (f.log(
45
+ ), this._observers.add(e), t === y.DISPOSAL_REQUESTED && (u.log(
46
46
  "BlacObservable.subscribe: Cancelling disposal due to new subscription.",
47
47
  this.bloc
48
48
  ), this.bloc._atomicStateTransition(
49
- _.DISPOSAL_REQUESTED,
50
- _.ACTIVE
49
+ y.DISPOSAL_REQUESTED,
50
+ y.ACTIVE
51
51
  )), () => {
52
- f.log(
52
+ u.log(
53
53
  "BlacObservable.subscribe: Unsubscribing observer.",
54
54
  this.bloc,
55
55
  e
@@ -61,7 +61,7 @@ class E {
61
61
  * @param observer - The observer to unsubscribe
62
62
  */
63
63
  unsubscribe(e) {
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(
64
+ this._observers.delete(e), this.size === 0 && (u.log("BlacObservable.unsubscribe: No observers left.", this.bloc), this.bloc._consumers.size === 0 && !this.bloc._keepAlive && this.bloc._disposalState === y.ACTIVE && (u.log(
65
65
  `[${this.bloc._name}:${this.bloc._id}] No observers or consumers left. Scheduling disposal.`
66
66
  ), this.bloc._scheduleDisposal()));
67
67
  }
@@ -72,29 +72,29 @@ class E {
72
72
  * @param action - Optional action that triggered the state change
73
73
  */
74
74
  notify(e, t, s) {
75
- this._observers.forEach((i) => {
76
- let r = !1;
77
- if (i.dependencyArray) {
78
- const a = i.lastState, o = i.dependencyArray(
75
+ this._observers.forEach((r) => {
76
+ let n = !1;
77
+ if (r.dependencyArray) {
78
+ const o = r.lastState, a = r.dependencyArray(
79
79
  e,
80
80
  t,
81
81
  this.bloc
82
82
  );
83
- if (!a)
84
- r = !0;
85
- else if (a.length !== o.length)
86
- r = !0;
83
+ if (!o)
84
+ n = !0;
85
+ else if (o.length !== a.length)
86
+ n = !0;
87
87
  else
88
- for (let l = 0; l < o.length; l++)
89
- if (!Object.is(a[l], o[l])) {
90
- r = !0;
88
+ for (let l = 0; l < a.length; l++)
89
+ if (!Object.is(o[l], a[l])) {
90
+ n = !0;
91
91
  break;
92
92
  }
93
- i.lastState = o;
93
+ r.lastState = a;
94
94
  } else
95
- r = !0;
96
- r && i.fn(e, t, s);
97
- });
95
+ n = !0;
96
+ n && r.fn(e, t, s);
97
+ }), u.instance.plugins.notifyStateChanged(this.bloc, t, e);
98
98
  }
99
99
  /**
100
100
  * Clears the observer set
@@ -103,13 +103,166 @@ class E {
103
103
  this._observers.clear();
104
104
  }
105
105
  }
106
- function R() {
107
- return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(u) {
106
+ function $() {
107
+ return typeof crypto < "u" && crypto.randomUUID ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
108
108
  const e = Math.random() * 16 | 0;
109
- return (u === "x" ? e : e & 3 | 8).toString(16);
109
+ return (c === "x" ? e : e & 3 | 8).toString(16);
110
110
  });
111
111
  }
112
- var _ = /* @__PURE__ */ ((u) => (u.ACTIVE = "active", u.DISPOSAL_REQUESTED = "disposal_requested", u.DISPOSING = "disposing", u.DISPOSED = "disposed", u))(_ || {});
112
+ class V {
113
+ constructor() {
114
+ i(this, "plugins", /* @__PURE__ */ new Map());
115
+ i(this, "executionOrder", []);
116
+ i(this, "attached", !1);
117
+ }
118
+ /**
119
+ * Add a bloc plugin
120
+ */
121
+ add(e) {
122
+ if (this.plugins.has(e.name))
123
+ throw new Error(`Plugin '${e.name}' is already registered`);
124
+ e.capabilities && this.validateCapabilities(e), this.plugins.set(e.name, e), this.executionOrder.push(e.name);
125
+ }
126
+ /**
127
+ * Remove a bloc plugin
128
+ */
129
+ remove(e) {
130
+ const t = this.plugins.get(e);
131
+ if (!t) return !1;
132
+ if (this.attached && t.onDetach)
133
+ try {
134
+ t.onDetach();
135
+ } catch (s) {
136
+ console.error(`Plugin '${e}' error in onDetach:`, s);
137
+ }
138
+ return this.plugins.delete(e), this.executionOrder = this.executionOrder.filter((s) => s !== e), !0;
139
+ }
140
+ /**
141
+ * Get a plugin by name
142
+ */
143
+ get(e) {
144
+ return this.plugins.get(e);
145
+ }
146
+ /**
147
+ * Get all plugins in execution order
148
+ */
149
+ getAll() {
150
+ return this.executionOrder.map((e) => this.plugins.get(e));
151
+ }
152
+ /**
153
+ * Clear all plugins
154
+ */
155
+ clear() {
156
+ if (this.attached) {
157
+ for (const e of this.getAll())
158
+ if (e.onDetach)
159
+ try {
160
+ e.onDetach();
161
+ } catch (t) {
162
+ console.error(`Plugin '${e.name}' error in onDetach:`, t);
163
+ }
164
+ }
165
+ this.plugins.clear(), this.executionOrder = [], this.attached = !1;
166
+ }
167
+ /**
168
+ * Attach all plugins to a bloc
169
+ */
170
+ attach(e) {
171
+ if (this.attached)
172
+ throw new Error("Plugins are already attached");
173
+ for (const t of this.getAll())
174
+ if (t.onAttach)
175
+ try {
176
+ t.onAttach(e);
177
+ } catch (s) {
178
+ console.error(`Plugin '${t.name}' error in onAttach:`, s), this.remove(t.name);
179
+ }
180
+ this.attached = !0;
181
+ }
182
+ /**
183
+ * Transform state through all plugins
184
+ */
185
+ transformState(e, t) {
186
+ let s = t;
187
+ for (const r of this.getAll())
188
+ if (r.transformState && this.canTransformState(r))
189
+ try {
190
+ s = r.transformState(e, s);
191
+ } catch (n) {
192
+ console.error(`Plugin '${r.name}' error in transformState:`, n);
193
+ }
194
+ return s;
195
+ }
196
+ /**
197
+ * Transform event through all plugins
198
+ */
199
+ transformEvent(e) {
200
+ let t = e;
201
+ for (const s of this.getAll()) {
202
+ if (t === null) break;
203
+ if (s.transformEvent && this.canInterceptEvents(s))
204
+ try {
205
+ t = s.transformEvent(t);
206
+ } catch (r) {
207
+ console.error(`Plugin '${s.name}' error in transformEvent:`, r);
208
+ }
209
+ }
210
+ return t;
211
+ }
212
+ /**
213
+ * Notify plugins of state change
214
+ */
215
+ notifyStateChange(e, t) {
216
+ for (const s of this.getAll())
217
+ if (s.onStateChange && this.canReadState(s))
218
+ try {
219
+ s.onStateChange(e, t);
220
+ } catch (r) {
221
+ console.error(`Plugin '${s.name}' error in onStateChange:`, r);
222
+ }
223
+ }
224
+ /**
225
+ * Notify plugins of event
226
+ */
227
+ notifyEvent(e) {
228
+ for (const t of this.getAll())
229
+ if (t.onEvent && this.canReadState(t))
230
+ try {
231
+ t.onEvent(e);
232
+ } catch (s) {
233
+ console.error(`Plugin '${t.name}' error in onEvent:`, s);
234
+ }
235
+ }
236
+ /**
237
+ * Notify plugins of error
238
+ */
239
+ notifyError(e, t) {
240
+ for (const s of this.getAll())
241
+ if (s.onError)
242
+ try {
243
+ s.onError(e, t);
244
+ } catch (r) {
245
+ console.error(`Plugin '${s.name}' error in onError:`, r);
246
+ }
247
+ }
248
+ validateCapabilities(e) {
249
+ const t = e.capabilities;
250
+ if (t.transformState && !t.readState)
251
+ throw new Error(`Plugin '${e.name}': transformState requires readState capability`);
252
+ if (t.interceptEvents && !t.readState)
253
+ throw new Error(`Plugin '${e.name}': interceptEvents requires readState capability`);
254
+ }
255
+ canReadState(e) {
256
+ return !e.capabilities || e.capabilities.readState !== !1;
257
+ }
258
+ canTransformState(e) {
259
+ return !e.capabilities || e.capabilities.transformState === !0;
260
+ }
261
+ canInterceptEvents(e) {
262
+ return !e.capabilities || e.capabilities.interceptEvents === !0;
263
+ }
264
+ }
265
+ var y = /* @__PURE__ */ ((c) => (c.ACTIVE = "active", c.DISPOSAL_REQUESTED = "disposal_requested", c.DISPOSING = "disposing", c.DISPOSED = "disposed", c))(y || {});
113
266
  class k {
114
267
  /**
115
268
  * Creates a new BlocBase instance with the given initial state.
@@ -118,88 +271,92 @@ class k {
118
271
  * @param initialState The initial state value for this Bloc
119
272
  */
120
273
  constructor(e) {
121
- n(this, "uid", R());
274
+ i(this, "uid", $());
122
275
  /**
123
276
  * Defines how dependencies are selected from the state for efficient updates.
124
277
  * When provided, observers will only be notified when selected dependencies change.
125
278
  */
126
- n(this, "defaultDependencySelector");
279
+ i(this, "defaultDependencySelector");
127
280
  /**
128
281
  * @internal
129
282
  * Indicates if this specific Bloc instance is isolated from others of the same type.
130
283
  */
131
- n(this, "_isolated", !1);
284
+ i(this, "_isolated", !1);
132
285
  /**
133
286
  * @internal
134
287
  * Observable responsible for managing state listeners and notifying consumers.
135
288
  */
136
- n(this, "_observer");
289
+ i(this, "_observer");
137
290
  /**
138
291
  * The unique identifier for this Bloc instance.
139
292
  * Defaults to the class name, but can be customized.
140
293
  */
141
- n(this, "_id");
294
+ i(this, "_id");
142
295
  /**
143
296
  * @internal
144
297
  * Reference string used internally for tracking and debugging.
145
298
  */
146
- n(this, "_instanceRef");
299
+ i(this, "_instanceRef");
147
300
  /**
148
301
  * @internal
149
302
  * Indicates if this specific Bloc instance should be kept alive when no consumers are present.
150
303
  */
151
- n(this, "_keepAlive", !1);
304
+ i(this, "_keepAlive", !1);
152
305
  /**
153
306
  * @readonly
154
307
  * Timestamp when this Bloc instance was created, useful for debugging and performance tracking.
155
308
  */
156
- n(this, "_createdAt", Date.now());
309
+ i(this, "_createdAt", Date.now());
157
310
  /**
158
311
  * @internal
159
312
  * Atomic disposal state to prevent race conditions
160
313
  */
161
- n(this, "_disposalState", "active");
314
+ i(this, "_disposalState", "active");
162
315
  /**
163
316
  * @internal
164
317
  * Timestamp when disposal was requested (for React Strict Mode grace period)
165
318
  */
166
- n(this, "_disposalRequestTime", 0);
319
+ i(this, "_disposalRequestTime", 0);
167
320
  /**
168
321
  * @internal
169
322
  * The current state of the Bloc.
170
323
  */
171
- n(this, "_state");
324
+ i(this, "_state");
172
325
  /**
173
326
  * @internal
174
327
  * The previous state of the Bloc, maintained for comparison and history.
175
328
  */
176
- n(this, "_oldState");
329
+ i(this, "_oldState");
177
330
  /**
178
331
  * Props passed during Bloc instance creation.
179
332
  * Can be used to configure or parameterize the Bloc's behavior.
180
333
  */
181
- n(this, "props", null);
334
+ i(this, "props", null);
182
335
  /**
183
336
  * @internal
184
337
  * Flag to prevent batching race conditions
185
338
  */
186
- n(this, "_batchingLock", !1);
339
+ i(this, "_batchingLock", !1);
187
340
  /**
188
341
  * @internal
189
342
  * Pending batched updates
190
343
  */
191
- n(this, "_pendingUpdates", []);
344
+ i(this, "_pendingUpdates", []);
192
345
  /**
193
346
  * @internal
194
347
  * Map of consumer IDs to their WeakRef objects for proper cleanup
195
348
  */
196
- n(this, "_consumerRefs", /* @__PURE__ */ new Map());
349
+ i(this, "_consumerRefs", /* @__PURE__ */ new Map());
350
+ /**
351
+ * Plugin registry for this bloc instance
352
+ */
353
+ i(this, "_plugins");
197
354
  /**
198
355
  * @internal
199
356
  * Validates that all consumer references are still alive
200
357
  * Removes dead consumers automatically
201
358
  */
202
- n(this, "_validateConsumers", () => {
359
+ i(this, "_validateConsumers", () => {
203
360
  const e = [];
204
361
  for (const [t, s] of this._consumerRefs)
205
362
  s.deref() === void 0 && e.push(t);
@@ -214,7 +371,7 @@ class k {
214
371
  *
215
372
  * @param id The new ID to assign to this Bloc instance
216
373
  */
217
- n(this, "_updateId", (e) => {
374
+ i(this, "_updateId", (e) => {
218
375
  const t = this._id;
219
376
  !e || e === t || (this._id = e);
220
377
  });
@@ -222,12 +379,12 @@ class k {
222
379
  * @internal
223
380
  * Optional function to be called when the Bloc is disposed.
224
381
  */
225
- n(this, "onDispose");
382
+ i(this, "onDispose");
226
383
  /**
227
384
  * @internal
228
385
  * Set of consumer IDs currently listening to this Bloc's state changes.
229
386
  */
230
- n(this, "_consumers", /* @__PURE__ */ new Set());
387
+ i(this, "_consumers", /* @__PURE__ */ new Set());
231
388
  /**
232
389
  * @internal
233
390
  * Registers a new consumer to this Bloc instance.
@@ -236,7 +393,7 @@ class k {
236
393
  * @param consumerId The unique ID of the consumer being added
237
394
  * @param consumerRef Optional reference to the consumer object for cleanup validation
238
395
  */
239
- n(this, "_addConsumer", (e, t) => {
396
+ i(this, "_addConsumer", (e, t) => {
240
397
  var s;
241
398
  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
399
  `[${this._name}:${this._id}] Consumer added. Total consumers: ${this._consumers.size}`
@@ -249,7 +406,7 @@ class k {
249
406
  *
250
407
  * @param consumerId The unique ID of the consumer being removed
251
408
  */
252
- n(this, "_removeConsumer", (e) => {
409
+ i(this, "_removeConsumer", (e) => {
253
410
  var t, s;
254
411
  this._consumers.has(e) && (this._consumers.delete(e), this._consumerRefs.delete(e), (t = globalThis.Blac) == null || t.log(
255
412
  `[${this._name}:${this._id}] Consumer removed. Remaining consumers: ${this._consumers.size}, keepAlive: ${this._keepAlive}`
@@ -261,13 +418,13 @@ class k {
261
418
  * @internal
262
419
  * Handler function for disposal (can be set by Blac manager)
263
420
  */
264
- n(this, "_disposalHandler");
265
- n(this, "lastUpdate", Date.now());
421
+ i(this, "_disposalHandler");
422
+ i(this, "lastUpdate", Date.now());
266
423
  /**
267
424
  * @internal
268
425
  * Flag to indicate if batching is enabled for this bloc
269
426
  */
270
- n(this, "_batchingEnabled", !1);
427
+ i(this, "_batchingEnabled", !1);
271
428
  /**
272
429
  * @internal
273
430
  * Updates the state and notifies all observers of the change.
@@ -276,20 +433,35 @@ class k {
276
433
  * @param oldState The previous state for comparison
277
434
  * @param action Optional metadata about what caused the state change
278
435
  */
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();
436
+ i(this, "_pushState", (e, t, s) => {
437
+ if (e === void 0 || s !== void 0 && typeof s != "object" && typeof s != "function")
438
+ return;
439
+ let r = e;
440
+ try {
441
+ r = this._plugins.transformState(t, e);
442
+ } catch (n) {
443
+ this._plugins.notifyError(n, {
444
+ phase: "state-change",
445
+ operation: "transformState"
446
+ });
447
+ }
448
+ if (this._batchingEnabled) {
449
+ this._pendingUpdates.push({ newState: r, oldState: t, action: s }), this._oldState = t, this._state = r;
450
+ return;
286
451
  }
452
+ this._oldState = t, this._state = r;
453
+ try {
454
+ this._plugins.notifyStateChange(t, r);
455
+ } catch (n) {
456
+ console.error("Error notifying bloc plugins of state change:", n);
457
+ }
458
+ this._observer.notify(r, t, s), this.lastUpdate = Date.now();
287
459
  });
288
460
  /**
289
461
  * Enables batching for multiple state updates
290
462
  * @param batchFn Function to execute with batching enabled
291
463
  */
292
- n(this, "batch", (e) => {
464
+ i(this, "batch", (e) => {
293
465
  if (this._batchingLock)
294
466
  return e();
295
467
  this._batchingLock = !0, this._batchingEnabled = !0, this._pendingUpdates = [];
@@ -308,9 +480,11 @@ class k {
308
480
  this._batchingEnabled = !1, this._batchingLock = !1, this._pendingUpdates = [];
309
481
  }
310
482
  });
311
- this._state = e, this._observer = new E(this), this._id = this.constructor.name;
483
+ this._state = e, this._observer = new H(this), this._id = this.constructor.name;
312
484
  const t = this.constructor;
313
- this._keepAlive = typeof t.keepAlive == "boolean" ? t.keepAlive : !1, this._isolated = typeof t.isolated == "boolean" ? t.isolated : !1;
485
+ if (this._keepAlive = typeof t.keepAlive == "boolean" ? t.keepAlive : !1, this._isolated = typeof t.isolated == "boolean" ? t.isolated : !1, this._plugins = new V(), t.plugins && Array.isArray(t.plugins))
486
+ for (const s of t.plugins)
487
+ this.addPlugin(s);
314
488
  }
315
489
  get isIsolated() {
316
490
  return this._isolated;
@@ -348,18 +522,18 @@ class k {
348
522
  * @returns Result indicating success/failure and state information
349
523
  */
350
524
  _atomicStateTransition(e, t) {
351
- var s, i, r, a;
525
+ var s, r, n, o;
352
526
  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)`
527
+ const a = this._disposalState;
528
+ return this._disposalState = t, (s = globalThis.Blac) != null && s.enableLog && ((r = globalThis.Blac) == null || r.log(
529
+ `[${this._name}:${this._id}] State transition: ${a} -> ${t} (SUCCESS)`
356
530
  )), {
357
531
  success: !0,
358
532
  currentState: t,
359
- previousState: o
533
+ previousState: a
360
534
  };
361
535
  }
362
- return (r = globalThis.Blac) != null && r.enableLog && ((a = globalThis.Blac) == null || a.log(
536
+ return (n = globalThis.Blac) != null && n.enableLog && ((o = globalThis.Blac) == null || o.log(
363
537
  `[${this._name}:${this._id}] State transition failed: expected ${e}, current ${this._disposalState}`
364
538
  )), {
365
539
  success: !1,
@@ -430,124 +604,308 @@ class k {
430
604
  );
431
605
  });
432
606
  }
607
+ /**
608
+ * Notify observers of a state change
609
+ * @internal Used by plugins for state hydration
610
+ * @param newState The new state
611
+ * @param oldState The old state
612
+ */
613
+ _notifyObservers(e, t) {
614
+ this._observer.notify(e, t);
615
+ }
616
+ /**
617
+ * Add a plugin to this bloc instance
618
+ */
619
+ addPlugin(e) {
620
+ if (this._plugins.add(e), this._disposalState === "active")
621
+ try {
622
+ e.onAttach && e.onAttach(this);
623
+ } catch (t) {
624
+ throw console.error(`Failed to attach plugin '${e.name}':`, t), this._plugins.remove(e.name), t;
625
+ }
626
+ }
627
+ /**
628
+ * Remove a plugin from this bloc instance
629
+ */
630
+ removePlugin(e) {
631
+ return this._plugins.remove(e);
632
+ }
633
+ /**
634
+ * Get a plugin by name
635
+ */
636
+ getPlugin(e) {
637
+ return this._plugins.get(e);
638
+ }
639
+ /**
640
+ * Get all plugins
641
+ */
642
+ getPlugins() {
643
+ return this._plugins.getAll();
644
+ }
645
+ /**
646
+ * @internal
647
+ * Activate plugins when bloc becomes active
648
+ */
649
+ _activatePlugins() {
650
+ if (this._disposalState === "active")
651
+ try {
652
+ this._plugins.attach(this);
653
+ } catch (e) {
654
+ console.error(`Failed to activate plugins for ${this._name}:`, e);
655
+ }
656
+ }
433
657
  }
434
658
  /**
435
659
  * When true, every consumer will receive its own unique instance of this Bloc.
436
660
  * Use this when state should not be shared between components.
437
661
  * @default false
438
662
  */
439
- n(k, "isolated", !1), /**
663
+ i(k, "isolated", !1), /**
440
664
  * When true, the Bloc instance persists even when there are no active consumers.
441
665
  * Useful for maintaining state between component unmount/remount cycles.
442
666
  * @default false
443
667
  */
444
- n(k, "keepAlive", !1);
445
- const I = class I {
668
+ i(k, "keepAlive", !1);
669
+ class U {
670
+ constructor() {
671
+ i(this, "plugins", /* @__PURE__ */ new Map());
672
+ i(this, "metrics", /* @__PURE__ */ new Map());
673
+ i(this, "executionOrder", []);
674
+ }
675
+ /**
676
+ * Add a system plugin
677
+ */
678
+ add(e) {
679
+ if (this.plugins.has(e.name))
680
+ throw new Error(`Plugin '${e.name}' is already registered`);
681
+ this.plugins.set(e.name, e), this.executionOrder.push(e.name), this.initializeMetrics(e.name);
682
+ }
683
+ /**
684
+ * Remove a system plugin
685
+ */
686
+ remove(e) {
687
+ return this.plugins.get(e) ? (this.plugins.delete(e), this.metrics.delete(e), this.executionOrder = this.executionOrder.filter((s) => s !== e), !0) : !1;
688
+ }
689
+ /**
690
+ * Get a plugin by name
691
+ */
692
+ get(e) {
693
+ return this.plugins.get(e);
694
+ }
695
+ /**
696
+ * Get all plugins in execution order
697
+ */
698
+ getAll() {
699
+ return this.executionOrder.map((e) => this.plugins.get(e));
700
+ }
701
+ /**
702
+ * Clear all plugins
703
+ */
704
+ clear() {
705
+ this.plugins.clear(), this.metrics.clear(), this.executionOrder = [];
706
+ }
707
+ /**
708
+ * Execute a hook on all plugins
709
+ */
710
+ executeHook(e, t, s) {
711
+ for (const r of this.executionOrder) {
712
+ const n = this.plugins.get(r), o = n[e];
713
+ if (typeof o != "function") continue;
714
+ const a = performance.now();
715
+ try {
716
+ o.apply(n, t), this.recordSuccess(r, e, a);
717
+ } catch (l) {
718
+ this.recordError(r, e, l), s ? s(l, n) : console.error(`Plugin '${r}' error in hook '${e}':`, l);
719
+ }
720
+ }
721
+ }
722
+ /**
723
+ * Bootstrap all plugins
724
+ */
725
+ bootstrap() {
726
+ this.executeHook("beforeBootstrap", []), this.executeHook("afterBootstrap", []);
727
+ }
728
+ /**
729
+ * Shutdown all plugins
730
+ */
731
+ shutdown() {
732
+ this.executeHook("beforeShutdown", []), this.executeHook("afterShutdown", []);
733
+ }
734
+ /**
735
+ * Notify plugins of bloc creation
736
+ */
737
+ notifyBlocCreated(e) {
738
+ this.executeHook("onBlocCreated", [e]);
739
+ }
740
+ /**
741
+ * Notify plugins of bloc disposal
742
+ */
743
+ notifyBlocDisposed(e) {
744
+ this.executeHook("onBlocDisposed", [e]);
745
+ }
746
+ /**
747
+ * Notify plugins of state change
748
+ */
749
+ notifyStateChanged(e, t, s) {
750
+ this.executeHook("onStateChanged", [e, t, s]);
751
+ }
752
+ /**
753
+ * Notify plugins of event addition
754
+ */
755
+ notifyEventAdded(e, t) {
756
+ this.executeHook("onEventAdded", [e, t]);
757
+ }
758
+ /**
759
+ * Notify plugins of errors
760
+ */
761
+ notifyError(e, t, s) {
762
+ this.executeHook("onError", [e, t, s], (r, n) => {
763
+ console.error(`Plugin '${n.name}' error handler failed:`, r);
764
+ });
765
+ }
766
+ /**
767
+ * Get metrics for a plugin
768
+ */
769
+ getMetrics(e) {
770
+ return this.metrics.get(e);
771
+ }
772
+ initializeMetrics(e) {
773
+ this.metrics.set(e, /* @__PURE__ */ new Map());
774
+ }
775
+ recordSuccess(e, t, s) {
776
+ const r = this.metrics.get(e), n = r.get(t) || {
777
+ executionTime: 0,
778
+ executionCount: 0,
779
+ errorCount: 0
780
+ }, o = performance.now() - s;
781
+ r.set(t, {
782
+ ...n,
783
+ executionTime: n.executionTime + o,
784
+ executionCount: n.executionCount + 1,
785
+ lastExecutionTime: o
786
+ });
787
+ }
788
+ recordError(e, t, s) {
789
+ const r = this.metrics.get(e), n = r.get(t) || {
790
+ executionTime: 0,
791
+ executionCount: 0,
792
+ errorCount: 0
793
+ };
794
+ r.set(t, {
795
+ ...n,
796
+ errorCount: n.errorCount + 1,
797
+ lastError: s
798
+ });
799
+ }
800
+ }
801
+ const _ = class _ {
446
802
  getInstance() {
447
- return I._instance || (I._instance = new f({
803
+ return _._instance || (_._instance = new u({
448
804
  __unsafe_ignore_singleton: !0
449
- })), I._instance;
805
+ })), _._instance;
450
806
  }
451
807
  setInstance(e) {
452
- I._instance = e;
808
+ _._instance = e;
453
809
  }
454
810
  resetInstance() {
455
- const e = I._instance;
456
- if (I._instance = new f({
811
+ const e = _._instance;
812
+ if (_._instance = new u({
457
813
  __unsafe_ignore_singleton: !0
458
814
  }), e)
459
815
  for (const t of e.keepAliveBlocs)
460
- I._instance.keepAliveBlocs.add(t), I._instance.uidRegistry.set(t.uid, t);
816
+ _._instance.keepAliveBlocs.add(t), _._instance.uidRegistry.set(t.uid, t);
461
817
  }
462
818
  };
463
- n(I, "_instance");
464
- let T = I, b = new T();
465
- function L(u) {
466
- b = u;
819
+ i(_, "_instance");
820
+ let E = _, S = new E();
821
+ function W(c) {
822
+ S = c;
467
823
  }
468
- const c = class c {
824
+ const h = class h {
469
825
  /**
470
826
  * Creates a new Blac instance.
471
827
  * @param options - Configuration options including singleton control
472
828
  */
473
829
  constructor(e = {}) {
474
830
  /** Timestamp when the instance was created */
475
- n(this, "createdAt", Date.now());
831
+ i(this, "createdAt", Date.now());
476
832
  /** Map storing all registered bloc instances by their class name and ID */
477
- n(this, "blocInstanceMap", /* @__PURE__ */ new Map());
833
+ i(this, "blocInstanceMap", /* @__PURE__ */ new Map());
478
834
  /** Map storing isolated bloc instances grouped by their constructor */
479
835
  // Using BlocConstructor<BlocBase<unknown>> would break type inference when storing
480
836
  // different bloc types in the same map. The 'any' allows proper polymorphic storage
481
837
  // while maintaining type safety at usage sites through the BlocConstructor constraint.
482
- n(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
838
+ i(this, "isolatedBlocMap", /* @__PURE__ */ new Map());
483
839
  /** Map for O(1) lookup of isolated blocs by UID */
484
- n(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
840
+ i(this, "isolatedBlocIndex", /* @__PURE__ */ new Map());
485
841
  /** Map tracking UIDs to prevent memory leaks */
486
- n(this, "uidRegistry", /* @__PURE__ */ new Map());
842
+ i(this, "uidRegistry", /* @__PURE__ */ new Map());
487
843
  /** Set of keep-alive blocs for controlled cleanup */
488
- n(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
844
+ i(this, "keepAliveBlocs", /* @__PURE__ */ new Set());
489
845
  /** Flag to control whether changes should be posted to document */
490
- n(this, "postChangesToDocument", !1);
846
+ i(this, "postChangesToDocument", !1);
847
+ /** System plugin registry */
848
+ i(this, "plugins", new U());
491
849
  /**
492
850
  * Logs messages to console when logging is enabled
493
851
  * @param args - Arguments to log
494
852
  */
495
- n(this, "log", (...e) => {
496
- c.logSpy && c.logSpy(e), c.enableLog && c.logLevel, c.enableLog && c.logLevel;
853
+ i(this, "log", (...e) => {
854
+ h.logSpy && h.logSpy(e), h.enableLog && h.logLevel, h.enableLog && h.logLevel;
497
855
  });
498
856
  /**
499
857
  * Logs a warning message
500
858
  * @param message - Warning message
501
859
  * @param args - Additional arguments
502
860
  */
503
- n(this, "warn", (e, ...t) => {
504
- c.enableLog;
861
+ i(this, "warn", (e, ...t) => {
862
+ h.enableLog;
505
863
  });
506
864
  /**
507
865
  * Logs an error message
508
866
  * @param message - Error message
509
867
  * @param args - Additional arguments
510
868
  */
511
- n(this, "error", (e, ...t) => {
512
- c.enableLog;
869
+ i(this, "error", (e, ...t) => {
870
+ h.enableLog;
513
871
  });
514
872
  /**
515
873
  * Resets the Blac instance to a new one, disposing non-keepAlive blocs
516
874
  * from the old instance.
517
875
  */
518
- n(this, "resetInstance", () => {
876
+ i(this, "resetInstance", () => {
519
877
  this.log("Reset Blac instance");
520
878
  const e = new Map(this.blocInstanceMap), t = new Map(this.isolatedBlocMap);
521
879
  e.forEach((s) => {
522
- !s._keepAlive && s._disposalState === _.ACTIVE && this.disposeBloc(s);
880
+ !s._keepAlive && s._disposalState === y.ACTIVE && this.disposeBloc(s);
523
881
  }), t.forEach((s) => {
524
- s.forEach((i) => {
525
- !i._keepAlive && i._disposalState === _.ACTIVE && this.disposeBloc(i);
882
+ s.forEach((r) => {
883
+ !r._keepAlive && r._disposalState === y.ACTIVE && this.disposeBloc(r);
526
884
  });
527
- }), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), b.resetInstance();
885
+ }), this.blocInstanceMap.clear(), this.isolatedBlocMap.clear(), this.isolatedBlocIndex.clear(), S.resetInstance();
528
886
  });
529
887
  /**
530
888
  * Disposes of a bloc instance by removing it from the appropriate registry
531
889
  * @param bloc - The bloc instance to dispose
532
890
  */
533
- n(this, "disposeBloc", (e) => {
891
+ i(this, "disposeBloc", (e) => {
534
892
  const t = e._disposalState;
535
893
  if (![
536
- _.ACTIVE,
537
- _.DISPOSAL_REQUESTED
894
+ y.ACTIVE,
895
+ y.DISPOSAL_REQUESTED
538
896
  ].includes(t)) {
539
897
  this.log(
540
898
  `[${e._name}:${String(e._id)}] disposeBloc called on bloc in invalid state: ${t}`
541
899
  );
542
900
  return;
543
901
  }
544
- const i = e.constructor, r = this.createBlocInstanceMapKey(e._name, e._id);
902
+ const r = e.constructor, n = this.createBlocInstanceMapKey(e._name, e._id);
545
903
  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);
904
+ `[${e._name}:${String(e._id)}] disposeBloc called. Isolated: ${String(r.isolated)}`
905
+ ), e._dispose(), this.plugins.notifyBlocDisposed(e), r.isolated ? (this.unregisterIsolatedBlocInstance(e), this.blocInstanceMap.delete(n)) : this.unregisterBlocInstance(e), this.log("dispatched bloc", e);
548
906
  });
549
- n(this, "activateBloc", (e) => {
550
- if (e._disposalState !== _.ACTIVE) {
907
+ i(this, "activateBloc", (e) => {
908
+ if (e._disposalState !== y.ACTIVE) {
551
909
  this.log(
552
910
  `[${e._name}:${String(e._id)}] activateBloc called on disposed bloc. Ignoring.`
553
911
  );
@@ -569,16 +927,16 @@ const c = class c {
569
927
  * - instanceRef: Optional reference string for the instance
570
928
  * @returns The bloc instance
571
929
  */
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:`, {
930
+ i(this, "getBloc", (e, t = {}) => {
931
+ const { id: s, forceNewInstance: r } = t, n = e, o = s ?? e.name;
932
+ if (this.log(`[${e.name}:${String(o)}] (getBloc) Called:`, {
575
933
  options: t,
576
- base: r
577
- }), !i)
578
- if (r.isolated) {
934
+ base: n
935
+ }), !r)
936
+ if (n.isolated) {
579
937
  const l = this.findIsolatedBlocInstance(
580
938
  e,
581
- t.instanceRef ?? a
939
+ t.instanceRef ?? o
582
940
  );
583
941
  if (l)
584
942
  return l;
@@ -587,23 +945,23 @@ const c = class c {
587
945
  } else {
588
946
  const l = this.findRegisteredBlocInstance(
589
947
  e,
590
- a
948
+ o
591
949
  );
592
950
  if (l)
593
951
  return l;
594
952
  if (t.throwIfNotFound)
595
953
  throw new Error(`Registered bloc ${e.name} not found`);
596
954
  }
597
- const o = this.createNewBlocInstance(e, a, t);
955
+ const a = this.createNewBlocInstance(e, o, t);
598
956
  if (this.log(
599
- `[${e.name}:${String(a)}] (getBloc) No existing instance found. Creating new one.`,
957
+ `[${e.name}:${String(o)}] (getBloc) No existing instance found. Creating new one.`,
600
958
  t,
601
- o
602
- ), !o)
959
+ a
960
+ ), !a)
603
961
  throw new Error(
604
962
  `[getBloc] Failed to create bloc instance for ${e.name}. This should never happen.`
605
963
  );
606
- return o;
964
+ return a;
607
965
  });
608
966
  /**
609
967
  * Gets a bloc instance or throws an error if it doesn't exist
@@ -613,10 +971,10 @@ const c = class c {
613
971
  * - props: Properties to pass to the bloc constructor
614
972
  * - instanceRef: Optional reference string for the instance
615
973
  */
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;
974
+ i(this, "getBlocOrThrow", (e, t = {}) => {
975
+ const s = e.isolated, r = t.id || e.name, n = s ? this.findIsolatedBlocInstance(e, r) : this.findRegisteredBlocInstance(e, r);
976
+ if (n)
977
+ return n;
620
978
  throw new Error(`Bloc ${e.name} not found`);
621
979
  });
622
980
  /**
@@ -626,13 +984,13 @@ const c = class c {
626
984
  * - searchIsolated: Whether to search in isolated blocs (defaults to bloc's isolated property)
627
985
  * @returns Array of matching bloc instances
628
986
  */
629
- n(this, "getAllBlocs", (e, t = {}) => {
987
+ i(this, "getAllBlocs", (e, t = {}) => {
630
988
  const s = [];
631
- if (this.blocInstanceMap.forEach((i) => {
632
- i.constructor === e && s.push(i);
989
+ if (this.blocInstanceMap.forEach((r) => {
990
+ r.constructor === e && s.push(r);
633
991
  }), t.searchIsolated !== !1) {
634
- const i = this.isolatedBlocMap.get(e);
635
- i && s.push(...i.map((r) => r));
992
+ const r = this.isolatedBlocMap.get(e);
993
+ r && s.push(...r.map((n) => n));
636
994
  }
637
995
  return s;
638
996
  });
@@ -640,7 +998,7 @@ const c = class c {
640
998
  * Disposes all keep-alive blocs of a specific type
641
999
  * @param blocClass - The bloc class to dispose
642
1000
  */
643
- n(this, "disposeKeepAliveBlocs", (e) => {
1001
+ i(this, "disposeKeepAliveBlocs", (e) => {
644
1002
  const t = [];
645
1003
  for (const s of this.keepAliveBlocs)
646
1004
  (!e || s.constructor === e) && t.push(s);
@@ -650,19 +1008,19 @@ const c = class c {
650
1008
  * Disposes all blocs matching a pattern
651
1009
  * @param predicate - Function to test each bloc for disposal
652
1010
  */
653
- n(this, "disposeBlocs", (e) => {
1011
+ i(this, "disposeBlocs", (e) => {
654
1012
  const t = [];
655
1013
  for (const s of this.blocInstanceMap.values())
656
1014
  e(s) && t.push(s);
657
1015
  for (const s of this.isolatedBlocMap.values())
658
- for (const i of s)
659
- e(i) && t.push(i);
1016
+ for (const r of s)
1017
+ e(r) && t.push(r);
660
1018
  t.forEach((s) => s._dispose());
661
1019
  });
662
1020
  /**
663
1021
  * Gets memory usage statistics for debugging
664
1022
  */
665
- n(this, "getMemoryStats", () => ({
1023
+ i(this, "getMemoryStats", () => ({
666
1024
  totalBlocs: this.uidRegistry.size,
667
1025
  registeredBlocs: this.blocInstanceMap.size,
668
1026
  isolatedBlocs: Array.from(this.isolatedBlocMap.values()).reduce(
@@ -675,41 +1033,60 @@ const c = class c {
675
1033
  /**
676
1034
  * Validates consumer references and cleans up orphaned consumers
677
1035
  */
678
- n(this, "validateConsumers", () => {
1036
+ i(this, "validateConsumers", () => {
679
1037
  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);
1038
+ e._validateConsumers(), e._consumers.size === 0 && !e._keepAlive && e._disposalState === y.ACTIVE && setTimeout(() => {
1039
+ e._consumers.size === 0 && !e._keepAlive && e._disposalState === y.ACTIVE && this.disposeBloc(e);
682
1040
  }, 1e3);
683
1041
  });
684
1042
  const { __unsafe_ignore_singleton: t = !1 } = e;
685
1043
  if (!t)
686
- return c.instance;
687
- b.setInstance(this);
1044
+ return h.instance;
1045
+ S.setInstance(this), this.plugins.bootstrap();
688
1046
  }
689
1047
  static get instance() {
690
- return b.getInstance();
1048
+ return S.getInstance();
691
1049
  }
692
1050
  static get getAllBlocs() {
693
- return c.instance.getAllBlocs;
1051
+ return h.instance.getAllBlocs;
1052
+ }
1053
+ /** Get current configuration */
1054
+ static get config() {
1055
+ return { ...this._config };
1056
+ }
1057
+ /**
1058
+ * Set or update Blac configuration
1059
+ * @param config - Partial configuration to merge with existing config
1060
+ * @throws Error if configuration is invalid
1061
+ */
1062
+ static setConfig(e) {
1063
+ if (e.proxyDependencyTracking !== void 0 && typeof e.proxyDependencyTracking != "boolean")
1064
+ throw new Error("BlacConfig.proxyDependencyTracking must be a boolean");
1065
+ if (e.exposeBlacInstance !== void 0 && typeof e.exposeBlacInstance != "boolean")
1066
+ throw new Error("BlacConfig.exposeBlacInstance must be a boolean");
1067
+ this._config = {
1068
+ ...this._config,
1069
+ ...e
1070
+ }, this.enableLog && this.instance.log("Blac config updated:", this._config);
694
1071
  }
695
1072
  static get log() {
696
- return c.instance.log;
1073
+ return h.instance.log;
697
1074
  }
698
1075
  /**
699
1076
  * Gets the current Blac instance
700
1077
  * @returns The Blac instance
701
1078
  */
702
1079
  static getInstance() {
703
- return b.getInstance();
1080
+ return S.getInstance();
704
1081
  }
705
1082
  static get warn() {
706
- return c.instance.warn;
1083
+ return h.instance.warn;
707
1084
  }
708
1085
  static get error() {
709
- return c.instance.error;
1086
+ return h.instance.error;
710
1087
  }
711
1088
  static get disposeBloc() {
712
- return c.instance.disposeBloc;
1089
+ return h.instance.disposeBloc;
713
1090
  }
714
1091
  /**
715
1092
  * Creates a unique key for a bloc instance in the map based on the bloc class name and instance ID
@@ -744,8 +1121,8 @@ const c = class c {
744
1121
  */
745
1122
  findRegisteredBlocInstance(e, t) {
746
1123
  if (e.isolated) return;
747
- const i = this.createBlocInstanceMapKey(e.name, t);
748
- return this.blocInstanceMap.get(i);
1124
+ const r = this.createBlocInstanceMapKey(e.name, t);
1125
+ return this.blocInstanceMap.get(r);
749
1126
  }
750
1127
  /**
751
1128
  * Registers an isolated bloc instance in the isolated registry
@@ -761,14 +1138,14 @@ const c = class c {
761
1138
  */
762
1139
  unregisterIsolatedBlocInstance(e) {
763
1140
  const t = e.constructor, s = this.isolatedBlocMap.get(t);
764
- let i = !1;
1141
+ let r = !1;
765
1142
  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);
1143
+ const o = s.findIndex((a) => a.uid === e.uid);
1144
+ o !== -1 && (s.splice(o, 1), r = !0), s.length === 0 && this.isolatedBlocMap.delete(t);
768
1145
  }
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}`
1146
+ const n = this.isolatedBlocIndex.delete(e.uid);
1147
+ this.uidRegistry.delete(e.uid), this.keepAliveBlocs.delete(e), r !== n && this.warn(
1148
+ `[Blac] Inconsistent state detected during isolated bloc cleanup for ${e._name}:${e.uid}. Map removal: ${r}, Index removal: ${n}`
772
1149
  );
773
1150
  }
774
1151
  /**
@@ -776,8 +1153,8 @@ const c = class c {
776
1153
  */
777
1154
  findIsolatedBlocInstance(e, t) {
778
1155
  if (!e.isolated) return;
779
- const i = this.isolatedBlocMap.get(e);
780
- return i ? i.find((a) => a._id === t) : void 0;
1156
+ const r = this.isolatedBlocMap.get(e);
1157
+ return r ? r.find((o) => o._id === t) : void 0;
781
1158
  }
782
1159
  /**
783
1160
  * Finds an isolated bloc instance by UID (O(1) lookup)
@@ -794,60 +1171,91 @@ const c = class c {
794
1171
  * @returns The newly created bloc instance
795
1172
  */
796
1173
  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);
1174
+ const { props: r, instanceRef: n } = s, o = new e(r);
1175
+ return o._instanceRef = n, o.props = r || null, o._updateId(t), o._setDisposalHandler((a) => this.disposeBloc(a)), o.isIsolated ? this.registerIsolatedBlocInstance(o) : this.registerBlocInstance(o), o._activatePlugins(), this.plugins.notifyBlocCreated(o), o;
799
1176
  }
800
1177
  static get activateBloc() {
801
- return c.instance.activateBloc;
1178
+ return h.instance.activateBloc;
802
1179
  }
803
1180
  static get getBloc() {
804
- return c.instance.getBloc;
1181
+ return h.instance.getBloc;
805
1182
  }
806
1183
  static get getBlocOrThrow() {
807
- return c.instance.getBlocOrThrow;
1184
+ return h.instance.getBlocOrThrow;
808
1185
  }
809
1186
  static get disposeKeepAliveBlocs() {
810
- return c.instance.disposeKeepAliveBlocs;
1187
+ return h.instance.disposeKeepAliveBlocs;
811
1188
  }
812
1189
  static get disposeBlocs() {
813
- return c.instance.disposeBlocs;
1190
+ return h.instance.disposeBlocs;
814
1191
  }
815
1192
  static get getMemoryStats() {
816
- return c.instance.getMemoryStats;
1193
+ return h.instance.getMemoryStats;
817
1194
  }
818
1195
  static get validateConsumers() {
819
- return c.instance.validateConsumers;
1196
+ return h.instance.validateConsumers;
1197
+ }
1198
+ /**
1199
+ * Bootstrap the Blac instance and all plugins
1200
+ */
1201
+ bootstrap() {
1202
+ this.plugins.bootstrap();
1203
+ }
1204
+ /**
1205
+ * Shutdown the Blac instance and all plugins
1206
+ */
1207
+ shutdown() {
1208
+ this.plugins.shutdown();
1209
+ for (const e of this.blocInstanceMap.values())
1210
+ e._keepAlive || this.disposeBloc(e);
1211
+ for (const e of this.isolatedBlocMap.values())
1212
+ for (const t of e)
1213
+ t._keepAlive || this.disposeBloc(t);
820
1214
  }
821
1215
  };
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();
1216
+ /** Private static configuration */
1217
+ i(h, "_config", {
1218
+ exposeBlacInstance: !1,
1219
+ proxyDependencyTracking: !0
1220
+ }), /** Flag to enable/disable logging */
1221
+ i(h, "enableLog", !1), i(h, "logLevel", "warn"), i(h, "logSpy", null), i(h, "resetInstance", () => {
1222
+ S.resetInstance();
825
1223
  });
826
- let f = c;
827
- class O extends k {
1224
+ let u = h;
1225
+ class j extends k {
828
1226
  constructor() {
829
1227
  super(...arguments);
830
- // Stores handlers: Map<EventConstructor (subtype of A), HandlerFunction>
831
- // The handler's event parameter will be correctly typed to the specific EventConstructor
832
- // by the 'on' method's signature.
833
- n(this, "eventHandlers", /* @__PURE__ */ new Map());
1228
+ i(this, "eventHandlers", /* @__PURE__ */ new Map());
834
1229
  /**
835
1230
  * @internal
836
1231
  * Event queue to ensure sequential processing of async events
837
1232
  */
838
- n(this, "_eventQueue", []);
1233
+ i(this, "_eventQueue", []);
839
1234
  /**
840
1235
  * @internal
841
1236
  * Flag indicating if an event is currently being processed
842
1237
  */
843
- n(this, "_isProcessingEvent", !1);
1238
+ i(this, "_isProcessingEvent", !1);
844
1239
  /**
845
1240
  * Dispatches an action/event to the Bloc.
846
1241
  * Events are queued and processed sequentially to prevent race conditions.
847
1242
  * @param action The action/event instance to be processed.
848
1243
  */
849
- n(this, "add", async (t) => {
850
- this._eventQueue.push(t), this._isProcessingEvent || await this._processEventQueue();
1244
+ i(this, "add", async (t) => {
1245
+ let s = t;
1246
+ try {
1247
+ s = this._plugins.transformEvent(t);
1248
+ } catch (r) {
1249
+ console.error("Error transforming event:", r);
1250
+ }
1251
+ if (s !== null) {
1252
+ try {
1253
+ this._plugins.notifyEvent(s);
1254
+ } catch (r) {
1255
+ console.error("Error notifying plugins of event:", r);
1256
+ }
1257
+ u.instance.plugins.notifyEventAdded(this, s), this._eventQueue.push(s), this._isProcessingEvent || await this._processEventQueue();
1258
+ }
851
1259
  });
852
1260
  }
853
1261
  /**
@@ -858,7 +1266,7 @@ class O extends k {
858
1266
  * The 'event' parameter in the handler will be typed to the specific eventConstructor.
859
1267
  */
860
1268
  on(t, s) {
861
- this.eventHandlers.has(t) && f.warn(
1269
+ this.eventHandlers.has(t) && u.warn(
862
1270
  `[Bloc ${this._name}:${String(this._id)}] Handler for event '${t.name}' already registered. It will be overwritten.`
863
1271
  ), this.eventHandlers.set(
864
1272
  t,
@@ -887,44 +1295,67 @@ class O extends k {
887
1295
  * Processes a single event
888
1296
  */
889
1297
  async _processEvent(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);
1298
+ const s = t.constructor, r = this.eventHandlers.get(s);
1299
+ if (r) {
1300
+ const n = (o) => {
1301
+ const a = this.state;
1302
+ this._pushState(o, a, t);
895
1303
  };
896
1304
  try {
897
- await i(t, r);
898
- } catch (a) {
899
- const o = t.constructor.name || "UnnamedConstructor", l = {
1305
+ await r(t, n);
1306
+ } catch (o) {
1307
+ const a = t.constructor.name || "UnnamedConstructor", l = {
900
1308
  blocName: this._name,
901
1309
  blocId: String(this._id),
902
- eventType: o,
1310
+ eventType: a,
903
1311
  currentState: this.state,
904
1312
  action: t,
905
1313
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
906
1314
  };
907
- if (f.error(
908
- `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${o}':`,
909
- a,
1315
+ if (u.error(
1316
+ `[Bloc ${this._name}:${String(this._id)}] Error in event handler for '${a}':`,
1317
+ o,
910
1318
  "Context:",
911
1319
  l
912
- ), a instanceof Error && a.name === "CriticalError")
913
- throw a;
1320
+ ), o instanceof Error)
1321
+ try {
1322
+ this._plugins.notifyError(o, {
1323
+ phase: "event-processing",
1324
+ operation: "handler",
1325
+ metadata: { event: t }
1326
+ }), u.instance.plugins.notifyError(o, this, {
1327
+ phase: "event-processing",
1328
+ operation: "handler",
1329
+ metadata: { event: t }
1330
+ });
1331
+ } catch (d) {
1332
+ console.error("Error notifying plugins:", d);
1333
+ }
1334
+ if (o instanceof Error && o.name === "CriticalError")
1335
+ throw o;
914
1336
  }
915
1337
  } else {
916
- const r = t.constructor.name || "UnnamedConstructor";
917
- f.warn(
918
- `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${r}'.`,
1338
+ const n = t.constructor.name || "UnnamedConstructor";
1339
+ u.warn(
1340
+ `[Bloc ${this._name}:${String(this._id)}] No handler registered for action type: '${n}'.`,
919
1341
  "Registered handlers:",
920
- Array.from(this.eventHandlers.keys()).map((a) => a.name),
1342
+ Array.from(this.eventHandlers.keys()).map((o) => o.name),
921
1343
  "Action was:",
922
1344
  t
923
1345
  );
924
1346
  }
925
1347
  }
926
1348
  }
927
- class V extends k {
1349
+ class z extends k {
1350
+ /**
1351
+ * @internal
1352
+ * Protected method for useBloc to call
1353
+ */
1354
+ _updateProps(e) {
1355
+ var s;
1356
+ const t = this.props;
1357
+ this.props = e, (s = this.onPropsChanged) == null || s.call(this, t, e);
1358
+ }
928
1359
  /**
929
1360
  * Updates the current state and notifies all observers of the change.
930
1361
  * If the new state is identical to the current state (using Object.is),
@@ -947,7 +1378,7 @@ class V extends k {
947
1378
  */
948
1379
  patch(e, t = !1) {
949
1380
  if (typeof this.state != "object" || this.state === null) {
950
- f.warn(
1381
+ u.warn(
951
1382
  "Cubit.patch: was called on a cubit where the state is not an object. This is a no-op."
952
1383
  );
953
1384
  return;
@@ -956,10 +1387,10 @@ class V extends k {
956
1387
  if (t)
957
1388
  s = !0;
958
1389
  else
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)) {
1390
+ for (const r in e)
1391
+ if (Object.prototype.hasOwnProperty.call(e, r)) {
1392
+ const o = this.state[r];
1393
+ if (!Object.is(e[r], o)) {
963
1394
  s = !0;
964
1395
  break;
965
1396
  }
@@ -970,86 +1401,106 @@ class V extends k {
970
1401
  });
971
1402
  }
972
1403
  }
973
- class U {
1404
+ class L {
1405
+ constructor(e) {
1406
+ this.props = e;
1407
+ }
1408
+ }
1409
+ function N(c, e) {
1410
+ if (Object.is(c, e))
1411
+ return !0;
1412
+ if (typeof c != "object" || c === null || typeof e != "object" || e === null)
1413
+ return !1;
1414
+ const t = Object.keys(c), s = Object.keys(e);
1415
+ if (t.length !== s.length)
1416
+ return !1;
1417
+ for (let r = 0; r < t.length; r++) {
1418
+ const n = t[r];
1419
+ if (!Object.prototype.hasOwnProperty.call(e, n) || !Object.is(c[n], e[n]))
1420
+ return !1;
1421
+ }
1422
+ return !0;
1423
+ }
1424
+ class q {
974
1425
  /**
975
1426
  * Sets up a clean test environment
976
1427
  */
977
1428
  static setUp() {
978
- this.originalInstance = f.instance, f.resetInstance(), f.enableLog = !1;
1429
+ this.originalInstance = u.instance, u.resetInstance(), u.enableLog = !1;
979
1430
  }
980
1431
  /**
981
1432
  * Tears down the test environment and restores original state
982
1433
  */
983
1434
  static tearDown() {
984
- f.resetInstance();
1435
+ u.resetInstance();
985
1436
  }
986
1437
  /**
987
1438
  * Creates a test bloc with automatic cleanup
988
1439
  */
989
1440
  static createBloc(e, ...t) {
990
1441
  const s = new e(...t);
991
- return f.activateBloc(s), s;
1442
+ return u.activateBloc(s), s;
992
1443
  }
993
1444
  /**
994
1445
  * Waits for a bloc to emit a specific state
995
1446
  */
996
1447
  static async waitForState(e, t, s = 5e3) {
997
- return new Promise((i, r) => {
998
- const a = setTimeout(() => {
999
- r(
1448
+ return new Promise((r, n) => {
1449
+ const o = setTimeout(() => {
1450
+ n(
1000
1451
  new Error(
1001
1452
  `Timeout waiting for state matching predicate after ${s}ms`
1002
1453
  )
1003
1454
  );
1004
- }, s), o = e._observer.subscribe({
1455
+ }, s), a = e._observer.subscribe({
1005
1456
  id: `test-waiter-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
1006
1457
  fn: (l) => {
1007
- t(l) && (clearTimeout(a), o(), i(l));
1458
+ t(l) && (clearTimeout(o), a(), r(l));
1008
1459
  }
1009
1460
  });
1010
- t(e.state) && (clearTimeout(a), o(), i(e.state));
1461
+ t(e.state) && (clearTimeout(o), a(), r(e.state));
1011
1462
  });
1012
1463
  }
1013
1464
  /**
1014
1465
  * Expects a bloc to emit specific states in order
1015
1466
  */
1016
1467
  static async expectStates(e, t, s = 5e3) {
1017
- const i = [];
1018
- return new Promise((r, a) => {
1019
- const o = setTimeout(() => {
1020
- a(
1468
+ const r = [];
1469
+ return new Promise((n, o) => {
1470
+ const a = setTimeout(() => {
1471
+ o(
1021
1472
  new Error(
1022
- `Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(i)}`
1473
+ `Timeout waiting for states. Expected: ${JSON.stringify(t)}, Received: ${JSON.stringify(r)}`
1023
1474
  )
1024
1475
  );
1025
1476
  }, s), l = e._observer.subscribe({
1026
1477
  id: `test-expecter-${crypto.randomUUID()}`,
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];
1478
+ fn: (d) => {
1479
+ if (r.push(d), r.length === t.length) {
1480
+ clearTimeout(a), l();
1481
+ for (let f = 0; f < t.length; f++) {
1482
+ const m = t[f], v = r[f];
1032
1483
  if (JSON.stringify(m) !== JSON.stringify(v)) {
1033
- a(
1484
+ o(
1034
1485
  new Error(
1035
- `State mismatch at index ${d}. Expected: ${JSON.stringify(m)}, Received: ${JSON.stringify(v)}`
1486
+ `State mismatch at index ${f}. Expected: ${JSON.stringify(m)}, Received: ${JSON.stringify(v)}`
1036
1487
  )
1037
1488
  );
1038
1489
  return;
1039
1490
  }
1040
1491
  }
1041
- r();
1492
+ n();
1042
1493
  }
1043
1494
  }
1044
1495
  });
1045
1496
  });
1046
1497
  }
1047
1498
  }
1048
- n(U, "originalInstance");
1049
- class z extends O {
1499
+ i(q, "originalInstance");
1500
+ class F extends j {
1050
1501
  constructor(t) {
1051
1502
  super(t);
1052
- n(this, "mockHandlers", /* @__PURE__ */ new Map());
1503
+ i(this, "mockHandlers", /* @__PURE__ */ new Map());
1053
1504
  }
1054
1505
  /**
1055
1506
  * Mock an event handler for testing
@@ -1070,10 +1521,10 @@ class z extends O {
1070
1521
  return this.eventHandlers.has(t);
1071
1522
  }
1072
1523
  }
1073
- class j extends V {
1524
+ class G extends z {
1074
1525
  constructor(t) {
1075
1526
  super(t);
1076
- n(this, "stateHistory", []);
1527
+ i(this, "stateHistory", []);
1077
1528
  this.stateHistory.push(t);
1078
1529
  }
1079
1530
  /**
@@ -1095,16 +1546,16 @@ class j extends V {
1095
1546
  this.stateHistory = [this.state];
1096
1547
  }
1097
1548
  }
1098
- class K {
1549
+ class J {
1099
1550
  constructor() {
1100
- n(this, "initialStats");
1101
- this.initialStats = f.getMemoryStats();
1551
+ i(this, "initialStats");
1552
+ this.initialStats = u.getMemoryStats();
1102
1553
  }
1103
1554
  /**
1104
1555
  * Check for memory leaks and return a report
1105
1556
  */
1106
1557
  checkForLeaks() {
1107
- const e = f.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
1558
+ const e = u.getMemoryStats(), t = e.registeredBlocs > this.initialStats.registeredBlocs || e.isolatedBlocs > this.initialStats.isolatedBlocs || e.keepAliveBlocs > this.initialStats.keepAliveBlocs, s = `
1108
1559
  Memory Leak Detection Report:
1109
1560
  - Initial registered blocs: ${this.initialStats.registeredBlocs}
1110
1561
  - Current registered blocs: ${e.registeredBlocs}
@@ -1121,11 +1572,11 @@ Memory Leak Detection Report:
1121
1572
  };
1122
1573
  }
1123
1574
  }
1124
- class H {
1575
+ class K {
1125
1576
  constructor() {
1126
- n(this, "consumers", /* @__PURE__ */ new WeakMap());
1127
- n(this, "registrationCount", 0);
1128
- n(this, "activeConsumers", 0);
1577
+ i(this, "consumers", /* @__PURE__ */ new WeakMap());
1578
+ i(this, "registrationCount", 0);
1579
+ i(this, "activeConsumers", 0);
1129
1580
  }
1130
1581
  register(e, t) {
1131
1582
  this.registrationCount++, this.consumers.get(e) || this.activeConsumers++, this.consumers.set(e, {
@@ -1144,11 +1595,11 @@ class H {
1144
1595
  unregister(e) {
1145
1596
  e && this.consumers.get(e) && (this.consumers.delete(e), this.activeConsumers = Math.max(0, this.activeConsumers - 1));
1146
1597
  }
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 }));
1598
+ trackAccess(e, t, s, r) {
1599
+ const n = this.consumers.get(e);
1600
+ if (!n) return;
1601
+ const o = Date.now();
1602
+ n.firstAccessTime || (n.firstAccessTime = o), n.accessCount++, n.lastAccessTime = o, t === "state" ? (n.stateAccesses.add(s), r !== void 0 && n.stateValues.set(s, { value: r, lastAccessTime: o })) : (n.classAccesses.add(s), r !== void 0 && n.classValues.set(s, { value: r, lastAccessTime: o }));
1152
1603
  }
1153
1604
  resetTracking(e) {
1154
1605
  const t = this.consumers.get(e);
@@ -1162,41 +1613,41 @@ class H {
1162
1613
  } : null;
1163
1614
  }
1164
1615
  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))
1616
+ const r = this.consumers.get(e);
1617
+ if (!r) return !0;
1618
+ let n = !1;
1619
+ const o = Date.now();
1620
+ if (r.stateValues.size === 0 && r.classValues.size === 0 && (r.stateAccesses.size > 0 || r.classAccesses.size > 0))
1170
1621
  return !0;
1171
- for (const [o, l] of i.stateValues)
1622
+ for (const [a, l] of r.stateValues)
1172
1623
  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);
1624
+ const d = this.getValueAtPath(t, a);
1625
+ d !== l.value && (r.stateValues.set(a, {
1626
+ value: d,
1627
+ lastAccessTime: o
1628
+ }), n = !0);
1178
1629
  } catch {
1179
- r = !0;
1630
+ n = !0;
1180
1631
  }
1181
- for (const [o, l] of i.classValues)
1632
+ for (const [a, l] of r.classValues)
1182
1633
  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);
1634
+ const d = this.getValueAtPath(s, a);
1635
+ d !== l.value && (r.classValues.set(a, {
1636
+ value: d,
1637
+ lastAccessTime: o
1638
+ }), n = !0);
1188
1639
  } catch {
1189
- r = !0;
1640
+ n = !0;
1190
1641
  }
1191
- return r;
1642
+ return n;
1192
1643
  }
1193
1644
  shouldNotifyConsumer(e, t) {
1194
1645
  const s = this.consumers.get(e);
1195
1646
  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 + "."))
1647
+ for (const r of t) {
1648
+ if (s.stateAccesses.has(r) || s.classAccesses.has(r)) return !0;
1649
+ for (const n of s.stateAccesses)
1650
+ if (r.startsWith(n + ".") || n.startsWith(r + "."))
1200
1651
  return !0;
1201
1652
  }
1202
1653
  return !1;
@@ -1223,16 +1674,16 @@ class H {
1223
1674
  }
1224
1675
  getValueAtPath(e, t) {
1225
1676
  const s = t.split(".");
1226
- let i = e;
1227
- for (const r of s) {
1228
- if (i == null) return;
1229
- i = i[r];
1677
+ let r = e;
1678
+ for (const n of s) {
1679
+ if (r == null) return;
1680
+ r = r[n];
1230
1681
  }
1231
- return i;
1682
+ return r;
1232
1683
  }
1233
1684
  }
1234
- const w = /* @__PURE__ */ new WeakMap();
1235
- let h = {
1685
+ const x = /* @__PURE__ */ new WeakMap();
1686
+ let p = {
1236
1687
  stateProxiesCreated: 0,
1237
1688
  classProxiesCreated: 0,
1238
1689
  cacheHits: 0,
@@ -1242,44 +1693,44 @@ let h = {
1242
1693
  totalProxiesCreated: 0,
1243
1694
  createdAt: Date.now()
1244
1695
  };
1245
- class y {
1696
+ class I {
1246
1697
  static createStateProxy(e) {
1247
- const { target: t, consumerRef: s, consumerTracker: i, path: r = "" } = e;
1248
- if (!s || !i || typeof t != "object" || t === null)
1698
+ const { target: t, consumerRef: s, consumerTracker: r, path: n = "" } = e;
1699
+ if (!s || !r || typeof t != "object" || t === null)
1249
1700
  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++;
1701
+ let o = x.get(t);
1702
+ o || (o = /* @__PURE__ */ new WeakMap(), x.set(t, o));
1703
+ const a = o.get(s);
1704
+ if (a)
1705
+ return p.cacheHits++, a;
1706
+ p.cacheMisses++;
1256
1707
  const l = {
1257
- get(d, m) {
1708
+ get(f, m) {
1258
1709
  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({
1710
+ return Reflect.get(f, m);
1711
+ const v = n ? `${n}.${m}` : m;
1712
+ p.propertyAccesses++;
1713
+ const g = Reflect.get(f, m), B = g && typeof g === "object" && g !== null ? void 0 : g;
1714
+ if (r.trackAccess(s, "state", v, B), g && typeof g == "object" && g !== null) {
1715
+ const w = Object.getPrototypeOf(g) === Object.prototype, T = Array.isArray(g);
1716
+ if (w || T)
1717
+ return p.nestedProxiesCreated++, I.createStateProxy({
1267
1718
  target: g,
1268
1719
  consumerRef: s,
1269
- consumerTracker: i,
1720
+ consumerTracker: r,
1270
1721
  path: v
1271
1722
  });
1272
1723
  }
1273
1724
  return g;
1274
1725
  },
1275
- has(d, m) {
1276
- return m in d;
1726
+ has(f, m) {
1727
+ return m in f;
1277
1728
  },
1278
- ownKeys(d) {
1279
- return Reflect.ownKeys(d);
1729
+ ownKeys(f) {
1730
+ return Reflect.ownKeys(f);
1280
1731
  },
1281
- getOwnPropertyDescriptor(d, m) {
1282
- return Reflect.getOwnPropertyDescriptor(d, m);
1732
+ getOwnPropertyDescriptor(f, m) {
1733
+ return Reflect.getOwnPropertyDescriptor(f, m);
1283
1734
  },
1284
1735
  set() {
1285
1736
  return !1;
@@ -1287,90 +1738,90 @@ class y {
1287
1738
  deleteProperty() {
1288
1739
  return !1;
1289
1740
  }
1290
- }, p = new Proxy(t, l);
1291
- return a.set(s, p), h.stateProxiesCreated++, h.totalProxiesCreated++, p;
1741
+ }, d = new Proxy(t, l);
1742
+ return o.set(s, d), p.stateProxiesCreated++, p.totalProxiesCreated++, d;
1292
1743
  }
1293
1744
  static createClassProxy(e) {
1294
- const { target: t, consumerRef: s, consumerTracker: i } = e;
1295
- if (!s || !i)
1745
+ const { target: t, consumerRef: s, consumerTracker: r } = e;
1746
+ if (!s || !r)
1296
1747
  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); ) {
1748
+ let n = x.get(t);
1749
+ n || (n = /* @__PURE__ */ new WeakMap(), x.set(t, n));
1750
+ const o = n.get(s);
1751
+ if (o)
1752
+ return p.cacheHits++, o;
1753
+ p.cacheMisses++;
1754
+ const a = {
1755
+ get(d, f) {
1756
+ const m = Reflect.get(d, f);
1757
+ let v = !1, g = d;
1758
+ const A = /* @__PURE__ */ new WeakSet(), P = 10;
1759
+ let B = 0;
1760
+ for (; g && !v && B < P && !A.has(g); ) {
1310
1761
  A.add(g);
1311
1762
  try {
1312
- const x = Object.getOwnPropertyDescriptor(
1763
+ const C = Object.getOwnPropertyDescriptor(
1313
1764
  g,
1314
- d
1765
+ f
1315
1766
  );
1316
- if (x && x.get) {
1767
+ if (C && C.get) {
1317
1768
  v = !0;
1318
1769
  break;
1319
1770
  }
1320
- g = Object.getPrototypeOf(g), S++;
1771
+ g = Object.getPrototypeOf(g), B++;
1321
1772
  } catch {
1322
1773
  break;
1323
1774
  }
1324
1775
  }
1325
1776
  if (!v)
1326
1777
  return m;
1327
- h.propertyAccesses++;
1328
- const B = m, $ = B !== null && typeof B != "object" ? B : void 0;
1329
- return i.trackAccess(
1778
+ p.propertyAccesses++;
1779
+ const w = m, M = w !== null && typeof w != "object" ? w : void 0;
1780
+ return r.trackAccess(
1330
1781
  s,
1331
1782
  "class",
1332
- String(d),
1333
- $
1783
+ String(f),
1784
+ M
1334
1785
  ), m;
1335
1786
  },
1336
- has(p, d) {
1337
- return d in p;
1787
+ has(d, f) {
1788
+ return f in d;
1338
1789
  },
1339
- ownKeys(p) {
1340
- return Reflect.ownKeys(p);
1790
+ ownKeys(d) {
1791
+ return Reflect.ownKeys(d);
1341
1792
  },
1342
- getOwnPropertyDescriptor(p, d) {
1343
- return Reflect.getOwnPropertyDescriptor(p, d);
1793
+ getOwnPropertyDescriptor(d, f) {
1794
+ return Reflect.getOwnPropertyDescriptor(d, f);
1344
1795
  }
1345
- }, l = new Proxy(t, o);
1346
- return r.set(s, l), h.classProxiesCreated++, h.totalProxiesCreated++, l;
1796
+ }, l = new Proxy(t, a);
1797
+ return n.set(s, l), p.classProxiesCreated++, p.totalProxiesCreated++, l;
1347
1798
  }
1348
1799
  static getProxyState(e) {
1349
- return y.createStateProxy({
1800
+ return I.createStateProxy({
1350
1801
  target: e.state,
1351
1802
  consumerRef: e.consumerRef,
1352
1803
  consumerTracker: e.consumerTracker
1353
1804
  });
1354
1805
  }
1355
1806
  static getProxyBlocInstance(e) {
1356
- return y.createClassProxy({
1807
+ return I.createClassProxy({
1357
1808
  target: e.blocInstance,
1358
1809
  consumerRef: e.consumerRef,
1359
1810
  consumerTracker: e.consumerTracker
1360
1811
  });
1361
1812
  }
1362
1813
  static getStats() {
1363
- const e = Date.now() - h.createdAt;
1814
+ const e = Date.now() - p.createdAt;
1364
1815
  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",
1816
+ ...p,
1817
+ totalProxies: p.stateProxiesCreated + p.classProxiesCreated,
1818
+ cacheEfficiency: p.cacheHits + p.cacheMisses > 0 ? `${(p.cacheHits / (p.cacheHits + p.cacheMisses) * 100).toFixed(1)}%` : "N/A",
1368
1819
  lifetime: `${e}ms`,
1369
- proxiesPerSecond: e > 0 ? (h.totalProxiesCreated / (e / 1e3)).toFixed(2) : "N/A"
1820
+ proxiesPerSecond: e > 0 ? (p.totalProxiesCreated / (e / 1e3)).toFixed(2) : "N/A"
1370
1821
  };
1371
1822
  }
1372
1823
  static resetStats() {
1373
- h = {
1824
+ p = {
1374
1825
  stateProxiesCreated: 0,
1375
1826
  classProxiesCreated: 0,
1376
1827
  cacheHits: 0,
@@ -1382,60 +1833,64 @@ class y {
1382
1833
  };
1383
1834
  }
1384
1835
  }
1385
- class q {
1836
+ const b = class b {
1386
1837
  constructor(e, t) {
1387
- n(this, "id", `consumer-${R()}`);
1388
- n(this, "blocConstructor");
1389
- n(this, "componentRef", { current: {} });
1390
- n(this, "blocInstance");
1838
+ i(this, "id", `consumer-${$()}`);
1839
+ i(this, "blocConstructor");
1840
+ i(this, "componentRef", { current: {} });
1841
+ i(this, "blocInstance");
1391
1842
  // Core components
1392
- n(this, "consumerTracker");
1393
- n(this, "unmountTime", 0);
1394
- n(this, "mountTime", 0);
1843
+ i(this, "consumerTracker");
1844
+ i(this, "lastProps");
1845
+ i(this, "unmountTime", 0);
1846
+ i(this, "mountTime", 0);
1395
1847
  // Dependency tracking
1396
- n(this, "dependencyValues");
1397
- n(this, "isUsingDependencies", !1);
1848
+ i(this, "dependencyValues");
1849
+ i(this, "isUsingDependencies", !1);
1398
1850
  // Lifecycle state
1399
- n(this, "hasMounted", !1);
1400
- n(this, "mountCount", 0);
1401
- n(this, "options");
1402
- n(this, "createStateProxy", (e) => y.createStateProxy({
1851
+ i(this, "hasMounted", !1);
1852
+ i(this, "mountCount", 0);
1853
+ i(this, "options");
1854
+ i(this, "createStateProxy", (e) => I.createStateProxy({
1403
1855
  target: e.target,
1404
1856
  consumerRef: this.componentRef.current,
1405
1857
  consumerTracker: this
1406
1858
  }));
1407
- n(this, "createClassProxy", (e) => y.createClassProxy({
1859
+ i(this, "createClassProxy", (e) => I.createClassProxy({
1408
1860
  target: e.target,
1409
1861
  consumerRef: this.componentRef.current,
1410
1862
  consumerTracker: this
1411
1863
  }));
1412
- n(this, "createSubscription", (e) => this.blocInstance._observer.subscribe({
1864
+ i(this, "createSubscription", (e) => this.blocInstance._observer.subscribe({
1413
1865
  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);
1866
+ fn: (s, r) => {
1867
+ var n;
1868
+ if (this.isUsingDependencies && ((n = this.options) != null && n.dependencies)) {
1869
+ const o = this.options.dependencies(this.blocInstance);
1418
1870
  if (!this.hasDependencyValuesChanged(
1419
1871
  this.dependencyValues,
1420
- a
1872
+ o
1421
1873
  ))
1422
1874
  return;
1423
- this.dependencyValues = a;
1424
- } else {
1425
- const a = this.consumerTracker.getConsumerInfo(
1875
+ this.dependencyValues = o;
1876
+ } else if (u.config.proxyDependencyTracking) {
1877
+ const o = this.consumerTracker.getConsumerInfo(
1426
1878
  this.componentRef.current
1427
1879
  );
1428
- if (a && a.hasRendered && !this.consumerTracker.hasValuesChanged(
1880
+ if (o && o.hasRendered && !this.consumerTracker.hasValuesChanged(
1429
1881
  this.componentRef.current,
1430
1882
  s,
1431
1883
  this.blocInstance
1432
1884
  ))
1433
1885
  return;
1886
+ } else {
1887
+ e.onChange();
1888
+ return;
1434
1889
  }
1435
1890
  e.onChange();
1436
1891
  }
1437
1892
  }));
1438
- n(this, "mount", () => {
1893
+ i(this, "mount", () => {
1439
1894
  var e, t;
1440
1895
  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
1896
  try {
@@ -1444,28 +1899,28 @@ class q {
1444
1899
  throw s;
1445
1900
  }
1446
1901
  });
1447
- n(this, "unmount", () => {
1902
+ i(this, "unmount", () => {
1448
1903
  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)
1904
+ if (this.unmountTime = Date.now(), this.consumerTracker.unregister(this.componentRef.current), this.blocInstance._removeConsumer(this.id), b.propsOwners.get(this.blocInstance) === this.id && b.propsOwners.delete(this.blocInstance), (e = this.options) != null && e.onUnmount)
1450
1905
  try {
1451
1906
  this.options.onUnmount(this.blocInstance);
1452
1907
  } catch {
1453
1908
  }
1454
1909
  });
1455
- n(this, "getProxyState", (e) => this.isUsingDependencies ? e : y.getProxyState({
1910
+ i(this, "getProxyState", (e) => this.isUsingDependencies || !u.config.proxyDependencyTracking ? e : I.getProxyState({
1456
1911
  state: e,
1457
1912
  consumerRef: this.componentRef.current,
1458
1913
  consumerTracker: this
1459
1914
  }));
1460
- n(this, "getProxyBlocInstance", () => this.isUsingDependencies ? this.blocInstance : y.getProxyBlocInstance({
1915
+ i(this, "getProxyBlocInstance", () => this.isUsingDependencies || !u.config.proxyDependencyTracking ? this.blocInstance : I.getProxyBlocInstance({
1461
1916
  blocInstance: this.blocInstance,
1462
1917
  consumerRef: this.componentRef.current,
1463
1918
  consumerTracker: this
1464
1919
  }));
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));
1920
+ this.options = t, this.blocConstructor = e.blocConstructor, this.componentRef = e.componentRef, this.isUsingDependencies = !!(t != null && t.dependencies), this.consumerTracker = new K(), 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);
1466
1921
  }
1467
- trackAccess(e, t, s, i) {
1468
- this.consumerTracker.trackAccess(e, t, s, i);
1922
+ trackAccess(e, t, s, r) {
1923
+ this.consumerTracker.trackAccess(e, t, s, r);
1469
1924
  }
1470
1925
  getConsumerDependencies(e) {
1471
1926
  return this.consumerTracker.getDependencies(e);
@@ -1482,7 +1937,7 @@ class q {
1482
1937
  }
1483
1938
  updateBlocInstance() {
1484
1939
  var e, t;
1485
- return this.blocInstance = f.instance.getBloc(this.blocConstructor, {
1940
+ return this.blocInstance = u.instance.getBloc(this.blocConstructor, {
1486
1941
  props: (e = this.options) == null ? void 0 : e.props,
1487
1942
  id: (t = this.options) == null ? void 0 : t.id,
1488
1943
  instanceRef: this.id
@@ -1492,6 +1947,16 @@ class q {
1492
1947
  get calledOnMount() {
1493
1948
  return this.hasMounted;
1494
1949
  }
1950
+ updateProps(e) {
1951
+ const t = this.blocInstance;
1952
+ if (b.propsOwners.has(t) || b.propsOwners.set(t, this.id), b.propsOwners.get(t) !== this.id) {
1953
+ u.warn(
1954
+ `[BlacAdapter] Attempted to set props on ${t.constructor.name} from non-owner adapter`
1955
+ );
1956
+ return;
1957
+ }
1958
+ t._disposalState === y.DISPOSED || t._disposalState === y.DISPOSING || N(this.lastProps, e) || ("add" in t && typeof t.add == "function" ? t.add(new L(e)) : "_updateProps" in t && typeof t._updateProps == "function" && t._updateProps(e), this.lastProps = e);
1959
+ }
1495
1960
  hasDependencyValuesChanged(e, t) {
1496
1961
  if (!e || e.length !== t.length) return !0;
1497
1962
  for (let s = 0; s < e.length; s++)
@@ -1499,22 +1964,29 @@ class q {
1499
1964
  return !0;
1500
1965
  return !1;
1501
1966
  }
1502
- }
1967
+ };
1968
+ // Props ownership tracking
1969
+ i(b, "propsOwners", /* @__PURE__ */ new WeakMap());
1970
+ let D = b;
1503
1971
  export {
1504
- f as Blac,
1505
- q as BlacAdapter,
1506
- E as BlacObservable,
1507
- O as Bloc,
1972
+ u as Blac,
1973
+ D as BlacAdapter,
1974
+ H as BlacObservable,
1975
+ j as Bloc,
1508
1976
  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
1977
+ y as BlocLifecycleState,
1978
+ V as BlocPluginRegistry,
1979
+ q as BlocTest,
1980
+ K as ConsumerTracker,
1981
+ z as Cubit,
1982
+ J as MemoryLeakDetector,
1983
+ F as MockBloc,
1984
+ G as MockCubit,
1985
+ L as PropsUpdated,
1986
+ I as ProxyFactory,
1987
+ U as SystemPluginRegistry,
1988
+ $ as generateUUID,
1989
+ W as setBlacInstanceManager,
1990
+ N as shallowEqual
1519
1991
  };
1520
1992
  //# sourceMappingURL=index.es.js.map