bee-ladybug 0.6.2 → 0.6.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bee-ladybug",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "description": "Universal telemetry and visual inspection overlay for Canvas, DOM, Python and AI flows.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -17,6 +17,12 @@
17
17
  import { isReportNoise } from '../core/ReportExporter.js';
18
18
 
19
19
  const MAX_PROBLEM_ROWS = 40;
20
+ const OBSERVE_OPTIONS = Object.freeze({
21
+ childList: true,
22
+ subtree: true,
23
+ attributes: true,
24
+ attributeFilter: ['class', 'style', 'hidden', 'disabled', 'open']
25
+ });
20
26
 
21
27
  export const WEB_DOM_ADAPTER_DEFAULTS = Object.freeze({
22
28
  overlay: true,
@@ -74,6 +80,7 @@ export class WebDOMAdapter {
74
80
  this.#seenAttr = 0;
75
81
  this.#mutTimer = 0;
76
82
  this.#lastHoverKey = '';
83
+ this.#overlayStyle = null;
77
84
  this.#onMove = (event) => {
78
85
  this.#pointer.x = event.clientX;
79
86
  this.#pointer.y = event.clientY;
@@ -104,6 +111,8 @@ export class WebDOMAdapter {
104
111
  #seenAttr;
105
112
  #mutTimer;
106
113
  #lastHoverKey;
114
+ /** Last style values written to the overlay. */
115
+ #overlayStyle;
107
116
  #onMove;
108
117
  #onResize;
109
118
  #onTick;
@@ -118,6 +127,7 @@ export class WebDOMAdapter {
118
127
  if (this.core && typeof this.core.subscribe === 'function') {
119
128
  this.#unsubscribe = this.core.subscribe((packet) => this.#onCore(packet));
120
129
  }
130
+ this.#reporting = true;
121
131
  if (this.overlayEnabled) this.#mountOverlay();
122
132
  if (typeof window !== 'undefined') {
123
133
  window.addEventListener('mousemove', this.#onMove, true);
@@ -126,18 +136,12 @@ export class WebDOMAdapter {
126
136
  }
127
137
  if (this.root && typeof MutationObserver !== 'undefined') {
128
138
  this.#observer = new MutationObserver(this.#onMutate);
129
- this.#observer.observe(this.root, {
130
- childList: true,
131
- subtree: true,
132
- attributes: true,
133
- attributeFilter: ['class', 'style', 'hidden', 'disabled', 'open']
134
- });
139
+ this.#observer.observe(this.root, OBSERVE_OPTIONS);
135
140
  }
136
141
  if (this.autoTick && typeof requestAnimationFrame === 'function') {
137
142
  this.#rafId = requestAnimationFrame(this.#onTick);
138
143
  }
139
144
 
140
- this.#reporting = true;
141
145
  this.core?.registerAdapter('dom', {
142
146
  label: 'DOM',
143
147
  enabled: true,
@@ -178,24 +182,41 @@ export class WebDOMAdapter {
178
182
  window.removeEventListener('scroll', this.#onResize, true);
179
183
  }
180
184
  this.#unmountOverlay();
185
+ this.hover = null;
186
+ this.#lastHoverKey = '';
187
+ this.#lastPump = 0;
188
+ this.#fps = 0;
189
+ this.#pointer = { x: 0, y: 0, dirty: false };
190
+ this.#mutAdded = 0;
191
+ this.#mutRemoved = 0;
192
+ this.#mutAttr = 0;
193
+ this.#seenAdded = 0;
194
+ this.#seenRemoved = 0;
195
+ this.#seenAttr = 0;
181
196
  return this;
182
197
  }
183
198
 
184
199
  /** @param {ParentNode | null} root */
185
200
  setRoot(root) {
186
201
  this.root = root;
187
- if (this.#attached && this.#observer && root) {
188
- this.#observer.disconnect();
189
- this.#observer.observe(root, {
190
- childList: true,
191
- subtree: true,
192
- attributes: true,
193
- attributeFilter: ['class', 'style', 'hidden', 'disabled', 'open']
194
- });
202
+ if (this.#observer) this.#observer.disconnect();
203
+ if (!root) {
204
+ this.#observer = null;
205
+ } else if (this.#attached && typeof MutationObserver !== 'undefined') {
206
+ if (!this.#observer) this.#observer = new MutationObserver(this.#onMutate);
207
+ this.#observer.observe(root, OBSERVE_OPTIONS);
195
208
  }
209
+ if (this.hover && !this.#rootHolds(this.hover)) this.hover = null;
196
210
  return this;
197
211
  }
198
212
 
213
+ #rootHolds(node) {
214
+ const root = this.root;
215
+ if (!root) return false;
216
+ if (typeof document !== 'undefined' && root === document) return true;
217
+ return node === root || Boolean(root.contains?.(node));
218
+ }
219
+
199
220
  /**
200
221
  * Box model of the hover and watched nodes, layout problems under root,
201
222
  * and the latest mutation counts. Returns null when detached.
@@ -311,6 +332,7 @@ export class WebDOMAdapter {
311
332
  this.#lastHoverKey = '';
312
333
  this.core.sendData('state', { source: this.source, key: 'hover', value: '—' });
313
334
  this.core.sendData('state', { source: this.source, key: 'box', value: '—' });
335
+ this.core.sendData('state', { source: this.source, key: 'display', value: '—' });
314
336
  }
315
337
  return;
316
338
  }
@@ -341,7 +363,7 @@ export class WebDOMAdapter {
341
363
  }
342
364
 
343
365
  #queueMutations(records) {
344
- if (this.frozen) return;
366
+ if (this.frozen || !this.#reporting) return;
345
367
  for (let i = 0; i < records.length; i++) {
346
368
  const rec = records[i];
347
369
  if (isBeeChrome(rec.target)) continue;
@@ -433,12 +455,14 @@ export class WebDOMAdapter {
433
455
  canvas.style.margin = '0';
434
456
  document.body.appendChild(canvas);
435
457
  this.#overlay = canvas;
458
+ this.#overlayStyle = null;
436
459
  this.#syncOverlay();
437
460
  }
438
461
 
439
462
  #unmountOverlay() {
440
463
  if (this.#overlay?.parentNode) this.#overlay.parentNode.removeChild(this.#overlay);
441
464
  this.#overlay = null;
465
+ this.#overlayStyle = null;
442
466
  }
443
467
 
444
468
  #syncOverlay() {
@@ -447,12 +471,22 @@ export class WebDOMAdapter {
447
471
  const dpr = Math.min(window.devicePixelRatio || 1, 2);
448
472
  const w = window.innerWidth;
449
473
  const h = window.innerHeight;
450
- canvas.style.width = `${w}px`;
451
- canvas.style.height = `${h}px`;
452
- canvas.width = Math.round(w * dpr);
453
- canvas.height = Math.round(h * dpr);
474
+ // Assigning width/height clears and reallocates the bitmap: only when they change.
475
+ const bitmapW = Math.round(w * dpr);
476
+ const bitmapH = Math.round(h * dpr);
477
+ if (canvas.width !== bitmapW) canvas.width = bitmapW;
478
+ if (canvas.height !== bitmapH) canvas.height = bitmapH;
454
479
  const hidden = !this.#reporting || (this.core && this.core.visible === false);
455
- canvas.style.display = hidden ? 'none' : 'block';
480
+ const next = {
481
+ width: `${w}px`,
482
+ height: `${h}px`,
483
+ display: hidden ? 'none' : 'block'
484
+ };
485
+ const prev = this.#overlayStyle;
486
+ for (const key of Object.keys(next)) {
487
+ if (!prev || prev[key] !== next[key]) canvas.style[key] = next[key];
488
+ }
489
+ this.#overlayStyle = next;
456
490
  }
457
491
 
458
492
  #enable() {
@@ -462,6 +496,11 @@ export class WebDOMAdapter {
462
496
 
463
497
  #disable() {
464
498
  this.#reporting = false;
499
+ if (this.#mutTimer && typeof clearTimeout === 'function') clearTimeout(this.#mutTimer);
500
+ this.#mutTimer = 0;
501
+ this.#mutAdded = 0;
502
+ this.#mutRemoved = 0;
503
+ this.#mutAttr = 0;
465
504
  this.#syncOverlay();
466
505
  }
467
506
 
@@ -10,7 +10,7 @@ import { UIOverlay } from './UIOverlay.js';
10
10
  import { buildAssistantSnapshot, normalizeAssistant } from './AiAssistant.js';
11
11
  import { exportReport as writeReport } from './ReportExporter.js';
12
12
 
13
- export const BEE_LADYBUG_VERSION = '0.6.2';
13
+ export const BEE_LADYBUG_VERSION = '0.6.3';
14
14
 
15
15
  export const CORE_DEFAULTS = Object.freeze({
16
16
  toggleKey: 'F2',
package/src/index.d.ts CHANGED
@@ -356,6 +356,8 @@ export interface WebDOMAdapterOptions {
356
356
 
357
357
  export const WEB_DOM_ADAPTER_DEFAULTS: Required<Omit<WebDOMAdapterOptions, 'root'>>;
358
358
 
359
+ export function domNoiseQuiet(cssEnabled: boolean, frozen: boolean, timeScale: number): boolean;
360
+
359
361
  export class WebDOMAdapter {
360
362
  core: BeeLadybugCore | null;
361
363
  root: ParentNode | null;
package/src/index.js CHANGED
@@ -2,7 +2,7 @@ export { BeeLadybugCore, BEE_LADYBUG_VERSION, CORE_DEFAULTS, WELL_KNOWN_TYPES, f
2
2
  export { exportReport, isReportNoise } from './core/ReportExporter.js';
3
3
  export { UIOverlay } from './core/UIOverlay.js';
4
4
  export { CanvasAdapter, CANVAS_ADAPTER_DEFAULTS } from './adapters/CanvasAdapter.js';
5
- export { WebDOMAdapter, WEB_DOM_ADAPTER_DEFAULTS } from './adapters/WebDOMAdapter.js';
5
+ export { WebDOMAdapter, WEB_DOM_ADAPTER_DEFAULTS, domNoiseQuiet } from './adapters/WebDOMAdapter.js';
6
6
  export { CSSAdapter, CSS_ADAPTER_DEFAULTS } from './adapters/CSSAdapter.js';
7
7
  export { AntAdapter, ANT_ADAPTER_DEFAULTS } from './adapters/AntAdapter.js';
8
8
  export { SpiderAdapter, SPIDER_ADAPTER_DEFAULTS } from './adapters/SpiderAdapter.js';