@buoy-gg/highlight-updates 2.1.12 → 2.1.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.
Files changed (64) hide show
  1. package/lib/commonjs/highlight-updates/HighlightUpdatesOverlay.js +1 -285
  2. package/lib/commonjs/highlight-updates/components/HighlightFilterView.js +1 -1371
  3. package/lib/commonjs/highlight-updates/components/HighlightUpdatesModal.js +1 -591
  4. package/lib/commonjs/highlight-updates/components/IdentifierBadge.js +1 -267
  5. package/lib/commonjs/highlight-updates/components/IsolatedRenderList.js +1 -178
  6. package/lib/commonjs/highlight-updates/components/ModalHeaderContent.js +1 -303
  7. package/lib/commonjs/highlight-updates/components/RenderCauseBadge.js +1 -500
  8. package/lib/commonjs/highlight-updates/components/RenderDetailView.js +1 -830
  9. package/lib/commonjs/highlight-updates/components/RenderHistoryViewer.js +1 -894
  10. package/lib/commonjs/highlight-updates/components/RenderListItem.js +1 -220
  11. package/lib/commonjs/highlight-updates/components/StatsDisplay.js +1 -70
  12. package/lib/commonjs/highlight-updates/components/index.js +1 -97
  13. package/lib/commonjs/highlight-updates/utils/HighlightUpdatesController.js +1 -1435
  14. package/lib/commonjs/highlight-updates/utils/PerformanceLogger.js +1 -359
  15. package/lib/commonjs/highlight-updates/utils/ProfilerInterceptor.js +1 -371
  16. package/lib/commonjs/highlight-updates/utils/RenderCauseDetector.js +1 -1828
  17. package/lib/commonjs/highlight-updates/utils/RenderTracker.js +1 -903
  18. package/lib/commonjs/highlight-updates/utils/ViewTypeMapper.js +1 -264
  19. package/lib/commonjs/highlight-updates/utils/renderExportFormatter.js +1 -58
  20. package/lib/commonjs/index.js +1 -311
  21. package/lib/commonjs/preset.js +1 -278
  22. package/lib/module/highlight-updates/HighlightUpdatesOverlay.js +1 -278
  23. package/lib/module/highlight-updates/components/HighlightFilterView.js +1 -1365
  24. package/lib/module/highlight-updates/components/HighlightUpdatesModal.js +1 -585
  25. package/lib/module/highlight-updates/components/IdentifierBadge.js +1 -259
  26. package/lib/module/highlight-updates/components/IsolatedRenderList.js +1 -174
  27. package/lib/module/highlight-updates/components/ModalHeaderContent.js +1 -298
  28. package/lib/module/highlight-updates/components/RenderCauseBadge.js +1 -491
  29. package/lib/module/highlight-updates/components/RenderDetailView.js +1 -826
  30. package/lib/module/highlight-updates/components/RenderHistoryViewer.js +1 -888
  31. package/lib/module/highlight-updates/components/RenderListItem.js +1 -215
  32. package/lib/module/highlight-updates/components/StatsDisplay.js +1 -67
  33. package/lib/module/highlight-updates/components/index.js +1 -16
  34. package/lib/module/highlight-updates/utils/HighlightUpdatesController.js +1 -1431
  35. package/lib/module/highlight-updates/utils/PerformanceLogger.js +1 -353
  36. package/lib/module/highlight-updates/utils/ProfilerInterceptor.js +1 -358
  37. package/lib/module/highlight-updates/utils/RenderCauseDetector.js +1 -1818
  38. package/lib/module/highlight-updates/utils/RenderTracker.js +1 -900
  39. package/lib/module/highlight-updates/utils/ViewTypeMapper.js +1 -255
  40. package/lib/module/highlight-updates/utils/renderExportFormatter.js +1 -54
  41. package/lib/module/index.js +1 -71
  42. package/lib/module/preset.js +1 -272
  43. package/package.json +7 -7
  44. package/lib/typescript/highlight-updates/HighlightUpdatesOverlay.d.ts.map +0 -1
  45. package/lib/typescript/highlight-updates/components/HighlightFilterView.d.ts.map +0 -1
  46. package/lib/typescript/highlight-updates/components/HighlightUpdatesModal.d.ts.map +0 -1
  47. package/lib/typescript/highlight-updates/components/IdentifierBadge.d.ts.map +0 -1
  48. package/lib/typescript/highlight-updates/components/IsolatedRenderList.d.ts.map +0 -1
  49. package/lib/typescript/highlight-updates/components/ModalHeaderContent.d.ts.map +0 -1
  50. package/lib/typescript/highlight-updates/components/RenderCauseBadge.d.ts.map +0 -1
  51. package/lib/typescript/highlight-updates/components/RenderDetailView.d.ts.map +0 -1
  52. package/lib/typescript/highlight-updates/components/RenderHistoryViewer.d.ts.map +0 -1
  53. package/lib/typescript/highlight-updates/components/RenderListItem.d.ts.map +0 -1
  54. package/lib/typescript/highlight-updates/components/StatsDisplay.d.ts.map +0 -1
  55. package/lib/typescript/highlight-updates/components/index.d.ts.map +0 -1
  56. package/lib/typescript/highlight-updates/utils/HighlightUpdatesController.d.ts.map +0 -1
  57. package/lib/typescript/highlight-updates/utils/PerformanceLogger.d.ts.map +0 -1
  58. package/lib/typescript/highlight-updates/utils/ProfilerInterceptor.d.ts.map +0 -1
  59. package/lib/typescript/highlight-updates/utils/RenderCauseDetector.d.ts.map +0 -1
  60. package/lib/typescript/highlight-updates/utils/RenderTracker.d.ts.map +0 -1
  61. package/lib/typescript/highlight-updates/utils/ViewTypeMapper.d.ts.map +0 -1
  62. package/lib/typescript/highlight-updates/utils/renderExportFormatter.d.ts.map +0 -1
  63. package/lib/typescript/index.d.ts.map +0 -1
  64. package/lib/typescript/preset.d.ts.map +0 -1
@@ -1,903 +1 @@
1
- /**
2
- * RenderTracker
3
- *
4
- * Singleton that tracks component render history for the Highlight Updates modal.
5
- * Stores information about each tracked component including render counts,
6
- * timestamps, and identifying props (testID, nativeID, etc.)
7
- */
8
-
9
- "use strict";
10
-
11
- Object.defineProperty(exports, "__esModule", {
12
- value: true
13
- });
14
- exports.default = exports.RenderTracker = void 0;
15
- var _ViewTypeMapper = require("./ViewTypeMapper");
16
- var _PerformanceLogger = require("./PerformanceLogger");
17
- /**
18
- * Debug logging levels for render cause detection.
19
- * Controls verbosity of console output for debugging "Why Did You Render" feature.
20
- *
21
- * - "off": No debug logging (default, best for production)
22
- * - "minimal": Only log state/hook value changes (e.g., "useState: 3334 → 3335")
23
- * - "verbose": Log component info + cause + value changes
24
- * - "all": Full fiber dump with everything (native fiber, component fiber, hooks, batch context)
25
- */
26
-
27
- // Render cause types - why did a component render?
28
-
29
- // Could not determine
30
-
31
- // Component-level cause - why did the React component re-render?
32
-
33
- // Could not determine
34
-
35
- /**
36
- * Represents a change in a single hook's state
37
- * Used to show meaningful before/after values for debugging
38
- */
39
-
40
- /**
41
- * A single render event in the history
42
- * Captures everything about one render occurrence
43
- */
44
-
45
- /** Callback for individual render events (for unified events integration) */
46
-
47
- // Maximum number of tracked components to prevent memory issues
48
- const MAX_TRACKED_COMPONENTS = 200;
49
-
50
- // Default batch size for highlight rendering
51
- const DEFAULT_BATCH_SIZE = 150;
52
- class RenderTrackerSingleton {
53
- renders = new Map();
54
- listeners = new Set();
55
- stateListeners = new Set();
56
- settingsListeners = new Set();
57
- filterListeners = new Set();
58
- /** Callbacks for individual render events (unified events integration) */
59
- renderEventCallbacks = new Set();
60
- isTracking = false;
61
- isPaused = false;
62
- settings = {
63
- batchSize: DEFAULT_BATCH_SIZE,
64
- showRenderCount: true,
65
- performanceLogging: false,
66
- trackRenderCauses: false,
67
- // History settings (always enabled)
68
- enableRenderHistory: true,
69
- maxRenderHistoryPerComponent: 20,
70
- capturePropsOnRender: false,
71
- captureStateOnRender: false,
72
- // Debug settings
73
- debugLogLevel: "off",
74
- // Dev tools visibility - exclude by default
75
- excludeDevTools: true
76
- };
77
-
78
- // Batch mode: defer notifyListeners until endBatch is called
79
- isBatchMode = false;
80
- batchDirty = false;
81
- filters = {
82
- includeTestID: new Set(),
83
- includeNativeID: new Set(),
84
- includeViewType: new Set(),
85
- includeComponent: new Set(),
86
- excludeTestID: new Set(),
87
- excludeNativeID: new Set(),
88
- excludeViewType: new Set(),
89
- excludeComponent: new Set(),
90
- includePatterns: [],
91
- excludePatterns: []
92
- };
93
-
94
- /**
95
- * Track a component render
96
- */
97
- trackRender(data) {
98
- if (this.isPaused) return;
99
- const id = String(data.nativeTag);
100
- const now = Date.now();
101
- const existing = this.renders.get(id);
102
- if (existing) {
103
- // Mutate in place to keep Map entry correct
104
- existing.renderCount = data.count;
105
- existing.lastRenderTime = now;
106
- existing.color = data.color;
107
- if (data.measurements) {
108
- existing.measurements = data.measurements;
109
- }
110
- // Update props if they weren't set before
111
- if (data.testID && !existing.testID) existing.testID = data.testID;
112
- if (data.nativeID && !existing.nativeID) existing.nativeID = data.nativeID;
113
- if (data.accessibilityLabel && !existing.accessibilityLabel) {
114
- existing.accessibilityLabel = data.accessibilityLabel;
115
- }
116
- if (data.componentName && !existing.componentName) {
117
- existing.componentName = data.componentName;
118
- }
119
- // Update render cause if provided
120
- if (data.renderCause) {
121
- existing.lastRenderCause = data.renderCause;
122
- }
123
-
124
- // Add to render history if enabled (create minimal cause if not provided)
125
- if (this.settings.enableRenderHistory) {
126
- const cause = data.renderCause || {
127
- type: "unknown",
128
- timestamp: now
129
- };
130
- this.addRenderEvent(existing, cause, data.capturedProps, data.capturedState);
131
- }
132
- } else {
133
- // Add new render
134
- const newRender = {
135
- id,
136
- nativeTag: data.nativeTag,
137
- viewType: data.viewType,
138
- displayName: (0, _ViewTypeMapper.getComponentDisplayName)(data.viewType),
139
- testID: data.testID,
140
- nativeID: data.nativeID,
141
- accessibilityLabel: data.accessibilityLabel,
142
- componentName: data.componentName,
143
- renderCount: data.count,
144
- firstRenderTime: now,
145
- lastRenderTime: now,
146
- measurements: data.measurements,
147
- color: data.color,
148
- lastRenderCause: data.renderCause
149
- };
150
-
151
- // Initialize render history if enabled (create minimal cause if not provided)
152
- if (this.settings.enableRenderHistory) {
153
- newRender.renderHistory = [];
154
- const cause = data.renderCause || {
155
- type: data.count === 1 ? "mount" : "unknown",
156
- timestamp: now
157
- };
158
- this.addRenderEvent(newRender, cause, data.capturedProps, data.capturedState);
159
- }
160
- this.renders.set(id, newRender);
161
-
162
- // Enforce max limit - remove oldest renders
163
- if (this.renders.size > MAX_TRACKED_COMPONENTS) {
164
- const sorted = Array.from(this.renders.values()).sort((a, b) => a.lastRenderTime - b.lastRenderTime);
165
- const toRemove = sorted.slice(0, this.renders.size - MAX_TRACKED_COMPONENTS);
166
- for (const render of toRemove) {
167
- this.renders.delete(render.id);
168
- }
169
- }
170
- }
171
-
172
- // In batch mode, defer notification until endBatch()
173
- if (this.isBatchMode) {
174
- this.batchDirty = true;
175
- } else {
176
- this.notifyListeners();
177
- }
178
- }
179
-
180
- /**
181
- * Add a render event to a component's history (circular buffer)
182
- */
183
- addRenderEvent(render, cause, capturedProps, capturedState) {
184
- // Initialize history array if needed
185
- if (!render.renderHistory) {
186
- render.renderHistory = [];
187
- }
188
- const event = {
189
- id: `${render.nativeTag}-${cause.timestamp}`,
190
- timestamp: cause.timestamp,
191
- cause,
192
- renderNumber: render.renderCount,
193
- // Only include captured data if settings allow and data is provided
194
- capturedProps: this.settings.capturePropsOnRender ? capturedProps : undefined,
195
- capturedState: this.settings.captureStateOnRender ? capturedState : undefined
196
- };
197
- render.renderHistory.push(event);
198
-
199
- // Enforce max history size (circular buffer behavior)
200
- const maxHistory = Math.max(5, Math.min(50, this.settings.maxRenderHistoryPerComponent));
201
- if (render.renderHistory.length > maxHistory) {
202
- // Remove oldest events
203
- render.renderHistory = render.renderHistory.slice(-maxHistory);
204
- }
205
-
206
- // Notify render event callbacks (for unified events integration)
207
- this.notifyRenderEventCallbacks(event, render);
208
- }
209
-
210
- /**
211
- * Notify all render event callbacks
212
- */
213
- notifyRenderEventCallbacks(event, render) {
214
- this.renderEventCallbacks.forEach(callback => {
215
- try {
216
- callback(event, render);
217
- } catch {
218
- // Silently ignore callback errors
219
- }
220
- });
221
- }
222
-
223
- /**
224
- * Emit a render event to callbacks only (without storing in the render list).
225
- * Used by Events tool when visual highlights are off - we want events but not list updates.
226
- */
227
- emitRenderEvent(data) {
228
- if (this.renderEventCallbacks.size === 0) return;
229
- const now = Date.now();
230
- const cause = data.renderCause || {
231
- type: "unknown",
232
- timestamp: now
233
- };
234
-
235
- // Create a minimal TrackedRender for the event (not stored)
236
- const render = {
237
- id: String(data.nativeTag),
238
- nativeTag: data.nativeTag,
239
- viewType: data.viewType,
240
- displayName: (0, _ViewTypeMapper.getComponentDisplayName)(data.viewType),
241
- testID: data.testID,
242
- nativeID: data.nativeID,
243
- accessibilityLabel: data.accessibilityLabel,
244
- componentName: data.componentName,
245
- renderCount: data.count,
246
- firstRenderTime: now,
247
- lastRenderTime: now,
248
- measurements: data.measurements,
249
- color: data.color,
250
- lastRenderCause: cause,
251
- renderHistory: []
252
- };
253
-
254
- // Create the event
255
- const event = {
256
- id: `${data.nativeTag}-${now}-${data.count}`,
257
- timestamp: now,
258
- renderNumber: data.count,
259
- cause,
260
- capturedProps: undefined,
261
- capturedState: undefined
262
- };
263
-
264
- // Notify callbacks only (no storage, no list listeners)
265
- this.notifyRenderEventCallbacks(event, render);
266
- }
267
-
268
- /**
269
- * Start batch mode - defers listener notifications until endBatch() is called.
270
- * Use this when tracking multiple renders in a loop to avoid O(n²) notifications.
271
- */
272
- startBatch() {
273
- this.isBatchMode = true;
274
- this.batchDirty = false;
275
- }
276
-
277
- /**
278
- * End batch mode and notify listeners if any renders were tracked.
279
- */
280
- endBatch() {
281
- this.isBatchMode = false;
282
- if (this.batchDirty) {
283
- this.batchDirty = false;
284
- this.notifyListeners();
285
- }
286
- }
287
-
288
- /**
289
- * Get all tracked renders
290
- * Creates new object copies to trigger React.memo re-renders
291
- */
292
- getRenders() {
293
- return Array.from(this.renders.values()).map(r => ({
294
- ...r
295
- }));
296
- }
297
-
298
- /**
299
- * Check if a component passes all active filters.
300
- * Used by both the modal list and the overlay to filter components.
301
- *
302
- * @param info Component info to check (can be TrackedRender or extracted component info)
303
- * @returns true if the component passes all filters, false if it should be hidden
304
- */
305
- passesFilters(info) {
306
- // Check new unified include patterns (if any are set, must match at least one)
307
- if (this.filters.includePatterns.length > 0) {
308
- const matchesInclude = this.matchesAnyPatternForInfo(info, this.filters.includePatterns);
309
- if (!matchesInclude) return false;
310
- }
311
-
312
- // Check new unified exclude patterns
313
- if (this.filters.excludePatterns.length > 0) {
314
- const matchesExclude = this.matchesAnyPatternForInfo(info, this.filters.excludePatterns);
315
- if (matchesExclude) return false;
316
- }
317
-
318
- // Legacy filter support (for backwards compatibility)
319
- // Include filters: if any are set, component must match at least one
320
- if (this.filters.includeViewType.size > 0) {
321
- const viewType = info.viewType || '';
322
- const displayName = info.displayName || '';
323
- if (!this.matchesPattern(viewType, this.filters.includeViewType) && !this.matchesPattern(displayName, this.filters.includeViewType)) {
324
- return false;
325
- }
326
- }
327
- if (this.filters.includeTestID.size > 0) {
328
- if (!info.testID || !this.matchesPattern(info.testID, this.filters.includeTestID)) {
329
- return false;
330
- }
331
- }
332
- if (this.filters.includeNativeID.size > 0) {
333
- if (!info.nativeID || !this.matchesPattern(info.nativeID, this.filters.includeNativeID)) {
334
- return false;
335
- }
336
- }
337
- if (this.filters.includeComponent.size > 0) {
338
- if (!info.componentName || !this.matchesPattern(info.componentName, this.filters.includeComponent)) {
339
- return false;
340
- }
341
- }
342
-
343
- // Exclude filters: if component matches any, it should be hidden
344
- if (this.filters.excludeViewType.size > 0) {
345
- const viewType = info.viewType || '';
346
- const displayName = info.displayName || '';
347
- if (this.matchesPattern(viewType, this.filters.excludeViewType) || this.matchesPattern(displayName, this.filters.excludeViewType)) {
348
- return false;
349
- }
350
- }
351
- if (this.filters.excludeTestID.size > 0) {
352
- if (info.testID && this.matchesPattern(info.testID, this.filters.excludeTestID)) {
353
- return false;
354
- }
355
- }
356
- if (this.filters.excludeNativeID.size > 0) {
357
- if (info.nativeID && this.matchesPattern(info.nativeID, this.filters.excludeNativeID)) {
358
- return false;
359
- }
360
- }
361
- if (this.filters.excludeComponent.size > 0) {
362
- if (info.componentName && this.matchesPattern(info.componentName, this.filters.excludeComponent)) {
363
- return false;
364
- }
365
- }
366
- return true;
367
- }
368
-
369
- /**
370
- * Check if component info matches any of the given patterns
371
- */
372
- matchesAnyPatternForInfo(info, patterns) {
373
- for (const pattern of patterns) {
374
- const lowerValue = pattern.value.toLowerCase();
375
- switch (pattern.type) {
376
- case "any":
377
- // Match against all fields
378
- if (info.viewType.toLowerCase().includes(lowerValue) || info.displayName?.toLowerCase().includes(lowerValue) || info.testID?.toLowerCase().includes(lowerValue) || info.nativeID?.toLowerCase().includes(lowerValue) || info.componentName?.toLowerCase().includes(lowerValue) || info.accessibilityLabel?.toLowerCase().includes(lowerValue)) {
379
- return true;
380
- }
381
- break;
382
- case "viewType":
383
- if (info.viewType.toLowerCase().includes(lowerValue) || info.displayName?.toLowerCase().includes(lowerValue)) {
384
- return true;
385
- }
386
- break;
387
- case "testID":
388
- if (info.testID?.toLowerCase().includes(lowerValue)) {
389
- return true;
390
- }
391
- break;
392
- case "nativeID":
393
- if (info.nativeID?.toLowerCase().includes(lowerValue)) {
394
- return true;
395
- }
396
- break;
397
- case "component":
398
- if (info.componentName?.toLowerCase().includes(lowerValue)) {
399
- return true;
400
- }
401
- break;
402
- case "accessibilityLabel":
403
- if (info.accessibilityLabel?.toLowerCase().includes(lowerValue)) {
404
- return true;
405
- }
406
- break;
407
- }
408
- }
409
- return false;
410
- }
411
-
412
- /**
413
- * Check if any filters are currently active
414
- */
415
- hasActiveFilters() {
416
- return this.filters.includePatterns.length > 0 || this.filters.excludePatterns.length > 0 || this.filters.includeViewType.size > 0 || this.filters.includeTestID.size > 0 || this.filters.includeNativeID.size > 0 || this.filters.includeComponent.size > 0 || this.filters.excludeViewType.size > 0 || this.filters.excludeTestID.size > 0 || this.filters.excludeNativeID.size > 0 || this.filters.excludeComponent.size > 0 || this.filters.minRenderCount !== undefined || this.filters.maxRenderCount !== undefined;
417
- }
418
-
419
- /**
420
- * Get filtered renders based on current filter config
421
- */
422
- getFilteredRenders(searchText = "") {
423
- let renders = this.getRenders();
424
-
425
- // Apply search filter
426
- if (searchText.trim()) {
427
- const search = searchText.toLowerCase();
428
- renders = renders.filter(r => {
429
- return r.viewType.toLowerCase().includes(search) || r.displayName.toLowerCase().includes(search) || r.testID?.toLowerCase().includes(search) || r.nativeID?.toLowerCase().includes(search) || r.accessibilityLabel?.toLowerCase().includes(search) || r.componentName?.toLowerCase().includes(search) || String(r.nativeTag).includes(search);
430
- });
431
- }
432
-
433
- // Apply filters using the shared passesFilters method
434
- renders = renders.filter(r => this.passesFilters(r));
435
-
436
- // Apply render count range filter
437
- if (this.filters.minRenderCount !== undefined) {
438
- renders = renders.filter(r => r.renderCount >= this.filters.minRenderCount);
439
- }
440
- if (this.filters.maxRenderCount !== undefined) {
441
- renders = renders.filter(r => r.renderCount <= this.filters.maxRenderCount);
442
- }
443
-
444
- // Sort by last render time (most recent first)
445
- return renders.sort((a, b) => b.lastRenderTime - a.lastRenderTime);
446
- }
447
-
448
- /**
449
- * Check if a value matches any pattern in the set
450
- */
451
- matchesPattern(value, patterns) {
452
- const lowerValue = value.toLowerCase();
453
- for (const pattern of patterns) {
454
- const lowerPattern = pattern.toLowerCase();
455
- if (lowerValue.includes(lowerPattern)) {
456
- return true;
457
- }
458
- }
459
- return false;
460
- }
461
-
462
- /**
463
- * Get a single render by id
464
- */
465
- getRender(id) {
466
- return this.renders.get(id);
467
- }
468
-
469
- /**
470
- * Clear all tracked renders
471
- */
472
- clear() {
473
- this.renders.clear();
474
- this.notifyListeners();
475
- }
476
-
477
- /**
478
- * Reset render count for a specific component
479
- */
480
- resetRenderCount(id) {
481
- const render = this.renders.get(id);
482
- if (render) {
483
- render.renderCount = 0;
484
- this.notifyListeners();
485
- }
486
- }
487
-
488
- /**
489
- * Start tracking
490
- */
491
- start() {
492
- this.isTracking = true;
493
- this.isPaused = false;
494
- this.notifyStateListeners();
495
- }
496
-
497
- /**
498
- * Stop tracking
499
- */
500
- stop() {
501
- this.isTracking = false;
502
- this.isPaused = false;
503
- this.notifyStateListeners();
504
- }
505
-
506
- /**
507
- * Pause tracking (keeps state but stops adding new renders)
508
- */
509
- pause() {
510
- this.isPaused = true;
511
- this.notifyStateListeners();
512
- }
513
-
514
- /**
515
- * Resume tracking
516
- */
517
- resume() {
518
- this.isPaused = false;
519
- this.notifyStateListeners();
520
- }
521
-
522
- /**
523
- * Toggle pause state
524
- */
525
- togglePause() {
526
- this.isPaused = !this.isPaused;
527
- this.notifyStateListeners();
528
- }
529
-
530
- /**
531
- * Get current tracking state
532
- */
533
- getState() {
534
- return {
535
- isTracking: this.isTracking,
536
- isPaused: this.isPaused
537
- };
538
- }
539
-
540
- /**
541
- * Get filter config
542
- */
543
- getFilters() {
544
- return this.filters;
545
- }
546
-
547
- /**
548
- * Update filter config
549
- */
550
- setFilters(filters) {
551
- this.filters = {
552
- ...this.filters,
553
- ...filters
554
- };
555
- this.notifyListeners();
556
- this.notifyFilterListeners();
557
- }
558
-
559
- /**
560
- * Add an include pattern
561
- */
562
- addIncludePattern(type, pattern) {
563
- const key = `include${type.charAt(0).toUpperCase() + type.slice(1)}`;
564
- this.filters[key].add(pattern);
565
- this.notifyListeners();
566
- }
567
-
568
- /**
569
- * Remove an include pattern
570
- */
571
- removeIncludePattern(type, pattern) {
572
- const key = `include${type.charAt(0).toUpperCase() + type.slice(1)}`;
573
- this.filters[key].delete(pattern);
574
- this.notifyListeners();
575
- }
576
-
577
- /**
578
- * Add an exclude pattern
579
- */
580
- addExcludePattern(type, pattern) {
581
- const key = `exclude${type.charAt(0).toUpperCase() + type.slice(1)}`;
582
- this.filters[key].add(pattern);
583
- this.notifyListeners();
584
- }
585
-
586
- /**
587
- * Remove an exclude pattern
588
- */
589
- removeExcludePattern(type, pattern) {
590
- const key = `exclude${type.charAt(0).toUpperCase() + type.slice(1)}`;
591
- this.filters[key].delete(pattern);
592
- this.notifyListeners();
593
- }
594
-
595
- /**
596
- * Clear all filters
597
- */
598
- clearFilters() {
599
- this.filters = {
600
- includeTestID: new Set(),
601
- includeNativeID: new Set(),
602
- includeViewType: new Set(),
603
- includeComponent: new Set(),
604
- excludeTestID: new Set(),
605
- excludeNativeID: new Set(),
606
- excludeViewType: new Set(),
607
- excludeComponent: new Set(),
608
- includePatterns: [],
609
- excludePatterns: [],
610
- minRenderCount: undefined,
611
- maxRenderCount: undefined
612
- };
613
- this.notifyListeners();
614
- }
615
-
616
- /**
617
- * Get available prop values from tracked renders
618
- */
619
- getAvailableProps() {
620
- const viewTypes = new Set();
621
- const testIDs = new Set();
622
- const nativeIDs = new Set();
623
- const componentNames = new Set();
624
- const accessibilityLabels = new Set();
625
- for (const render of this.renders.values()) {
626
- if (render.viewType) viewTypes.add(render.viewType);
627
- if (render.testID) testIDs.add(render.testID);
628
- if (render.nativeID) nativeIDs.add(render.nativeID);
629
- if (render.componentName) componentNames.add(render.componentName);
630
- if (render.accessibilityLabel) accessibilityLabels.add(render.accessibilityLabel);
631
- }
632
- return {
633
- viewTypes: Array.from(viewTypes).sort(),
634
- testIDs: Array.from(testIDs).sort(),
635
- nativeIDs: Array.from(nativeIDs).sort(),
636
- componentNames: Array.from(componentNames).sort(),
637
- accessibilityLabels: Array.from(accessibilityLabels).sort()
638
- };
639
- }
640
-
641
- /**
642
- * Get summary stats
643
- */
644
- getStats() {
645
- let totalRenders = 0;
646
- for (const render of this.renders.values()) {
647
- totalRenders += render.renderCount;
648
- }
649
- return {
650
- totalComponents: this.renders.size,
651
- totalRenders
652
- };
653
- }
654
-
655
- /**
656
- * Subscribe to render updates
657
- */
658
- subscribe(listener) {
659
- this.listeners.add(listener);
660
- // Immediately notify with current state
661
- listener(this.getRenders());
662
- return () => {
663
- this.listeners.delete(listener);
664
- };
665
- }
666
-
667
- /**
668
- * Subscribe to state changes (tracking/paused)
669
- */
670
- subscribeToState(listener) {
671
- this.stateListeners.add(listener);
672
- // Immediately notify with current state
673
- listener(this.getState());
674
- return () => {
675
- this.stateListeners.delete(listener);
676
- };
677
- }
678
-
679
- /**
680
- * Subscribe to settings changes
681
- */
682
- subscribeToSettings(listener) {
683
- this.settingsListeners.add(listener);
684
- // Immediately notify with current settings
685
- listener(this.settings);
686
- return () => {
687
- this.settingsListeners.delete(listener);
688
- };
689
- }
690
-
691
- /**
692
- * Subscribe to filter changes
693
- */
694
- subscribeToFilters(listener) {
695
- this.filterListeners.add(listener);
696
- // Immediately notify with current filters
697
- listener(this.filters);
698
- return () => {
699
- this.filterListeners.delete(listener);
700
- };
701
- }
702
-
703
- /**
704
- * Subscribe to individual render events as they occur.
705
- * Used by unified events system to integrate render events into the timeline.
706
- *
707
- * @param callback - Called for each render event with the event and component info
708
- * @returns Unsubscribe function
709
- */
710
- onRenderEvent(callback) {
711
- this.renderEventCallbacks.add(callback);
712
- return () => {
713
- this.renderEventCallbacks.delete(callback);
714
- };
715
- }
716
-
717
- /**
718
- * Get the number of render event callbacks (for debugging)
719
- */
720
- getRenderEventCallbackCount() {
721
- return this.renderEventCallbacks.size;
722
- }
723
-
724
- /**
725
- * Check if a render should be visible based on current filters
726
- * Used by the overlay to filter frozen highlights
727
- */
728
- shouldShowRender(render) {
729
- const filters = this.filters;
730
-
731
- // Check new pattern-based filters first
732
- if (filters.includePatterns.length > 0) {
733
- if (!this.matchesAnyPatternForInfo(render, filters.includePatterns)) {
734
- return false;
735
- }
736
- }
737
- if (filters.excludePatterns.length > 0) {
738
- if (this.matchesAnyPatternForInfo(render, filters.excludePatterns)) {
739
- return false;
740
- }
741
- }
742
-
743
- // Legacy set-based filters
744
- const hasLegacyIncludeFilters = filters.includeViewType.size > 0 || filters.includeTestID.size > 0 || filters.includeNativeID.size > 0 || filters.includeComponent.size > 0;
745
- if (hasLegacyIncludeFilters) {
746
- const matchesInclude = filters.includeViewType.size > 0 && filters.includeViewType.has(render.viewType) || filters.includeTestID.size > 0 && render.testID && filters.includeTestID.has(render.testID) || filters.includeNativeID.size > 0 && render.nativeID && filters.includeNativeID.has(render.nativeID) || filters.includeComponent.size > 0 && render.componentName && filters.includeComponent.has(render.componentName);
747
- if (!matchesInclude) {
748
- return false;
749
- }
750
- }
751
-
752
- // Check exclude filters
753
- if (filters.excludeViewType.has(render.viewType)) return false;
754
- if (render.testID && filters.excludeTestID.has(render.testID)) return false;
755
- if (render.nativeID && filters.excludeNativeID.has(render.nativeID)) return false;
756
- if (render.componentName && filters.excludeComponent.has(render.componentName)) return false;
757
- return true;
758
- }
759
-
760
- /**
761
- * Get current settings
762
- */
763
- getSettings() {
764
- return {
765
- ...this.settings
766
- };
767
- }
768
-
769
- /**
770
- * Update settings
771
- */
772
- setSettings(newSettings) {
773
- // Validate batchSize
774
- if (newSettings.batchSize !== undefined) {
775
- newSettings.batchSize = Math.max(10, Math.min(500, newSettings.batchSize));
776
- }
777
-
778
- // Validate maxRenderHistoryPerComponent
779
- if (newSettings.maxRenderHistoryPerComponent !== undefined) {
780
- newSettings.maxRenderHistoryPerComponent = Math.max(5, Math.min(50, newSettings.maxRenderHistoryPerComponent));
781
- }
782
-
783
- // If enabling render history, also enable trackRenderCauses
784
- if (newSettings.enableRenderHistory && !this.settings.trackRenderCauses) {
785
- newSettings.trackRenderCauses = true;
786
- }
787
-
788
- // If disabling trackRenderCauses, also disable render history
789
- if (newSettings.trackRenderCauses === false && this.settings.enableRenderHistory) {
790
- newSettings.enableRenderHistory = false;
791
- }
792
- this.settings = {
793
- ...this.settings,
794
- ...newSettings
795
- };
796
-
797
- // Sync performance logging with PerformanceLogger
798
- if (newSettings.performanceLogging !== undefined) {
799
- _PerformanceLogger.PerformanceLogger.setEnabled(newSettings.performanceLogging);
800
- }
801
- this.notifySettingsListeners();
802
- }
803
-
804
- /**
805
- * Clear render history for all components
806
- */
807
- clearAllRenderHistory() {
808
- for (const render of this.renders.values()) {
809
- render.renderHistory = [];
810
- }
811
- this.notifyListeners();
812
- }
813
-
814
- /**
815
- * Clear render history for a specific component
816
- */
817
- clearRenderHistory(id) {
818
- const render = this.renders.get(id);
819
- if (render) {
820
- render.renderHistory = [];
821
- this.notifyListeners();
822
- }
823
- }
824
-
825
- /**
826
- * Get render history stats for debugging
827
- */
828
- getRenderHistoryStats() {
829
- let totalEvents = 0;
830
- let componentsWithHistory = 0;
831
- for (const render of this.renders.values()) {
832
- if (render.renderHistory && render.renderHistory.length > 0) {
833
- totalEvents += render.renderHistory.length;
834
- componentsWithHistory++;
835
- }
836
- }
837
- return {
838
- totalEvents,
839
- componentsWithHistory,
840
- averageEventsPerComponent: componentsWithHistory > 0 ? totalEvents / componentsWithHistory : 0
841
- };
842
- }
843
-
844
- /**
845
- * Get batch size (convenience method)
846
- */
847
- getBatchSize() {
848
- return this.settings.batchSize;
849
- }
850
-
851
- /**
852
- * Set batch size (convenience method)
853
- */
854
- setBatchSize(size) {
855
- this.setSettings({
856
- batchSize: size
857
- });
858
- }
859
- notifyListeners() {
860
- const renders = this.getRenders();
861
- for (const listener of this.listeners) {
862
- try {
863
- listener(renders);
864
- } catch (error) {
865
- console.error("[RenderTracker] Error in listener:", error);
866
- }
867
- }
868
- }
869
- notifyStateListeners() {
870
- const state = this.getState();
871
- for (const listener of this.stateListeners) {
872
- try {
873
- listener(state);
874
- } catch (error) {
875
- console.error("[RenderTracker] Error in state listener:", error);
876
- }
877
- }
878
- }
879
- notifySettingsListeners() {
880
- const settings = this.getSettings();
881
- for (const listener of this.settingsListeners) {
882
- try {
883
- listener(settings);
884
- } catch (error) {
885
- console.error("[RenderTracker] Error in settings listener:", error);
886
- }
887
- }
888
- }
889
- notifyFilterListeners() {
890
- const filters = this.getFilters();
891
- for (const listener of this.filterListeners) {
892
- try {
893
- listener(filters);
894
- } catch (error) {
895
- console.error("[RenderTracker] Error in filter listener:", error);
896
- }
897
- }
898
- }
899
- }
900
-
901
- // Export singleton instance
902
- const RenderTracker = exports.RenderTracker = new RenderTrackerSingleton();
903
- var _default = exports.default = RenderTracker;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=exports.RenderTracker=void 0;var _ViewTypeMapper=require("./ViewTypeMapper"),_PerformanceLogger=require("./PerformanceLogger");const MAX_TRACKED_COMPONENTS=200,DEFAULT_BATCH_SIZE=150;class RenderTrackerSingleton{renders=new Map;listeners=new Set;stateListeners=new Set;settingsListeners=new Set;filterListeners=new Set;renderEventCallbacks=new Set;isTracking=!1;isPaused=!1;settings={batchSize:150,showRenderCount:!0,performanceLogging:!1,trackRenderCauses:!1,enableRenderHistory:!0,maxRenderHistoryPerComponent:20,capturePropsOnRender:!1,captureStateOnRender:!1,debugLogLevel:"off",excludeDevTools:!0};isBatchMode=!1;batchDirty=!1;filters={includeTestID:new Set,includeNativeID:new Set,includeViewType:new Set,includeComponent:new Set,excludeTestID:new Set,excludeNativeID:new Set,excludeViewType:new Set,excludeComponent:new Set,includePatterns:[],excludePatterns:[]};trackRender(e){if(this.isPaused)return;const t=String(e.nativeTag),s=Date.now(),i=this.renders.get(t);if(i){if(i.renderCount=e.count,i.lastRenderTime=s,i.color=e.color,e.measurements&&(i.measurements=e.measurements),e.testID&&!i.testID&&(i.testID=e.testID),e.nativeID&&!i.nativeID&&(i.nativeID=e.nativeID),e.accessibilityLabel&&!i.accessibilityLabel&&(i.accessibilityLabel=e.accessibilityLabel),e.componentName&&!i.componentName&&(i.componentName=e.componentName),e.renderCause&&(i.lastRenderCause=e.renderCause),this.settings.enableRenderHistory){const t=e.renderCause||{type:"unknown",timestamp:s};this.addRenderEvent(i,t,e.capturedProps,e.capturedState)}}else{const i={id:t,nativeTag:e.nativeTag,viewType:e.viewType,displayName:(0,_ViewTypeMapper.getComponentDisplayName)(e.viewType),testID:e.testID,nativeID:e.nativeID,accessibilityLabel:e.accessibilityLabel,componentName:e.componentName,renderCount:e.count,firstRenderTime:s,lastRenderTime:s,measurements:e.measurements,color:e.color,lastRenderCause:e.renderCause};if(this.settings.enableRenderHistory){i.renderHistory=[];const t=e.renderCause||{type:1===e.count?"mount":"unknown",timestamp:s};this.addRenderEvent(i,t,e.capturedProps,e.capturedState)}if(this.renders.set(t,i),this.renders.size>200){const e=Array.from(this.renders.values()).sort((e,t)=>e.lastRenderTime-t.lastRenderTime).slice(0,this.renders.size-200);for(const t of e)this.renders.delete(t.id)}}this.isBatchMode?this.batchDirty=!0:this.notifyListeners()}addRenderEvent(e,t,s,i){e.renderHistory||(e.renderHistory=[]);const n={id:`${e.nativeTag}-${t.timestamp}`,timestamp:t.timestamp,cause:t,renderNumber:e.renderCount,capturedProps:this.settings.capturePropsOnRender?s:void 0,capturedState:this.settings.captureStateOnRender?i:void 0};e.renderHistory.push(n);const r=Math.max(5,Math.min(50,this.settings.maxRenderHistoryPerComponent));e.renderHistory.length>r&&(e.renderHistory=e.renderHistory.slice(-r)),this.notifyRenderEventCallbacks(n,e)}notifyRenderEventCallbacks(e,t){this.renderEventCallbacks.forEach(s=>{try{s(e,t)}catch{}})}emitRenderEvent(e){if(0===this.renderEventCallbacks.size)return;const t=Date.now(),s=e.renderCause||{type:"unknown",timestamp:t},i={id:String(e.nativeTag),nativeTag:e.nativeTag,viewType:e.viewType,displayName:(0,_ViewTypeMapper.getComponentDisplayName)(e.viewType),testID:e.testID,nativeID:e.nativeID,accessibilityLabel:e.accessibilityLabel,componentName:e.componentName,renderCount:e.count,firstRenderTime:t,lastRenderTime:t,measurements:e.measurements,color:e.color,lastRenderCause:s,renderHistory:[]},n={id:`${e.nativeTag}-${t}-${e.count}`,timestamp:t,renderNumber:e.count,cause:s,capturedProps:void 0,capturedState:void 0};this.notifyRenderEventCallbacks(n,i)}startBatch(){this.isBatchMode=!0,this.batchDirty=!1}endBatch(){this.isBatchMode=!1,this.batchDirty&&(this.batchDirty=!1,this.notifyListeners())}getRenders(){return Array.from(this.renders.values()).map(e=>({...e}))}passesFilters(e){if(this.filters.includePatterns.length>0&&!this.matchesAnyPatternForInfo(e,this.filters.includePatterns))return!1;if(this.filters.excludePatterns.length>0&&this.matchesAnyPatternForInfo(e,this.filters.excludePatterns))return!1;if(this.filters.includeViewType.size>0){const t=e.viewType||"",s=e.displayName||"";if(!this.matchesPattern(t,this.filters.includeViewType)&&!this.matchesPattern(s,this.filters.includeViewType))return!1}if(this.filters.includeTestID.size>0&&(!e.testID||!this.matchesPattern(e.testID,this.filters.includeTestID)))return!1;if(this.filters.includeNativeID.size>0&&(!e.nativeID||!this.matchesPattern(e.nativeID,this.filters.includeNativeID)))return!1;if(this.filters.includeComponent.size>0&&(!e.componentName||!this.matchesPattern(e.componentName,this.filters.includeComponent)))return!1;if(this.filters.excludeViewType.size>0){const t=e.viewType||"",s=e.displayName||"";if(this.matchesPattern(t,this.filters.excludeViewType)||this.matchesPattern(s,this.filters.excludeViewType))return!1}return!(this.filters.excludeTestID.size>0&&e.testID&&this.matchesPattern(e.testID,this.filters.excludeTestID)||this.filters.excludeNativeID.size>0&&e.nativeID&&this.matchesPattern(e.nativeID,this.filters.excludeNativeID)||this.filters.excludeComponent.size>0&&e.componentName&&this.matchesPattern(e.componentName,this.filters.excludeComponent))}matchesAnyPatternForInfo(e,t){for(const s of t){const t=s.value.toLowerCase();switch(s.type){case"any":if(e.viewType.toLowerCase().includes(t)||e.displayName?.toLowerCase().includes(t)||e.testID?.toLowerCase().includes(t)||e.nativeID?.toLowerCase().includes(t)||e.componentName?.toLowerCase().includes(t)||e.accessibilityLabel?.toLowerCase().includes(t))return!0;break;case"viewType":if(e.viewType.toLowerCase().includes(t)||e.displayName?.toLowerCase().includes(t))return!0;break;case"testID":if(e.testID?.toLowerCase().includes(t))return!0;break;case"nativeID":if(e.nativeID?.toLowerCase().includes(t))return!0;break;case"component":if(e.componentName?.toLowerCase().includes(t))return!0;break;case"accessibilityLabel":if(e.accessibilityLabel?.toLowerCase().includes(t))return!0}}return!1}hasActiveFilters(){return this.filters.includePatterns.length>0||this.filters.excludePatterns.length>0||this.filters.includeViewType.size>0||this.filters.includeTestID.size>0||this.filters.includeNativeID.size>0||this.filters.includeComponent.size>0||this.filters.excludeViewType.size>0||this.filters.excludeTestID.size>0||this.filters.excludeNativeID.size>0||this.filters.excludeComponent.size>0||void 0!==this.filters.minRenderCount||void 0!==this.filters.maxRenderCount}getFilteredRenders(e=""){let t=this.getRenders();if(e.trim()){const s=e.toLowerCase();t=t.filter(e=>e.viewType.toLowerCase().includes(s)||e.displayName.toLowerCase().includes(s)||e.testID?.toLowerCase().includes(s)||e.nativeID?.toLowerCase().includes(s)||e.accessibilityLabel?.toLowerCase().includes(s)||e.componentName?.toLowerCase().includes(s)||String(e.nativeTag).includes(s))}return t=t.filter(e=>this.passesFilters(e)),void 0!==this.filters.minRenderCount&&(t=t.filter(e=>e.renderCount>=this.filters.minRenderCount)),void 0!==this.filters.maxRenderCount&&(t=t.filter(e=>e.renderCount<=this.filters.maxRenderCount)),t.sort((e,t)=>t.lastRenderTime-e.lastRenderTime)}matchesPattern(e,t){const s=e.toLowerCase();for(const e of t){const t=e.toLowerCase();if(s.includes(t))return!0}return!1}getRender(e){return this.renders.get(e)}clear(){this.renders.clear(),this.notifyListeners()}resetRenderCount(e){const t=this.renders.get(e);t&&(t.renderCount=0,this.notifyListeners())}start(){this.isTracking=!0,this.isPaused=!1,this.notifyStateListeners()}stop(){this.isTracking=!1,this.isPaused=!1,this.notifyStateListeners()}pause(){this.isPaused=!0,this.notifyStateListeners()}resume(){this.isPaused=!1,this.notifyStateListeners()}togglePause(){this.isPaused=!this.isPaused,this.notifyStateListeners()}getState(){return{isTracking:this.isTracking,isPaused:this.isPaused}}getFilters(){return this.filters}setFilters(e){this.filters={...this.filters,...e},this.notifyListeners(),this.notifyFilterListeners()}addIncludePattern(e,t){const s=`include${e.charAt(0).toUpperCase()+e.slice(1)}`;this.filters[s].add(t),this.notifyListeners()}removeIncludePattern(e,t){const s=`include${e.charAt(0).toUpperCase()+e.slice(1)}`;this.filters[s].delete(t),this.notifyListeners()}addExcludePattern(e,t){const s=`exclude${e.charAt(0).toUpperCase()+e.slice(1)}`;this.filters[s].add(t),this.notifyListeners()}removeExcludePattern(e,t){const s=`exclude${e.charAt(0).toUpperCase()+e.slice(1)}`;this.filters[s].delete(t),this.notifyListeners()}clearFilters(){this.filters={includeTestID:new Set,includeNativeID:new Set,includeViewType:new Set,includeComponent:new Set,excludeTestID:new Set,excludeNativeID:new Set,excludeViewType:new Set,excludeComponent:new Set,includePatterns:[],excludePatterns:[],minRenderCount:void 0,maxRenderCount:void 0},this.notifyListeners()}getAvailableProps(){const e=new Set,t=new Set,s=new Set,i=new Set,n=new Set;for(const r of this.renders.values())r.viewType&&e.add(r.viewType),r.testID&&t.add(r.testID),r.nativeID&&s.add(r.nativeID),r.componentName&&i.add(r.componentName),r.accessibilityLabel&&n.add(r.accessibilityLabel);return{viewTypes:Array.from(e).sort(),testIDs:Array.from(t).sort(),nativeIDs:Array.from(s).sort(),componentNames:Array.from(i).sort(),accessibilityLabels:Array.from(n).sort()}}getStats(){let e=0;for(const t of this.renders.values())e+=t.renderCount;return{totalComponents:this.renders.size,totalRenders:e}}subscribe(e){return this.listeners.add(e),e(this.getRenders()),()=>{this.listeners.delete(e)}}subscribeToState(e){return this.stateListeners.add(e),e(this.getState()),()=>{this.stateListeners.delete(e)}}subscribeToSettings(e){return this.settingsListeners.add(e),e(this.settings),()=>{this.settingsListeners.delete(e)}}subscribeToFilters(e){return this.filterListeners.add(e),e(this.filters),()=>{this.filterListeners.delete(e)}}onRenderEvent(e){return this.renderEventCallbacks.add(e),()=>{this.renderEventCallbacks.delete(e)}}getRenderEventCallbackCount(){return this.renderEventCallbacks.size}shouldShowRender(e){const t=this.filters;return!(t.includePatterns.length>0&&!this.matchesAnyPatternForInfo(e,t.includePatterns))&&(!(t.excludePatterns.length>0&&this.matchesAnyPatternForInfo(e,t.excludePatterns))&&(!((t.includeViewType.size>0||t.includeTestID.size>0||t.includeNativeID.size>0||t.includeComponent.size>0)&&!(t.includeViewType.size>0&&t.includeViewType.has(e.viewType)||t.includeTestID.size>0&&e.testID&&t.includeTestID.has(e.testID)||t.includeNativeID.size>0&&e.nativeID&&t.includeNativeID.has(e.nativeID)||t.includeComponent.size>0&&e.componentName&&t.includeComponent.has(e.componentName)))&&!(t.excludeViewType.has(e.viewType)||e.testID&&t.excludeTestID.has(e.testID)||e.nativeID&&t.excludeNativeID.has(e.nativeID)||e.componentName&&t.excludeComponent.has(e.componentName))))}getSettings(){return{...this.settings}}setSettings(e){void 0!==e.batchSize&&(e.batchSize=Math.max(10,Math.min(500,e.batchSize))),void 0!==e.maxRenderHistoryPerComponent&&(e.maxRenderHistoryPerComponent=Math.max(5,Math.min(50,e.maxRenderHistoryPerComponent))),e.enableRenderHistory&&!this.settings.trackRenderCauses&&(e.trackRenderCauses=!0),!1===e.trackRenderCauses&&this.settings.enableRenderHistory&&(e.enableRenderHistory=!1),this.settings={...this.settings,...e},void 0!==e.performanceLogging&&_PerformanceLogger.PerformanceLogger.setEnabled(e.performanceLogging),this.notifySettingsListeners()}clearAllRenderHistory(){for(const e of this.renders.values())e.renderHistory=[];this.notifyListeners()}clearRenderHistory(e){const t=this.renders.get(e);t&&(t.renderHistory=[],this.notifyListeners())}getRenderHistoryStats(){let e=0,t=0;for(const s of this.renders.values())s.renderHistory&&s.renderHistory.length>0&&(e+=s.renderHistory.length,t++);return{totalEvents:e,componentsWithHistory:t,averageEventsPerComponent:t>0?e/t:0}}getBatchSize(){return this.settings.batchSize}setBatchSize(e){this.setSettings({batchSize:e})}notifyListeners(){const e=this.getRenders();for(const t of this.listeners)try{t(e)}catch(e){console.error("[RenderTracker] Error in listener:",e)}}notifyStateListeners(){const e=this.getState();for(const t of this.stateListeners)try{t(e)}catch(e){console.error("[RenderTracker] Error in state listener:",e)}}notifySettingsListeners(){const e=this.getSettings();for(const t of this.settingsListeners)try{t(e)}catch(e){console.error("[RenderTracker] Error in settings listener:",e)}}notifyFilterListeners(){const e=this.getFilters();for(const t of this.filterListeners)try{t(e)}catch(e){console.error("[RenderTracker] Error in filter listener:",e)}}}const RenderTracker=exports.RenderTracker=new RenderTrackerSingleton;var _default=exports.default=RenderTracker;