bee-ladybug 0.6.2 → 0.6.4
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 +1 -1
- package/src/adapters/AntAdapter.js +1 -0
- package/src/adapters/CSSAdapter.js +70 -28
- package/src/adapters/WebDOMAdapter.js +61 -21
- package/src/core/BeeLadybugCore.js +1 -1
- package/src/index.d.ts +2 -0
- package/src/index.js +1 -1
package/package.json
CHANGED
|
@@ -189,6 +189,7 @@ function isBeeChrome(node) {
|
|
|
189
189
|
if (tag === 'BEE-LADYBUG-OVERLAY') return true;
|
|
190
190
|
if (el.hasAttribute?.('data-bee-ladybug-dom')) return true;
|
|
191
191
|
if (el.hasAttribute?.('data-bee-ladybug-canvas')) return true;
|
|
192
|
+
if (el.hasAttribute?.('data-bee-ladybug-css')) return true;
|
|
192
193
|
el = el.parentElement;
|
|
193
194
|
}
|
|
194
195
|
return false;
|
|
@@ -61,9 +61,13 @@ export class CSSAdapter {
|
|
|
61
61
|
this.#hoverBox = null;
|
|
62
62
|
this.#pinBox = null;
|
|
63
63
|
this.#observer = null;
|
|
64
|
+
this.#unsubscribe = null;
|
|
65
|
+
this.#hasPointer = false;
|
|
64
66
|
this.#onMove = (event) => {
|
|
67
|
+
if (this.core && this.core.visible === false) return;
|
|
65
68
|
this.#x = event.clientX;
|
|
66
69
|
this.#y = event.clientY;
|
|
70
|
+
this.#hasPointer = true;
|
|
67
71
|
this.#schedule();
|
|
68
72
|
};
|
|
69
73
|
this.#onKey = (event) => this.#handleKey(event);
|
|
@@ -71,7 +75,7 @@ export class CSSAdapter {
|
|
|
71
75
|
this.#onMutate = (records) => {
|
|
72
76
|
if (!records.some(touchesSheet)) return;
|
|
73
77
|
this.#sheetsDirty = true;
|
|
74
|
-
this.#schedule();
|
|
78
|
+
if (this.#hasPointer) this.#schedule();
|
|
75
79
|
};
|
|
76
80
|
}
|
|
77
81
|
|
|
@@ -92,6 +96,9 @@ export class CSSAdapter {
|
|
|
92
96
|
#hoverBox;
|
|
93
97
|
#pinBox;
|
|
94
98
|
#observer;
|
|
99
|
+
#unsubscribe;
|
|
100
|
+
/** True after the first mousemove: before that (x, y) is not a real pointer. */
|
|
101
|
+
#hasPointer;
|
|
95
102
|
#onMove;
|
|
96
103
|
#onKey;
|
|
97
104
|
#onScroll;
|
|
@@ -104,6 +111,9 @@ export class CSSAdapter {
|
|
|
104
111
|
attach() {
|
|
105
112
|
if (this.#attached) return this;
|
|
106
113
|
this.#attached = true;
|
|
114
|
+
if (this.core && typeof this.core.subscribe === 'function') {
|
|
115
|
+
this.#unsubscribe = this.core.subscribe((packet) => this.#onCore(packet));
|
|
116
|
+
}
|
|
107
117
|
this.core?.registerAdapter('css', {
|
|
108
118
|
label: this.label,
|
|
109
119
|
hotkey: this.hotkey,
|
|
@@ -128,10 +138,21 @@ export class CSSAdapter {
|
|
|
128
138
|
if (!this.#attached) return this;
|
|
129
139
|
this.#disable();
|
|
130
140
|
this.#attached = false;
|
|
141
|
+
if (this.#unsubscribe) this.#unsubscribe();
|
|
142
|
+
this.#unsubscribe = null;
|
|
131
143
|
this.core?.unregisterAdapter('css');
|
|
132
144
|
return this;
|
|
133
145
|
}
|
|
134
146
|
|
|
147
|
+
#onCore(packet) {
|
|
148
|
+
if (packet.type !== 'sys' || packet.payload?.op !== 'visibility') return;
|
|
149
|
+
this.#placeBoxes();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#boxesVisible() {
|
|
153
|
+
return !(this.core && this.core.visible === false);
|
|
154
|
+
}
|
|
155
|
+
|
|
135
156
|
/** Page scan. Click a row to outline one element of that group. */
|
|
136
157
|
scan() {
|
|
137
158
|
if (!this.#active || typeof document === 'undefined') return this;
|
|
@@ -141,15 +162,15 @@ export class CSSAdapter {
|
|
|
141
162
|
const rows = [];
|
|
142
163
|
for (let i = 0; i < nodes.length; i++) {
|
|
143
164
|
const el = nodes[i];
|
|
144
|
-
if (!el || isBeeChrome(el) || isSkippedTag(el)) continue;
|
|
165
|
+
if (!el || isBeeChrome(el) || isSkippedTag(el) || isReportNoise(el)) continue;
|
|
145
166
|
const measured = measureViewportOverflow(el);
|
|
146
167
|
if (measured) overflow.push(measured);
|
|
147
168
|
const findings = [];
|
|
148
169
|
pushNegativeMargins(el, findings);
|
|
149
170
|
pushInvisible(el, findings);
|
|
150
|
-
pushBlockers(el, findings);
|
|
171
|
+
pushBlockers(el, findings, true);
|
|
151
172
|
pushImage(el, findings);
|
|
152
|
-
pushStacking(el, findings);
|
|
173
|
+
pushStacking(el, findings, true);
|
|
153
174
|
pushImportant(el, this.#rules, findings);
|
|
154
175
|
for (let j = 0; j < findings.length; j++) {
|
|
155
176
|
rows.push({ el, selector: cssPath(el), ...findings[j] });
|
|
@@ -245,7 +266,9 @@ export class CSSAdapter {
|
|
|
245
266
|
for (let i = 0; i < rows.length; i++) {
|
|
246
267
|
const row = rows[i];
|
|
247
268
|
if (describeCause(row.kind, row.selector)) {
|
|
248
|
-
|
|
269
|
+
// No cap here: MAX_SNAPSHOT applies after the severity sort, so an info row
|
|
270
|
+
// can never push a real error out.
|
|
271
|
+
causes = addCause(causes, { kind: row.kind, path: row.selector, el: row.el }, Infinity);
|
|
249
272
|
} else {
|
|
250
273
|
plain.push(row);
|
|
251
274
|
}
|
|
@@ -319,6 +342,7 @@ export class CSSAdapter {
|
|
|
319
342
|
#disable() {
|
|
320
343
|
if (!this.#active) return;
|
|
321
344
|
this.#active = false;
|
|
345
|
+
this.#hasPointer = false;
|
|
322
346
|
if (typeof window !== 'undefined') {
|
|
323
347
|
window.removeEventListener('mousemove', this.#onMove, true);
|
|
324
348
|
window.removeEventListener('keydown', this.#onKey);
|
|
@@ -340,11 +364,16 @@ export class CSSAdapter {
|
|
|
340
364
|
this.core?.publishDetail([]);
|
|
341
365
|
this.core?.publishIssues([]);
|
|
342
366
|
this.core?.sendData('state', { source: this.source, key: 'css.hunt', value: 'off' });
|
|
367
|
+
this.core?.sendData('state', { source: this.source, key: 'css.target', value: '—' });
|
|
368
|
+
this.core?.sendData('state', { source: this.source, key: 'css.hits', value: '0' });
|
|
369
|
+
this.core?.sendData('state', { source: this.source, key: 'css.pin', value: 'off' });
|
|
343
370
|
this.core?.sendData('log', { source: this.source, message: 'CSS hunt off.' });
|
|
344
371
|
}
|
|
345
372
|
|
|
346
373
|
#handleKey(event) {
|
|
347
374
|
if (!this.#active || event.repeat) return;
|
|
375
|
+
if (event.ctrlKey || event.metaKey || event.altKey) return;
|
|
376
|
+
if (this.core && this.core.visible === false) return;
|
|
348
377
|
if (isTypingTarget(event.target)) return;
|
|
349
378
|
if (event.code === this.pinKey) {
|
|
350
379
|
event.preventDefault();
|
|
@@ -377,22 +406,23 @@ export class CSSAdapter {
|
|
|
377
406
|
|
|
378
407
|
#inspect(x, y) {
|
|
379
408
|
const el = pickElement(x, y);
|
|
380
|
-
placeBox(this.#hoverBox, el);
|
|
409
|
+
placeBox(this.#hoverBox, el, this.#boxesVisible());
|
|
381
410
|
if (this.#panelLock) return;
|
|
382
411
|
if (el === this.#lastEl) return;
|
|
383
412
|
this.#lastEl = el;
|
|
384
413
|
if (!el) {
|
|
385
414
|
this.core?.publishDetail([]);
|
|
386
415
|
this.core?.sendData('state', { source: this.source, key: 'css.target', value: '—' });
|
|
416
|
+
this.core?.sendData('state', { source: this.source, key: 'css.hits', value: '0' });
|
|
387
417
|
return;
|
|
388
418
|
}
|
|
389
419
|
const findings = [];
|
|
390
420
|
pushImportant(el, this.#rules, findings);
|
|
391
421
|
pushOverflow(el, findings);
|
|
392
422
|
pushInvisible(el, findings);
|
|
393
|
-
pushBlockers(el, findings);
|
|
423
|
+
pushBlockers(el, findings, true);
|
|
394
424
|
pushImage(el, findings);
|
|
395
|
-
pushStacking(el, findings);
|
|
425
|
+
pushStacking(el, findings, true);
|
|
396
426
|
const path = cssPath(el);
|
|
397
427
|
this.core?.sendData('state', { source: this.source, key: 'css.target', value: path });
|
|
398
428
|
this.core?.sendData('state', {
|
|
@@ -419,7 +449,7 @@ export class CSSAdapter {
|
|
|
419
449
|
if (this.#panelLock) {
|
|
420
450
|
this.#panelLock = false;
|
|
421
451
|
this.#pinned = null;
|
|
422
|
-
placeBox(this.#pinBox, null);
|
|
452
|
+
placeBox(this.#pinBox, null, this.#boxesVisible());
|
|
423
453
|
this.core?.sendData('state', { source: this.source, key: 'css.pin', value: 'off' });
|
|
424
454
|
this.core?.sendData('log', { source: this.source, message: 'CSS pin off.' });
|
|
425
455
|
this.#lastEl = null;
|
|
@@ -504,15 +534,16 @@ export class CSSAdapter {
|
|
|
504
534
|
|
|
505
535
|
#pin(el) {
|
|
506
536
|
this.#pinned = el;
|
|
507
|
-
placeBox(this.#pinBox, el);
|
|
537
|
+
placeBox(this.#pinBox, el, this.#boxesVisible());
|
|
508
538
|
if (el && typeof el.scrollIntoView === 'function') {
|
|
509
539
|
el.scrollIntoView({ block: 'center', inline: 'nearest', behavior: 'smooth' });
|
|
510
540
|
}
|
|
511
541
|
}
|
|
512
542
|
|
|
513
543
|
#placeBoxes() {
|
|
514
|
-
|
|
515
|
-
placeBox(this.#
|
|
544
|
+
const visible = this.#boxesVisible();
|
|
545
|
+
placeBox(this.#hoverBox, this.#lastEl, visible);
|
|
546
|
+
placeBox(this.#pinBox, this.#pinned, visible);
|
|
516
547
|
}
|
|
517
548
|
|
|
518
549
|
#mountBoxes() {
|
|
@@ -538,6 +569,8 @@ function collectImportantRules() {
|
|
|
538
569
|
const sheets = document.styleSheets;
|
|
539
570
|
for (let i = 0; i < sheets.length; i++) {
|
|
540
571
|
const sheet = sheets[i];
|
|
572
|
+
if (sheet.disabled === true) continue;
|
|
573
|
+
if (sheet.media && sheet.media.mediaText && !mediaMatches(sheet.media.mediaText)) continue;
|
|
541
574
|
let list = null;
|
|
542
575
|
try {
|
|
543
576
|
list = sheet.cssRules;
|
|
@@ -550,21 +583,21 @@ function collectImportantRules() {
|
|
|
550
583
|
return { rules, unreadable };
|
|
551
584
|
}
|
|
552
585
|
|
|
586
|
+
function mediaMatches(mediaText) {
|
|
587
|
+
try {
|
|
588
|
+
return typeof matchMedia === 'function' ? matchMedia(mediaText).matches : true;
|
|
589
|
+
} catch {
|
|
590
|
+
return true;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
|
|
553
594
|
function walkRules(list, source, into) {
|
|
554
595
|
if (!list) return;
|
|
555
596
|
for (let i = 0; i < list.length; i++) {
|
|
556
597
|
const rule = list[i];
|
|
557
598
|
if (!rule) continue;
|
|
558
599
|
if (rule.type === 4 && rule.media) {
|
|
559
|
-
|
|
560
|
-
try {
|
|
561
|
-
active = typeof matchMedia === 'function'
|
|
562
|
-
? matchMedia(rule.media.mediaText).matches
|
|
563
|
-
: true;
|
|
564
|
-
} catch {
|
|
565
|
-
active = true;
|
|
566
|
-
}
|
|
567
|
-
if (active) walkRules(rule.cssRules, source, into);
|
|
600
|
+
if (mediaMatches(rule.media.mediaText)) walkRules(rule.cssRules, source, into);
|
|
568
601
|
continue;
|
|
569
602
|
}
|
|
570
603
|
if (rule.type === 1 && rule.selectorText && rule.style) {
|
|
@@ -745,7 +778,9 @@ function pushInvisible(el, findings) {
|
|
|
745
778
|
findings.push(issue('invisible text (opacity 0)', ISSUE_RANK.invisible, 30));
|
|
746
779
|
}
|
|
747
780
|
const color = parseColor(style.color);
|
|
748
|
-
|
|
781
|
+
// Unknown syntax (oklch, lab, color(), color-mix): nothing to compare, nothing to report.
|
|
782
|
+
if (!color) return;
|
|
783
|
+
if (color.a === 0) {
|
|
749
784
|
findings.push(issue('invisible text (transparent color)', ISSUE_RANK.invisible, 30));
|
|
750
785
|
return;
|
|
751
786
|
}
|
|
@@ -1096,7 +1131,7 @@ function pickElement(x, y) {
|
|
|
1096
1131
|
const stack = document.elementsFromPoint(x, y);
|
|
1097
1132
|
for (let i = 0; i < stack.length; i++) {
|
|
1098
1133
|
const el = stack[i];
|
|
1099
|
-
if (!el || isBeeChrome(el)) continue;
|
|
1134
|
+
if (!el || isBeeChrome(el) || isReportNoise(el)) continue;
|
|
1100
1135
|
if (el === document.documentElement || el === document.body) continue;
|
|
1101
1136
|
return el;
|
|
1102
1137
|
}
|
|
@@ -1154,12 +1189,16 @@ function hasOwnText(el) {
|
|
|
1154
1189
|
function cssPath(el) {
|
|
1155
1190
|
if (!el || !el.tagName) return 'node';
|
|
1156
1191
|
const tag = el.tagName.toLowerCase();
|
|
1157
|
-
if (el.id) return `${tag}#${el.id}`;
|
|
1192
|
+
if (el.id) return `${tag}#${cssEscape(el.id)}`;
|
|
1158
1193
|
const classes = el.classList ? [...el.classList].slice(0, 2) : [];
|
|
1159
|
-
if (classes.length) return `${tag}.${classes.join('.')}`;
|
|
1194
|
+
if (classes.length) return `${tag}.${classes.map(cssEscape).join('.')}`;
|
|
1160
1195
|
return tag;
|
|
1161
1196
|
}
|
|
1162
1197
|
|
|
1198
|
+
function cssEscape(value) {
|
|
1199
|
+
return String(value).replace(/[^\w-]/g, '\\$&');
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1163
1202
|
function isSkippedTag(el) {
|
|
1164
1203
|
const tag = el.tagName;
|
|
1165
1204
|
return tag === 'SCRIPT' || tag === 'STYLE' || tag === 'LINK' || tag === 'META';
|
|
@@ -1179,7 +1218,10 @@ function touchesSheet(record) {
|
|
|
1179
1218
|
const name = record.target?.nodeName;
|
|
1180
1219
|
return name === 'STYLE' || name === 'LINK';
|
|
1181
1220
|
}
|
|
1182
|
-
|
|
1221
|
+
// Only what was added or removed: the target's whole subtree always holds some <style> or <link>.
|
|
1222
|
+
// A <style> that receives new text is the one target worth checking, and that check is O(1).
|
|
1223
|
+
if (record.target?.nodeName === 'STYLE') return true;
|
|
1224
|
+
const nodes = [];
|
|
1183
1225
|
if (record.addedNodes) {
|
|
1184
1226
|
for (let i = 0; i < record.addedNodes.length; i++) nodes.push(record.addedNodes[i]);
|
|
1185
1227
|
}
|
|
@@ -1220,9 +1262,9 @@ function makeBox(kind, border, fill) {
|
|
|
1220
1262
|
return node;
|
|
1221
1263
|
}
|
|
1222
1264
|
|
|
1223
|
-
function placeBox(node, el) {
|
|
1265
|
+
function placeBox(node, el, visible = true) {
|
|
1224
1266
|
if (!node) return;
|
|
1225
|
-
if (!el || typeof el.getBoundingClientRect !== 'function' || isBeeChrome(el)) {
|
|
1267
|
+
if (visible === false || !el || typeof el.getBoundingClientRect !== 'function' || isBeeChrome(el)) {
|
|
1226
1268
|
node.style.display = 'none';
|
|
1227
1269
|
return;
|
|
1228
1270
|
}
|
|
@@ -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.#
|
|
188
|
-
|
|
189
|
-
this.#observer
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
canvas.
|
|
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
|
-
|
|
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
|
|
|
@@ -481,6 +520,7 @@ function isBeeChrome(node) {
|
|
|
481
520
|
if (tag === 'BEE-LADYBUG-OVERLAY') return true;
|
|
482
521
|
if (el.hasAttribute?.('data-bee-ladybug-dom')) return true;
|
|
483
522
|
if (el.hasAttribute?.('data-bee-ladybug-canvas')) return true;
|
|
523
|
+
if (el.hasAttribute?.('data-bee-ladybug-css')) return true;
|
|
484
524
|
el = el.parentElement;
|
|
485
525
|
}
|
|
486
526
|
return false;
|
|
@@ -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.
|
|
13
|
+
export const BEE_LADYBUG_VERSION = '0.6.4';
|
|
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';
|