wcag-scanner 1.2.63 → 1.2.65

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.
@@ -1,12 +1,8 @@
1
1
  import React from 'react';
2
2
  export interface WcagDevOverlayProps {
3
- /** WCAG conformance level (default: 'AA') */
4
3
  level?: 'A' | 'AA' | 'AAA';
5
- /** Subset of rules to run. Omit to run all. */
6
4
  rules?: string[];
7
- /** Corner to anchor the overlay (default: 'bottom-right') */
8
5
  position?: 'bottom-right' | 'bottom-left';
9
- /** Delay in ms between DOM mutation and re-scan (default: 750) */
10
6
  debounce?: number;
11
7
  }
12
8
  export declare const WcagDevOverlay: React.FC<WcagDevOverlayProps>;
@@ -4,211 +4,106 @@ exports.WcagDevOverlay = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const browserScanner_1 = require("./browserScanner");
7
- // ─── Constants ───────────────────────────────────────────────────────────────
8
- const IMPACT_COLOR = {
9
- critical: '#ef4444',
10
- serious: '#f97316',
11
- moderate: '#eab308',
12
- minor: '#3b82f6',
7
+ // ─── Impact theme ──────────────────────────────────────────────────────────────
8
+ const IMPACT = {
9
+ critical: { color: '#dc2626', bg: '#fef2f2', border: '#fca5a5' },
10
+ serious: { color: '#ea580c', bg: '#fff7ed', border: '#fdba74' },
11
+ moderate: { color: '#ca8a04', bg: '#fefce8', border: '#fde047' },
12
+ minor: { color: '#2563eb', bg: '#eff6ff', border: '#93c5fd' },
13
13
  };
14
- const IMPACT_BG = {
15
- critical: '#fef2f2',
16
- serious: '#fff7ed',
17
- moderate: '#fefce8',
18
- minor: '#eff6ff',
19
- };
20
- const IMPACT_BORDER = {
21
- critical: '#fca5a5',
22
- serious: '#fdba74',
23
- moderate: '#fde047',
24
- minor: '#93c5fd',
25
- };
26
- // ─── Highlight helpers ────────────────────────────────────────────────────────
27
- let _prevHighlighted = null;
28
- let _prevOutline = '';
29
- let _prevBoxShadow = '';
30
- let _pinnedEl = null;
31
- let _pinnedOutline = '';
32
- let _pinnedBoxShadow = '';
14
+ const impactTheme = (impact) => { var _a; return (_a = IMPACT[impact]) !== null && _a !== void 0 ? _a : { color: '#6b7280', bg: '#f9fafb', border: '#e5e7eb' }; };
15
+ // ─── Highlight helpers ─────────────────────────────────────────────────────────
16
+ let _hovered = null;
17
+ let _pinned = null;
18
+ function restoreEl(saved) {
19
+ saved.el.style.outline = saved.outline;
20
+ saved.el.style.boxShadow = saved.shadow;
21
+ }
33
22
  function applyHighlight(el, color) {
34
- el.style.outline = `3px solid ${color}`;
35
- el.style.boxShadow = `0 0 0 6px ${color}33`;
23
+ el.style.outline = `2px solid ${color}`;
24
+ el.style.boxShadow = `0 0 0 4px ${color}28`;
36
25
  }
37
- function highlightElement(el, pinned = false) {
38
- if (!el)
39
- return;
40
- const htmlEl = el;
41
- if (pinned) {
42
- // Clear previous pin
43
- if (_pinnedEl && _pinnedEl !== el) {
44
- _pinnedEl.style.outline = _pinnedOutline;
45
- _pinnedEl.style.boxShadow = _pinnedBoxShadow;
46
- }
47
- _pinnedOutline = htmlEl.style.outline;
48
- _pinnedBoxShadow = htmlEl.style.boxShadow;
49
- _pinnedEl = el;
50
- applyHighlight(htmlEl, '#7c3aed');
51
- }
52
- else {
53
- if (_prevHighlighted) {
54
- _prevHighlighted.style.outline = _prevOutline;
55
- _prevHighlighted.style.boxShadow = _prevBoxShadow;
56
- _prevHighlighted = null;
57
- }
58
- // Don't hover-highlight if this element is pinned
59
- if (_pinnedEl === el)
60
- return;
61
- _prevOutline = htmlEl.style.outline;
62
- _prevBoxShadow = htmlEl.style.boxShadow;
63
- _prevHighlighted = el;
64
- applyHighlight(htmlEl, '#0ea5e9');
26
+ function hoverEl(el) {
27
+ if (_hovered) {
28
+ restoreEl(_hovered);
29
+ _hovered = null;
65
30
  }
66
- el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
31
+ if (!el || (_pinned === null || _pinned === void 0 ? void 0 : _pinned.el) === el)
32
+ return;
33
+ const h = el;
34
+ _hovered = { el: h, outline: h.style.outline, shadow: h.style.boxShadow };
35
+ applyHighlight(h, '#0ea5e9');
36
+ h.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
67
37
  }
68
38
  function clearHover() {
69
- if (_prevHighlighted) {
70
- _prevHighlighted.style.outline = _prevOutline;
71
- _prevHighlighted.style.boxShadow = _prevBoxShadow;
72
- _prevHighlighted = null;
39
+ if (_hovered) {
40
+ restoreEl(_hovered);
41
+ _hovered = null;
73
42
  }
74
43
  }
75
- function clearPin() {
76
- if (_pinnedEl) {
77
- _pinnedEl.style.outline = _pinnedOutline;
78
- _pinnedEl.style.boxShadow = _pinnedBoxShadow;
79
- _pinnedEl = null;
44
+ function pinEl(el) {
45
+ if ((_pinned === null || _pinned === void 0 ? void 0 : _pinned.el) === el) {
46
+ restoreEl(_pinned);
47
+ _pinned = null;
48
+ return false;
80
49
  }
50
+ if (_pinned)
51
+ restoreEl(_pinned);
52
+ if ((_hovered === null || _hovered === void 0 ? void 0 : _hovered.el) === el) {
53
+ restoreEl(_hovered);
54
+ _hovered = null;
55
+ }
56
+ const h = el;
57
+ _pinned = { el: h, outline: h.style.outline, shadow: h.style.boxShadow };
58
+ applyHighlight(h, '#7c3aed');
59
+ h.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
60
+ return true;
81
61
  }
82
62
  function clearAllHighlights() {
83
- clearHover();
84
- clearPin();
63
+ if (_hovered) {
64
+ restoreEl(_hovered);
65
+ _hovered = null;
66
+ }
67
+ if (_pinned) {
68
+ restoreEl(_pinned);
69
+ _pinned = null;
70
+ }
85
71
  }
86
- const ViolationCard = ({ item, index, pinned, onPin }) => {
87
- var _a, _b, _c;
72
+ const ViolationCard = ({ item, pinned, onPin }) => {
88
73
  const [expanded, setExpanded] = (0, react_1.useState)(false);
89
- const color = (_a = IMPACT_COLOR[item.impact]) !== null && _a !== void 0 ? _a : '#6b7280';
90
- const bg = (_b = IMPACT_BG[item.impact]) !== null && _b !== void 0 ? _b : '#f9fafb';
91
- const border = (_c = IMPACT_BORDER[item.impact]) !== null && _c !== void 0 ? _c : '#d1d5db';
92
- const cardStyle = {
93
- background: bg,
94
- border: `1px solid ${border}`,
95
- borderLeft: `4px solid ${color}`,
96
- borderRadius: 8,
97
- marginBottom: 8,
98
- overflow: 'hidden',
99
- transition: 'box-shadow 0.15s',
100
- boxShadow: pinned ? `0 0 0 2px ${color}` : undefined,
101
- };
102
- const headerRowStyle = {
103
- display: 'flex',
104
- alignItems: 'flex-start',
105
- gap: 8,
106
- padding: '10px 12px',
107
- cursor: item.domElement ? 'pointer' : 'default',
108
- };
109
- const badgeStyle = {
110
- display: 'inline-flex',
111
- alignItems: 'center',
112
- background: color,
113
- color: '#fff',
114
- fontSize: 9,
115
- fontWeight: 700,
116
- letterSpacing: '0.06em',
117
- textTransform: 'uppercase',
118
- borderRadius: 4,
119
- padding: '2px 6px',
120
- flexShrink: 0,
121
- marginTop: 2,
122
- };
123
- const descStyle = {
124
- fontSize: 13,
125
- fontWeight: 500,
126
- color: '#1e293b',
127
- lineHeight: 1.45,
128
- flex: 1,
129
- };
130
- const expandBtnStyle = {
131
- background: 'none',
132
- border: 'none',
133
- cursor: 'pointer',
134
- fontSize: 11,
135
- color: '#94a3b8',
136
- padding: '2px 4px',
137
- flexShrink: 0,
138
- marginTop: 1,
139
- lineHeight: 1,
140
- };
141
- const detailsStyle = {
142
- padding: '0 12px 10px',
143
- borderTop: `1px solid ${border}`,
144
- };
145
- const codeStyle = {
146
- fontFamily: '"JetBrains Mono", "Fira Code", "Cascadia Code", monospace',
147
- fontSize: 11,
148
- background: '#0f172a',
149
- color: '#e2e8f0',
150
- borderRadius: 6,
151
- padding: '6px 10px',
152
- marginTop: 8,
153
- display: 'block',
154
- whiteSpace: 'pre-wrap',
155
- wordBreak: 'break-all',
156
- overflowWrap: 'break-word',
157
- maxHeight: 80,
158
- overflow: 'auto',
159
- };
160
- const pathStyle = {
161
- fontFamily: 'monospace',
162
- fontSize: 10,
163
- color: '#64748b',
164
- background: '#f1f5f9',
165
- border: '1px solid #e2e8f0',
166
- borderRadius: 4,
167
- padding: '3px 7px',
168
- marginTop: 6,
169
- display: 'inline-block',
170
- maxWidth: '100%',
171
- overflow: 'hidden',
172
- textOverflow: 'ellipsis',
173
- whiteSpace: 'nowrap',
174
- };
175
- const metaRowStyle = {
176
- display: 'flex',
177
- flexWrap: 'wrap',
178
- gap: 6,
179
- marginTop: 8,
180
- alignItems: 'center',
181
- };
182
- const wcagTagStyle = {
183
- fontSize: 10,
184
- fontWeight: 600,
185
- color: '#7c3aed',
186
- background: '#f5f3ff',
187
- border: '1px solid #ddd6fe',
188
- borderRadius: 4,
189
- padding: '2px 6px',
190
- };
191
- const helpStyle = {
192
- fontSize: 11,
193
- color: '#475569',
194
- fontStyle: 'italic',
195
- marginTop: 6,
196
- lineHeight: 1.5,
197
- };
198
- const pinIndicatorStyle = {
199
- fontSize: 10,
200
- color: '#7c3aed',
201
- fontWeight: 700,
202
- marginLeft: 4,
203
- };
204
- return ((0, jsx_runtime_1.jsxs)("div", { style: cardStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: headerRowStyle, onMouseEnter: () => highlightElement(item.domElement), onMouseLeave: () => clearHover(), onClick: () => item.domElement && onPin(item.domElement), title: item.domElement ? (pinned ? 'Click to unpin' : 'Click to pin element') : undefined, children: [(0, jsx_runtime_1.jsx)("span", { style: badgeStyle, children: item.impact }), (0, jsx_runtime_1.jsxs)("span", { style: descStyle, children: [item.description, pinned && (0, jsx_runtime_1.jsx)("span", { style: pinIndicatorStyle, children: "\uD83D\uDCCD" })] }), (0, jsx_runtime_1.jsx)("button", { style: expandBtnStyle, onClick: e => { e.stopPropagation(); setExpanded(x => !x); }, title: expanded ? 'Collapse' : 'Expand details', children: expanded ? '▲' : '▼' })] }), expanded && ((0, jsx_runtime_1.jsxs)("div", { style: detailsStyle, children: [item.elementPath && ((0, jsx_runtime_1.jsx)("span", { style: pathStyle, title: "Element path in DOM", children: item.elementPath })), item.snippet && ((0, jsx_runtime_1.jsx)("code", { style: codeStyle, children: item.snippet })), item.help && ((0, jsx_runtime_1.jsx)("div", { style: helpStyle, children: item.help })), item.wcag && item.wcag.length > 0 && ((0, jsx_runtime_1.jsx)("div", { style: metaRowStyle, children: item.wcag.map(w => ((0, jsx_runtime_1.jsxs)("span", { style: wcagTagStyle, children: ["WCAG ", w] }, w))) }))] }))] }));
74
+ const { color, bg, border } = impactTheme(item.impact);
75
+ const clickable = !!item.domElement;
76
+ return ((0, jsx_runtime_1.jsxs)("div", { style: {
77
+ background: bg,
78
+ borderRadius: 8,
79
+ marginBottom: 6,
80
+ overflow: 'hidden',
81
+ outline: pinned ? `2px solid ${color}` : `1px solid ${border}`,
82
+ outlineOffset: pinned ? 1 : 0,
83
+ borderLeft: `3px solid ${color}`,
84
+ }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'flex-start', gap: 8, padding: '9px 10px', cursor: clickable ? 'pointer' : 'default' }, onMouseEnter: () => hoverEl(item.domElement), onMouseLeave: () => clearHover(), onClick: () => item.domElement && onPin(item.domElement), children: [(0, jsx_runtime_1.jsx)("span", { style: {
85
+ fontSize: 9, fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase',
86
+ background: color, color: '#fff', borderRadius: 4, padding: '2px 5px', flexShrink: 0, marginTop: 2,
87
+ }, children: item.impact }), (0, jsx_runtime_1.jsxs)("span", { style: { fontSize: 12, fontWeight: 500, color: '#1e293b', lineHeight: 1.5, flex: 1 }, children: [item.description, pinned && (0, jsx_runtime_1.jsx)("span", { style: { marginLeft: 5, fontSize: 10 }, children: "\uD83D\uDCCD" })] }), (0, jsx_runtime_1.jsx)("button", { style: { background: 'none', border: 'none', cursor: 'pointer', color: '#94a3b8', fontSize: 11, padding: '1px 4px', flexShrink: 0 }, onClick: e => { e.stopPropagation(); setExpanded(x => !x); }, title: expanded ? 'Collapse' : 'Show details', children: expanded ? '▲' : '▼' })] }), expanded && ((0, jsx_runtime_1.jsxs)("div", { style: { padding: '0 10px 10px', borderTop: `1px solid ${border}` }, children: [item.elementPath && ((0, jsx_runtime_1.jsx)("code", { style: {
88
+ display: 'block', marginTop: 8, fontSize: 10, color: '#475569',
89
+ background: '#f1f5f9', border: '1px solid #e2e8f0', borderRadius: 4,
90
+ padding: '3px 7px', fontFamily: 'monospace', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
91
+ }, children: item.elementPath })), item.snippet && ((0, jsx_runtime_1.jsx)("code", { style: {
92
+ display: 'block', marginTop: 6, fontSize: 10,
93
+ background: '#0f172a', color: '#e2e8f0', borderRadius: 5,
94
+ padding: '5px 8px', fontFamily: 'monospace', whiteSpace: 'pre-wrap', wordBreak: 'break-all',
95
+ maxHeight: 72, overflow: 'auto',
96
+ }, children: item.snippet })), item.help && ((0, jsx_runtime_1.jsx)("p", { style: { margin: '7px 0 0', fontSize: 11, color: '#475569', fontStyle: 'italic', lineHeight: 1.5 }, children: item.help })), item.wcag && item.wcag.length > 0 && ((0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', flexWrap: 'wrap', gap: 4, marginTop: 7 }, children: item.wcag.map(w => ((0, jsx_runtime_1.jsxs)("span", { style: {
97
+ fontSize: 10, fontWeight: 600, color: '#7c3aed',
98
+ background: '#f5f3ff', border: '1px solid #ddd6fe', borderRadius: 4, padding: '1px 6px',
99
+ }, children: ["WCAG ", w] }, w))) }))] }))] }));
205
100
  };
206
- // ─── Main Overlay ─────────────────────────────────────────────────────────────
101
+ // ─── Main Overlay ──────────────────────────────────────────────────────────────
207
102
  const WcagDevOverlay = ({ level = 'AA', rules, position = 'bottom-right', debounce = 750, }) => {
208
- var _a, _b, _c, _d, _e;
103
+ var _a, _b, _c;
209
104
  const [open, setOpen] = (0, react_1.useState)(() => {
210
105
  try {
211
- return sessionStorage.getItem('wcag-overlay-open') === '1';
106
+ return sessionStorage.getItem('wcag-open') === '1';
212
107
  }
213
108
  catch (_a) {
214
109
  return false;
@@ -220,40 +115,49 @@ const WcagDevOverlay = ({ level = 'AA', rules, position = 'bottom-right', deboun
220
115
  const [results, setResults] = (0, react_1.useState)(null);
221
116
  const [lastScan, setLastScan] = (0, react_1.useState)(null);
222
117
  const [pinnedEl, setPinnedEl] = (0, react_1.useState)(null);
223
- // Drag state
118
+ // Drag
224
119
  const [pos, setPos] = (0, react_1.useState)(null);
225
120
  const dragging = (0, react_1.useRef)(false);
226
121
  const dragOffset = (0, react_1.useRef)({ x: 0, y: 0 });
227
122
  const observerRef = (0, react_1.useRef)(null);
228
123
  const timerRef = (0, react_1.useRef)(null);
229
124
  const overlayRef = (0, react_1.useRef)(null);
230
- const panelRef = (0, react_1.useRef)(null);
231
- // ── Persist open state ──────────────────────────────────────────────────
125
+ const scanningRef = (0, react_1.useRef)(false);
126
+ const cooldownRef = (0, react_1.useRef)(false);
127
+ // ── Persist open state ────────────────────────────────────────────────────
232
128
  (0, react_1.useEffect)(() => {
233
129
  try {
234
- sessionStorage.setItem('wcag-overlay-open', open ? '1' : '0');
130
+ sessionStorage.setItem('wcag-open', open ? '1' : '0');
235
131
  }
236
- catch ( /* ignore */_a) { /* ignore */ }
132
+ catch ( /* */_a) { /* */ }
237
133
  if (!open)
238
134
  clearAllHighlights();
239
135
  }, [open]);
240
- // ── Scan ────────────────────────────────────────────────────────────────
136
+ // ── Scan ──────────────────────────────────────────────────────────────────
241
137
  const scan = (0, react_1.useCallback)(async () => {
138
+ if (scanningRef.current)
139
+ return;
140
+ scanningRef.current = true;
242
141
  setScanning(true);
243
142
  try {
244
- const opts = { level, rules };
245
- const res = await (0, browserScanner_1.scanBrowserPage)(opts);
143
+ const res = await (0, browserScanner_1.scanBrowserPage)({ level, rules });
246
144
  setResults(res);
247
145
  setLastScan(new Date());
248
146
  }
249
147
  finally {
148
+ scanningRef.current = false;
250
149
  setScanning(false);
150
+ // Cooldown prevents the observer from immediately re-triggering after scan
151
+ cooldownRef.current = true;
152
+ setTimeout(() => { cooldownRef.current = false; }, 1200);
251
153
  }
252
154
  }, [level, rules]);
253
155
  (0, react_1.useEffect)(() => { scan(); }, [scan]);
254
- // ── MutationObserver ────────────────────────────────────────────────────
156
+ // ── MutationObserver ──────────────────────────────────────────────────────
255
157
  (0, react_1.useEffect)(() => {
256
158
  observerRef.current = new MutationObserver((mutations) => {
159
+ if (scanningRef.current || cooldownRef.current)
160
+ return;
257
161
  if (overlayRef.current &&
258
162
  mutations.every(m => overlayRef.current.contains(m.target)))
259
163
  return;
@@ -265,7 +169,9 @@ const WcagDevOverlay = ({ level = 'AA', rules, position = 'bottom-right', deboun
265
169
  childList: true,
266
170
  subtree: true,
267
171
  attributes: true,
268
- attributeFilter: ['class', 'style', 'hidden', 'aria-hidden', 'role', 'alt', 'src', 'href'],
172
+ // 'style' excluded our highlight helper modifies inline styles on
173
+ // page elements which would otherwise cause an infinite rescan loop
174
+ attributeFilter: ['class', 'hidden', 'aria-hidden', 'role', 'alt', 'src', 'href'],
269
175
  });
270
176
  return () => {
271
177
  var _a;
@@ -275,38 +181,26 @@ const WcagDevOverlay = ({ level = 'AA', rules, position = 'bottom-right', deboun
275
181
  clearAllHighlights();
276
182
  };
277
183
  }, [scan, debounce]);
278
- // ── Keyboard shortcut Alt+Shift+W ───────────────────────────────────────
184
+ // ── Keyboard shortcut Alt+Shift+W ─────────────────────────────────────────
279
185
  (0, react_1.useEffect)(() => {
280
186
  const handler = (e) => {
281
- if (e.altKey && e.shiftKey && e.key === 'W') {
187
+ if (e.altKey && e.shiftKey && e.key === 'W')
282
188
  setOpen(o => !o);
283
- }
284
189
  };
285
190
  window.addEventListener('keydown', handler);
286
191
  return () => window.removeEventListener('keydown', handler);
287
192
  }, []);
288
- // ── Pin handler ─────────────────────────────────────────────────────────
193
+ // ── Pin handler ───────────────────────────────────────────────────────────
289
194
  const handlePin = (0, react_1.useCallback)((el) => {
290
- if (!el)
291
- return;
292
- if (_pinnedEl === el) {
293
- clearPin();
294
- setPinnedEl(null);
295
- }
296
- else {
297
- highlightElement(el, true);
298
- setPinnedEl(el);
299
- }
195
+ const nowPinned = pinEl(el);
196
+ setPinnedEl(nowPinned ? el : null);
300
197
  }, []);
301
- // ── Drag handlers ────────────────────────────────────────────────────────
198
+ // ── Drag ──────────────────────────────────────────────────────────────────
302
199
  const onDragStart = (e) => {
303
200
  var _a, _b, _c;
304
201
  dragging.current = true;
305
202
  const rect = (_a = overlayRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
306
- dragOffset.current = {
307
- x: e.clientX - ((_b = rect === null || rect === void 0 ? void 0 : rect.left) !== null && _b !== void 0 ? _b : 0),
308
- y: e.clientY - ((_c = rect === null || rect === void 0 ? void 0 : rect.top) !== null && _c !== void 0 ? _c : 0),
309
- };
203
+ dragOffset.current = { x: e.clientX - ((_b = rect === null || rect === void 0 ? void 0 : rect.left) !== null && _b !== void 0 ? _b : 0), y: e.clientY - ((_c = rect === null || rect === void 0 ? void 0 : rect.top) !== null && _c !== void 0 ? _c : 0) };
310
204
  e.preventDefault();
311
205
  };
312
206
  (0, react_1.useEffect)(() => {
@@ -318,181 +212,107 @@ const WcagDevOverlay = ({ level = 'AA', rules, position = 'bottom-right', deboun
318
212
  const onUp = () => { dragging.current = false; };
319
213
  window.addEventListener('mousemove', onMove);
320
214
  window.addEventListener('mouseup', onUp);
321
- return () => {
322
- window.removeEventListener('mousemove', onMove);
323
- window.removeEventListener('mouseup', onUp);
324
- };
215
+ return () => { window.removeEventListener('mousemove', onMove); window.removeEventListener('mouseup', onUp); };
325
216
  }, []);
326
- // ── Derived state ────────────────────────────────────────────────────────
327
- const violationCount = (_a = results === null || results === void 0 ? void 0 : results.violations.length) !== null && _a !== void 0 ? _a : 0;
328
- const warningCount = (_b = results === null || results === void 0 ? void 0 : results.warnings.length) !== null && _b !== void 0 ? _b : 0;
217
+ // ── Derived ───────────────────────────────────────────────────────────────
218
+ const vCount = (_a = results === null || results === void 0 ? void 0 : results.violations.length) !== null && _a !== void 0 ? _a : 0;
219
+ const wCount = (_b = results === null || results === void 0 ? void 0 : results.warnings.length) !== null && _b !== void 0 ? _b : 0;
220
+ const pCount = (_c = results === null || results === void 0 ? void 0 : results.passes.length) !== null && _c !== void 0 ? _c : 0;
329
221
  const isLeft = position === 'bottom-left';
330
222
  const rawItems = tab === 'violations' ? results === null || results === void 0 ? void 0 : results.violations : results === null || results === void 0 ? void 0 : results.warnings;
331
- const items = filter === 'all'
332
- ? rawItems
333
- : rawItems === null || rawItems === void 0 ? void 0 : rawItems.filter(i => i.impact === filter);
223
+ const items = filter === 'all' ? rawItems : rawItems === null || rawItems === void 0 ? void 0 : rawItems.filter(i => i.impact === filter);
334
224
  const isEmpty = !items || items.length === 0;
335
- const elapsed = lastScan
336
- ? (() => {
337
- const s = Math.round((Date.now() - lastScan.getTime()) / 1000);
338
- return s < 5 ? 'just now' : s < 60 ? `${s}s ago` : `${Math.round(s / 60)}m ago`;
339
- })()
340
- : '—';
341
- // ── Styles ───────────────────────────────────────────────────────────────
225
+ const elapsed = lastScan ? (() => {
226
+ const s = Math.round((Date.now() - lastScan.getTime()) / 1000);
227
+ return s < 5 ? 'just now' : s < 60 ? `${s}s ago` : `${Math.round(s / 60)}m ago`;
228
+ })() : '';
229
+ // ── Styles ────────────────────────────────────────────────────────────────
342
230
  const anchorStyle = pos
343
231
  ? { position: 'fixed', top: pos.y, left: pos.x, zIndex: 2147483647, fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' }
344
- : {
345
- position: 'fixed',
346
- bottom: 20,
347
- [isLeft ? 'left' : 'right']: 20,
348
- zIndex: 2147483647,
349
- fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
350
- };
351
- const toggleStyle = {
352
- display: 'flex',
353
- alignItems: 'center',
354
- gap: 7,
355
- background: violationCount > 0 ? '#7c3aed' : scanning ? '#475569' : '#16a34a',
356
- color: '#fff',
357
- border: 'none',
358
- borderRadius: 24,
359
- padding: '9px 16px',
360
- fontSize: 13,
361
- fontWeight: 600,
362
- cursor: 'pointer',
363
- boxShadow: '0 4px 16px rgba(0,0,0,0.22)',
364
- transition: 'transform 0.1s, box-shadow 0.1s',
365
- userSelect: 'none',
232
+ : { position: 'fixed', bottom: 20, [isLeft ? 'left' : 'right']: 20, zIndex: 2147483647, fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif' };
233
+ const btnColor = scanning ? '#64748b' : vCount > 0 ? '#7c3aed' : '#16a34a';
234
+ const s = {
235
+ toggle: {
236
+ display: 'flex', alignItems: 'center', gap: 6,
237
+ background: btnColor, color: '#fff', border: 'none', borderRadius: 22,
238
+ padding: '8px 14px', fontSize: 12, fontWeight: 600, cursor: 'pointer',
239
+ boxShadow: '0 2px 12px rgba(0,0,0,0.2)', userSelect: 'none',
240
+ },
241
+ badge: {
242
+ background: 'rgba(255,255,255,0.22)', borderRadius: 9,
243
+ padding: '1px 6px', fontSize: 11, fontWeight: 700,
244
+ },
245
+ panel: {
246
+ position: 'absolute',
247
+ bottom: pos ? undefined : 48,
248
+ top: pos ? 48 : undefined,
249
+ [isLeft ? 'left' : 'right']: 0,
250
+ width: 400,
251
+ maxHeight: '74vh',
252
+ background: '#ffffff',
253
+ borderRadius: 10,
254
+ boxShadow: '0 8px 40px rgba(0,0,0,0.16), 0 0 0 1px rgba(0,0,0,0.07)',
255
+ display: 'flex',
256
+ flexDirection: 'column',
257
+ overflow: 'hidden',
258
+ },
259
+ header: {
260
+ display: 'flex', alignItems: 'center', gap: 8,
261
+ padding: '10px 12px', background: '#0f172a',
262
+ cursor: 'grab', userSelect: 'none', flexShrink: 0,
263
+ },
264
+ headerBtn: {
265
+ background: 'none', border: 'none', cursor: 'pointer',
266
+ color: '#64748b', fontSize: 14, padding: '2px 5px', lineHeight: 1, borderRadius: 4,
267
+ },
268
+ summary: {
269
+ display: 'flex', gap: 6, padding: '8px 12px',
270
+ borderBottom: '1px solid #f1f5f9', background: '#f8fafc', flexShrink: 0,
271
+ },
272
+ toolbar: {
273
+ display: 'flex', alignItems: 'center',
274
+ borderBottom: '1px solid #f1f5f9', padding: '0 12px',
275
+ gap: 2, flexShrink: 0,
276
+ },
277
+ list: {
278
+ flex: 1, overflowY: 'auto', padding: '10px 10px',
279
+ },
280
+ footer: {
281
+ display: 'flex', alignItems: 'center', justifyContent: 'space-between',
282
+ padding: '7px 12px', borderTop: '1px solid #f1f5f9',
283
+ background: '#f8fafc', fontSize: 10, color: '#94a3b8', flexShrink: 0,
284
+ },
366
285
  };
367
- const badgeCountStyle = {
368
- background: 'rgba(255,255,255,0.25)',
369
- borderRadius: 10,
370
- padding: '1px 7px',
371
- fontSize: 12,
372
- fontWeight: 700,
373
- };
374
- const panelStyle = {
375
- position: 'absolute',
376
- bottom: pos ? undefined : 54,
377
- top: pos ? 54 : undefined,
378
- [isLeft ? 'left' : 'right']: 0,
379
- width: 420,
380
- maxHeight: '75vh',
381
- background: '#fff',
382
- borderRadius: 12,
383
- boxShadow: '0 24px 64px rgba(0,0,0,0.2), 0 0 0 1px rgba(0,0,0,0.08)',
384
- display: 'flex',
385
- flexDirection: 'column',
386
- overflow: 'hidden',
387
- };
388
- const headerStyle = {
389
- display: 'flex',
390
- alignItems: 'center',
391
- padding: '11px 14px',
392
- background: '#0f172a',
393
- gap: 8,
394
- cursor: 'grab',
395
- userSelect: 'none',
396
- };
397
- const summaryStyle = {
398
- display: 'flex',
399
- gap: 8,
400
- padding: '10px 14px',
401
- borderBottom: '1px solid #e2e8f0',
402
- background: '#f8fafc',
403
- };
404
- const toolbarStyle = {
405
- display: 'flex',
406
- alignItems: 'center',
407
- borderBottom: '1px solid #e2e8f0',
408
- padding: '0 14px',
409
- gap: 4,
410
- };
411
- const tabBtnStyle = (active) => ({
412
- padding: '8px 12px',
413
- fontSize: 13,
414
- fontWeight: active ? 600 : 400,
415
- color: active ? '#7c3aed' : '#64748b',
416
- borderBottom: active ? '2px solid #7c3aed' : '2px solid transparent',
417
- cursor: 'pointer',
418
- background: 'none',
419
- border: 'none',
420
- borderBottomColor: active ? '#7c3aed' : 'transparent',
421
- borderBottomStyle: 'solid',
422
- borderBottomWidth: 2,
423
- whiteSpace: 'nowrap',
286
+ const chip = (color, count) => ({
287
+ display: 'flex', alignItems: 'center', gap: 3, fontSize: 11, fontWeight: 600,
288
+ color: count > 0 ? color : '#94a3b8',
289
+ background: count > 0 ? `${color}14` : '#f1f5f9',
290
+ border: `1px solid ${count > 0 ? color + '35' : '#e2e8f0'}`,
291
+ borderRadius: 5, padding: '3px 8px', flexShrink: 0,
424
292
  });
425
- const filterSelectStyle = {
426
- marginLeft: 'auto',
427
- fontSize: 11,
428
- border: '1px solid #e2e8f0',
429
- borderRadius: 6,
430
- padding: '3px 8px',
431
- color: '#475569',
432
- background: '#fff',
433
- cursor: 'pointer',
434
- outline: 'none',
435
- };
436
- const listStyle = {
437
- flex: 1,
438
- overflowY: 'auto',
439
- padding: '12px 12px',
440
- };
441
- const footerStyle = {
442
- display: 'flex',
443
- alignItems: 'center',
444
- justifyContent: 'space-between',
445
- padding: '8px 14px',
446
- borderTop: '1px solid #e2e8f0',
447
- background: '#f8fafc',
448
- fontSize: 11,
449
- color: '#94a3b8',
450
- };
451
- const rescanBtnStyle = {
452
- background: '#7c3aed',
453
- color: '#fff',
454
- border: 'none',
455
- borderRadius: 6,
456
- padding: '4px 12px',
457
- fontSize: 11,
458
- fontWeight: 600,
459
- cursor: scanning ? 'wait' : 'pointer',
460
- opacity: scanning ? 0.6 : 1,
461
- };
462
- const chipStyle = (color, active = true) => ({
463
- display: 'flex',
464
- alignItems: 'center',
465
- gap: 4,
466
- fontSize: 11,
467
- fontWeight: 600,
468
- color: active ? color : '#94a3b8',
469
- background: active ? `${color}18` : '#f1f5f9',
470
- border: `1px solid ${active ? color + '40' : '#e2e8f0'}`,
471
- borderRadius: 6,
472
- padding: '4px 10px',
473
- flexShrink: 0,
293
+ const tabBtn = (active) => ({
294
+ padding: '7px 10px', fontSize: 12, fontWeight: active ? 600 : 400,
295
+ color: active ? '#7c3aed' : '#64748b', cursor: 'pointer',
296
+ background: 'none', border: 'none',
297
+ boxShadow: active ? 'inset 0 -2px 0 #7c3aed' : 'none',
298
+ whiteSpace: 'nowrap',
474
299
  });
475
- const iconBtnStyle = {
476
- background: 'none',
477
- border: 'none',
478
- cursor: 'pointer',
479
- color: '#94a3b8',
480
- padding: '3px 6px',
481
- fontSize: 14,
482
- lineHeight: 1,
483
- borderRadius: 4,
484
- transition: 'color 0.15s',
300
+ const rescanBtn = {
301
+ background: '#7c3aed', color: '#fff', border: 'none', borderRadius: 5,
302
+ padding: '4px 10px', fontSize: 10, fontWeight: 600,
303
+ cursor: scanning ? 'wait' : 'pointer', opacity: scanning ? 0.55 : 1,
485
304
  };
486
- return ((0, jsx_runtime_1.jsxs)("div", { ref: overlayRef, style: anchorStyle, "data-wcag-overlay": "true", children: [open && ((0, jsx_runtime_1.jsxs)("div", { ref: panelRef, style: panelStyle, role: "dialog", "aria-label": "WCAG Dev Inspector", children: [(0, jsx_runtime_1.jsxs)("div", { style: headerStyle, onMouseDown: onDragStart, children: [(0, jsx_runtime_1.jsx)("span", { style: { fontSize: 15, lineHeight: 1 }, children: "\u267F" }), (0, jsx_runtime_1.jsx)("span", { style: { fontWeight: 700, fontSize: 13, flex: 1, color: '#f1f5f9', letterSpacing: '0.01em' }, children: "WCAG Dev Inspector" }), (0, jsx_runtime_1.jsx)("span", { style: {
487
- fontSize: 10, fontWeight: 700, color: '#a78bfa',
488
- background: '#4c1d95', borderRadius: 4, padding: '2px 7px', letterSpacing: '0.05em',
489
- }, children: level }), (0, jsx_runtime_1.jsx)("button", { onClick: scan, disabled: scanning, title: "Rescan page", style: { ...iconBtnStyle, color: scanning ? '#475569' : '#94a3b8', fontSize: 16 }, children: scanning ? '⏳' : '↻' }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setOpen(false), title: "Close (Alt+Shift+W)", style: { ...iconBtnStyle, fontSize: 15 }, children: "\u2715" })] }), (0, jsx_runtime_1.jsxs)("div", { style: summaryStyle, children: [(0, jsx_runtime_1.jsxs)("span", { style: chipStyle('#ef4444', violationCount > 0), children: ["\u2717 ", violationCount, " violation", violationCount !== 1 ? 's' : ''] }), (0, jsx_runtime_1.jsxs)("span", { style: chipStyle('#f97316', warningCount > 0), children: ["\u26A0 ", warningCount, " warning", warningCount !== 1 ? 's' : ''] }), (0, jsx_runtime_1.jsxs)("span", { style: chipStyle('#16a34a', ((_c = results === null || results === void 0 ? void 0 : results.passes.length) !== null && _c !== void 0 ? _c : 0) > 0), children: ["\u2713 ", (_d = results === null || results === void 0 ? void 0 : results.passes.length) !== null && _d !== void 0 ? _d : 0, " pass", ((_e = results === null || results === void 0 ? void 0 : results.passes.length) !== null && _e !== void 0 ? _e : 0) !== 1 ? 'es' : ''] })] }), (0, jsx_runtime_1.jsxs)("div", { style: toolbarStyle, children: [['violations', 'warnings'].map(t => ((0, jsx_runtime_1.jsx)("button", { style: tabBtnStyle(tab === t), onClick: () => setTab(t), children: t === 'violations'
490
- ? `Violations (${violationCount})`
491
- : `Warnings (${warningCount})` }, t))), (0, jsx_runtime_1.jsxs)("select", { style: filterSelectStyle, value: filter, onChange: e => setFilter(e.target.value), title: "Filter by impact", children: [(0, jsx_runtime_1.jsx)("option", { value: "all", children: "All impacts" }), (0, jsx_runtime_1.jsx)("option", { value: "critical", children: "Critical" }), (0, jsx_runtime_1.jsx)("option", { value: "serious", children: "Serious" }), (0, jsx_runtime_1.jsx)("option", { value: "moderate", children: "Moderate" }), (0, jsx_runtime_1.jsx)("option", { value: "minor", children: "Minor" })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: listStyle, children: [scanning && !results && ((0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center', color: '#94a3b8', padding: '32px 0', fontSize: 13 }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: 24, marginBottom: 10 }, children: "\u23F3" }), "Scanning\u2026"] })), !scanning && isEmpty && ((0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center', padding: '32px 0' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: 32, marginBottom: 10 }, children: tab === 'violations' ? '✅' : '🔕' }), (0, jsx_runtime_1.jsxs)("div", { style: { color: '#64748b', fontSize: 13, fontWeight: 500 }, children: ["No ", tab, " found"] }), filter !== 'all' && ((0, jsx_runtime_1.jsxs)("div", { style: { color: '#94a3b8', fontSize: 11, marginTop: 6 }, children: ["(filter: ", filter, " \u2014 ", (0, jsx_runtime_1.jsx)("button", { style: { background: 'none', border: 'none', color: '#7c3aed', cursor: 'pointer', fontSize: 11, padding: 0 }, onClick: () => setFilter('all'), children: "clear" }), ")"] }))] })), items === null || items === void 0 ? void 0 : items.map((item, i) => ((0, jsx_runtime_1.jsx)(ViolationCard, { item: item, index: i, pinned: pinnedEl === item.domElement && item.domElement != null, onPin: handlePin }, `${item.rule}-${i}`)))] }), (0, jsx_runtime_1.jsxs)("div", { style: footerStyle, children: [(0, jsx_runtime_1.jsxs)("span", { children: [pinnedEl ? '📍 element pinned · ' : '', "Scanned ", elapsed, results && ` · ${results.duration}ms`] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: 8, alignItems: 'center' }, children: [pinnedEl && ((0, jsx_runtime_1.jsx)("button", { style: { ...rescanBtnStyle, background: '#64748b' }, onClick: () => { clearPin(); setPinnedEl(null); }, children: "Unpin" })), (0, jsx_runtime_1.jsx)("button", { style: rescanBtnStyle, onClick: scan, disabled: scanning, children: scanning ? 'Scanning…' : 'Rescan' })] })] })] })), (0, jsx_runtime_1.jsxs)("button", { style: toggleStyle, onClick: () => setOpen(o => !o), title: "Toggle WCAG Dev Inspector (Alt+Shift+W)", "aria-expanded": open, "aria-label": `WCAG Inspector: ${violationCount} violation${violationCount !== 1 ? 's' : ''}`, children: [(0, jsx_runtime_1.jsx)("span", { style: { fontSize: 16 }, children: "\u267F" }), scanning
492
- ? (0, jsx_runtime_1.jsx)("span", { style: { opacity: 0.8, fontSize: 12 }, children: "scanning\u2026" })
493
- : violationCount > 0
494
- ? (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { style: badgeCountStyle, children: violationCount }), " ", (0, jsx_runtime_1.jsx)("span", { style: { fontSize: 12 }, children: "issues" })] })
495
- : (0, jsx_runtime_1.jsx)("span", { style: badgeCountStyle, children: "\u2713" })] })] }));
305
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: overlayRef, style: anchorStyle, "data-wcag-overlay": "true", children: [open && ((0, jsx_runtime_1.jsxs)("div", { style: s.panel, role: "dialog", "aria-label": "WCAG Dev Inspector", children: [(0, jsx_runtime_1.jsxs)("div", { style: s.header, onMouseDown: onDragStart, children: [(0, jsx_runtime_1.jsx)("span", { style: { fontSize: 14 }, children: "\u267F" }), (0, jsx_runtime_1.jsx)("span", { style: { fontWeight: 700, fontSize: 13, flex: 1, color: '#f1f5f9' }, children: "WCAG Inspector" }), (0, jsx_runtime_1.jsx)("span", { style: {
306
+ fontSize: 9, fontWeight: 700, color: '#a78bfa',
307
+ background: '#4c1d95', borderRadius: 4, padding: '2px 6px', letterSpacing: '0.05em',
308
+ }, children: level }), (0, jsx_runtime_1.jsx)("button", { onClick: scan, disabled: scanning, title: "Rescan", style: s.headerBtn, children: scanning ? '⏳' : '↻' }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setOpen(false), title: "Close (Alt+Shift+W)", style: s.headerBtn, children: "\u2715" })] }), (0, jsx_runtime_1.jsxs)("div", { style: s.summary, children: [(0, jsx_runtime_1.jsxs)("span", { style: chip('#dc2626', vCount), children: ["\u2717 ", vCount, " violation", vCount !== 1 ? 's' : ''] }), (0, jsx_runtime_1.jsxs)("span", { style: chip('#ea580c', wCount), children: ["\u26A0 ", wCount, " warning", wCount !== 1 ? 's' : ''] }), (0, jsx_runtime_1.jsxs)("span", { style: chip('#16a34a', pCount), children: ["\u2713 ", pCount, " pass", pCount !== 1 ? 'es' : ''] })] }), (0, jsx_runtime_1.jsxs)("div", { style: s.toolbar, children: [(0, jsx_runtime_1.jsxs)("button", { style: tabBtn(tab === 'violations'), onClick: () => setTab('violations'), children: ["Violations (", vCount, ")"] }), (0, jsx_runtime_1.jsxs)("button", { style: tabBtn(tab === 'warnings'), onClick: () => setTab('warnings'), children: ["Warnings (", wCount, ")"] }), (0, jsx_runtime_1.jsxs)("select", { style: {
309
+ marginLeft: 'auto', fontSize: 10, border: '1px solid #e2e8f0',
310
+ borderRadius: 5, padding: '3px 6px', color: '#475569', background: '#fff', cursor: 'pointer', outline: 'none',
311
+ }, value: filter, onChange: e => setFilter(e.target.value), children: [(0, jsx_runtime_1.jsx)("option", { value: "all", children: "All" }), (0, jsx_runtime_1.jsx)("option", { value: "critical", children: "Critical" }), (0, jsx_runtime_1.jsx)("option", { value: "serious", children: "Serious" }), (0, jsx_runtime_1.jsx)("option", { value: "moderate", children: "Moderate" }), (0, jsx_runtime_1.jsx)("option", { value: "minor", children: "Minor" })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: s.list, children: [scanning && !results && ((0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center', color: '#94a3b8', padding: '28px 0', fontSize: 12 }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: 22, marginBottom: 8 }, children: "\u23F3" }), "Scanning\u2026"] })), !scanning && isEmpty && ((0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center', padding: '28px 0' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: 28, marginBottom: 8 }, children: tab === 'violations' ? '✅' : '🔕' }), (0, jsx_runtime_1.jsxs)("div", { style: { color: '#64748b', fontSize: 12, fontWeight: 500 }, children: ["No ", tab, " found"] }), filter !== 'all' && ((0, jsx_runtime_1.jsx)("button", { style: { marginTop: 6, fontSize: 11, color: '#7c3aed', background: 'none', border: 'none', cursor: 'pointer' }, onClick: () => setFilter('all'), children: "Clear filter" }))] })), items === null || items === void 0 ? void 0 : items.map((item, i) => ((0, jsx_runtime_1.jsx)(ViolationCard, { item: item, pinned: pinnedEl === item.domElement && item.domElement != null, onPin: handlePin }, `${item.rule}-${i}`)))] }), (0, jsx_runtime_1.jsxs)("div", { style: s.footer, children: [(0, jsx_runtime_1.jsxs)("span", { children: [pinnedEl ? '📍 pinned · ' : '', "Scanned ", elapsed, results ? ` · ${results.duration}ms` : ''] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', gap: 6, alignItems: 'center' }, children: [pinnedEl && ((0, jsx_runtime_1.jsx)("button", { style: { ...rescanBtn, background: '#64748b' }, onClick: () => { clearAllHighlights(); setPinnedEl(null); }, children: "Unpin" })), (0, jsx_runtime_1.jsx)("button", { style: rescanBtn, onClick: scan, disabled: scanning, children: scanning ? 'Scanning…' : 'Rescan' })] })] })] })), (0, jsx_runtime_1.jsxs)("button", { style: s.toggle, onClick: () => setOpen(o => !o), title: "Toggle WCAG Inspector (Alt+Shift+W)", "aria-expanded": open, children: [(0, jsx_runtime_1.jsx)("span", { style: { fontSize: 14 }, children: "\u267F" }), scanning
312
+ ? (0, jsx_runtime_1.jsx)("span", { style: { opacity: 0.8, fontSize: 11 }, children: "scanning\u2026" })
313
+ : vCount > 0
314
+ ? (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { style: s.badge, children: vCount }), (0, jsx_runtime_1.jsx)("span", { style: { fontSize: 11 }, children: "issues" })] })
315
+ : (0, jsx_runtime_1.jsx)("span", { style: s.badge, children: "\u2713" })] })] }));
496
316
  };
497
317
  exports.WcagDevOverlay = WcagDevOverlay;
498
318
  exports.default = exports.WcagDevOverlay;
@@ -39,13 +39,16 @@ async function scanBrowserPage(options = {}) {
39
39
  // rule failed in browser context — skip silently
40
40
  }
41
41
  }
42
+ // Exclude any elements that live inside the WCAG overlay itself
43
+ const overlayRoot = document.querySelector('[data-wcag-overlay-root]');
44
+ const isInOverlay = (el) => el != null && overlayRoot != null && overlayRoot.contains(el);
42
45
  const annotate = (item) => {
43
46
  const el = findElement(item, document);
44
47
  return { ...item, domElement: el !== null && el !== void 0 ? el : undefined, elementPath: el ? getElementPath(el) : undefined };
45
48
  };
46
49
  return {
47
- violations: violations.map(annotate),
48
- warnings: warnings.map(annotate),
50
+ violations: violations.map(annotate).filter(v => { var _a; return !isInOverlay((_a = v.domElement) !== null && _a !== void 0 ? _a : null); }),
51
+ warnings: warnings.map(annotate).filter(w => { var _a; return !isInOverlay((_a = w.domElement) !== null && _a !== void 0 ? _a : null); }),
49
52
  passes,
50
53
  duration: Math.round(performance.now() - start),
51
54
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wcag-scanner",
3
- "version": "1.2.63",
3
+ "version": "1.2.65",
4
4
  "description": "Scan HTML for WCAG accessibility violations with AI-powered fix suggestions",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",