abledom 0.6.5 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -14,6 +14,11 @@ var ValidationRule = class {
14
14
  __publicField(this, "_window");
15
15
  __publicField(this, "_exceptions", []);
16
16
  __publicField(this, "_onIssue");
17
+ /**
18
+ * A short friendly group name for grouping issues in the UI.
19
+ * If undefined, the issue will not be grouped.
20
+ */
21
+ __publicField(this, "groupName");
17
22
  }
18
23
  static init(instance, window, onIssue) {
19
24
  instance._window = window;
@@ -58,7 +63,7 @@ var ValidationRule = class {
58
63
  };
59
64
 
60
65
  // inline-file:/Users/marata/tmp/abledom/src/ui/ui.css
61
- var ui_default = "#abledom-report {\n bottom: 20px;\n display: flex;\n flex-direction: column;\n left: 10px;\n max-height: 80%;\n max-width: 60%;\n padding: 4px 8px;\n position: fixed;\n z-index: 100500;\n}\n\n#abledom-report :focus-visible {\n outline: 3px solid red;\n mix-blend-mode: difference;\n}\n\n#abledom-report.abledom-align-left {\n left: 10px;\n right: auto;\n}\n\n#abledom-report.abledom-align-right {\n left: auto;\n right: 10px;\n}\n\n#abledom-report.abledom-align-bottom {\n bottom: 20px;\n top: auto;\n}\n\n#abledom-report.abledom-align-top {\n /* flex-direction: column-reverse; */\n bottom: auto;\n top: 10px;\n}\n\n.abledom-menu-container {\n backdrop-filter: blur(3px);\n border-radius: 8px;\n box-shadow: 0px 0px 4px rgba(127, 127, 127, 0.5);\n display: inline-block;\n margin: 2px auto 2px 0;\n}\n\n#abledom-report.abledom-align-right .abledom-menu-container {\n margin: 2px 0 2px auto;\n}\n\n.abledom-menu {\n background-color: rgba(140, 10, 121, 0.7);\n border-radius: 8px;\n color: white;\n display: inline flex;\n font-family: Arial, Helvetica, sans-serif;\n font-size: 16px;\n line-height: 26px;\n padding: 4px;\n}\n\n.abledom-menu .issues-count {\n margin: 0 8px;\n display: inline-block;\n}\n\n.abledom-menu .button {\n all: unset;\n color: #000;\n cursor: pointer;\n background: linear-gradient(\n 180deg,\n rgba(255, 255, 255, 1) 0%,\n rgba(200, 200, 200, 1) 100%\n );\n border-radius: 6px;\n border: 1px solid rgba(255, 255, 255, 0.4);\n box-sizing: border-box;\n line-height: 0px;\n margin-right: 4px;\n max-height: 26px;\n padding: 2px;\n text-decoration: none;\n}\n\n.abledom-menu .align-button {\n border-right-color: rgba(0, 0, 0, 0.4);\n border-radius: 0;\n margin: 0;\n}\n\n.abledom-menu .align-button:active,\n#abledom-report .pressed {\n background: linear-gradient(\n 180deg,\n rgba(130, 130, 130, 1) 0%,\n rgba(180, 180, 180, 1) 100%\n );\n}\n\n.abledom-menu .align-button-first {\n border-top-left-radius: 6px;\n border-bottom-left-radius: 6px;\n margin-left: 8px;\n}\n.abledom-menu .align-button-last {\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n border-right-color: rgba(255, 255, 255, 0.4);\n}\n\n.abledom-issues-container {\n overflow: auto;\n max-height: calc(100vh - 100px);\n}\n\n#abledom-report.abledom-align-right .abledom-issues-container {\n text-align: right;\n}\n\n.abledom-issue-container {\n backdrop-filter: blur(3px);\n border-radius: 8px;\n box-shadow: 0px 0px 4px rgba(127, 127, 127, 0.5);\n display: inline-flex;\n margin: 2px 0;\n}\n\n.abledom-issue {\n background-color: rgba(164, 2, 2, 0.7);\n border-radius: 8px;\n color: white;\n display: inline flex;\n font-family: Arial, Helvetica, sans-serif;\n font-size: 16px;\n line-height: 26px;\n padding: 4px;\n}\n.abledom-issue_warning {\n background-color: rgba(163, 82, 1, 0.7);\n}\n.abledom-issue_info {\n background-color: rgba(0, 0, 255, 0.7);\n}\n\n.abledom-issue .button {\n all: unset;\n color: #000;\n cursor: pointer;\n background: linear-gradient(\n 180deg,\n rgba(255, 255, 255, 1) 0%,\n rgba(200, 200, 200, 1) 100%\n );\n border-radius: 6px;\n border: 1px solid rgba(255, 255, 255, 0.4);\n box-sizing: border-box;\n line-height: 0px;\n margin-right: 4px;\n max-height: 26px;\n padding: 2px;\n text-decoration: none;\n}\n\n.abledom-issue .button:hover {\n opacity: 0.7;\n}\n\n.abledom-issue .button.close {\n background: none;\n border-color: transparent;\n color: #fff;\n margin: 0;\n}\n";
66
+ var ui_default = "#abledom-report {\n bottom: 20px;\n display: flex;\n flex-direction: column;\n left: 10px;\n max-height: 80%;\n max-width: 60%;\n padding: 4px 8px;\n position: fixed;\n z-index: 100500;\n}\n\n#abledom-report :focus-visible {\n mix-blend-mode: difference;\n outline: 3px solid red;\n}\n\n#abledom-report.abledom-align-left {\n left: 10px;\n right: auto;\n}\n\n#abledom-report.abledom-align-right {\n left: auto;\n right: 10px;\n}\n\n#abledom-report.abledom-align-bottom {\n bottom: 20px;\n top: auto;\n}\n\n#abledom-report.abledom-align-top {\n /* flex-direction: column-reverse; */\n bottom: auto;\n top: 10px;\n}\n\n.abledom-menu-container {\n margin: 2px auto 2px 0;\n padding: 8px 0;\n}\n\n#abledom-report.abledom-align-right .abledom-menu-container {\n margin: 2px 0 2px auto;\n}\n\n.abledom-menu-wrapper {\n backdrop-filter: blur(3px);\n border-radius: 20px;\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);\n}\n\n.abledom-menu {\n background-color: rgba(140, 10, 121, 0.7);\n border-radius: 20px;\n color: white;\n display: inline flex;\n font-family: Arial, Helvetica, sans-serif;\n font-size: 16px;\n line-height: 26px;\n padding: 6px;\n position: relative;\n}\n\n.abledom-menu .issues-count {\n cursor: pointer;\n display: inline-block;\n margin: 0 8px;\n}\n\n.abledom-menu-container .controls-wrapper {\n display: none;\n left: calc(100% - 28px);\n position: absolute;\n top: -9px;\n}\n\n.abledom-menu .controls-wrapper {\n padding: 8px;\n}\n\n.abledom-menu .controls {\n background: #fff;\n border-radius: 4px;\n border: 1px solid #ddd;\n box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);\n display: flex;\n margin-left: 30px;\n padding: 6px;\n}\n\n.abledom-menu-container:hover .controls-wrapper {\n display: block;\n}\n\n#abledom-report.abledom-align-right .controls-wrapper {\n left: auto;\n right: calc(100% - 28px);\n}\n\n#abledom-report.abledom-align-right .controls {\n left: auto;\n margin: 0 30px 0 0;\n right: calc(100%);\n}\n\n.abledom-menu .button {\n all: unset;\n background: linear-gradient(\n 180deg,\n rgba(255, 255, 255, 1) 0%,\n rgba(200, 200, 200, 1) 100%\n );\n border-radius: 6px;\n border: 1px solid rgba(255, 255, 255, 0.4);\n box-sizing: border-box;\n color: #000;\n cursor: pointer;\n line-height: 0px;\n margin-right: 4px;\n max-height: 26px;\n padding: 2px;\n text-decoration: none;\n}\n\n.abledom-menu .align-button {\n border-radius: 0;\n border-right-color: rgba(0, 0, 0, 0.4);\n margin: 0;\n}\n\n.abledom-menu .align-button:active,\n#abledom-report .pressed {\n background: linear-gradient(\n 180deg,\n rgba(130, 130, 130, 1) 0%,\n rgba(180, 180, 180, 1) 100%\n );\n}\n\n.abledom-menu .align-button-first {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n margin-left: 8px;\n}\n.abledom-menu .align-button-last {\n border-bottom-right-radius: 6px;\n border-right-color: rgba(255, 255, 255, 0.4);\n border-top-right-radius: 6px;\n}\n\n.abledom-issues-container {\n max-height: calc(100vh - 100px);\n overflow: auto;\n}\n\n#abledom-report.abledom-align-right .abledom-issues-container {\n text-align: right;\n}\n\n.abledom-issue-container {\n backdrop-filter: blur(3px);\n border-radius: 8px;\n box-shadow: 0px 0px 4px rgba(127, 127, 127, 0.5);\n display: inline-flex;\n margin-top: 5px;\n}\n\n.abledom-issue-group-issues {\n border-bottom-left-radius: 10px;\n border-left: 3px solid rgba(164, 2, 2, 0.7);\n margin-left: 15px;\n padding-left: 10px;\n}\n\n#abledom-report.abledom-align-right .abledom-issue-group-issues {\n border-bottom-right-radius: 10px;\n border-left: none;\n border-right: 3px solid rgba(164, 2, 2, 0.7);\n margin-left: 0;\n margin-right: 15px;\n padding-left: 0;\n padding-right: 10px;\n}\n\n.abledom-issue_warning + .abledom-issue-group-issues {\n border-left: 3px solid rgba(163, 82, 1, 0.7);\n}\n#abledom-report.abledom-align-right\n .abledom-issue_warning\n + .abledom-issue-group-issues {\n border-right: 3px solid rgba(163, 82, 1, 0.7);\n}\n\n.abledom-issue_info + .abledom-issue-group-issues {\n border-left: 3px solid rgba(0, 0, 255, 0.7);\n}\n#abledom-report.abledom-align-right\n .abledom-issue_info\n + .abledom-issue-group-issues {\n border-right: 3px solid rgba(0, 0, 255, 0.7);\n}\n\n.abledom-issue-group-title {\n background-color: rgba(164, 2, 2, 0.7);\n color: white;\n}\n\n.abledom-issue-group-count {\n font-size: 14px;\n margin: 0 4px;\n opacity: 0.8;\n}\n\n.abledom-issue {\n border-radius: 8px;\n color: #fff;\n display: inline flex;\n font-family: Arial, Helvetica, sans-serif;\n font-size: 16px;\n line-height: 26px;\n padding: 4px;\n text-align: left;\n}\n.abledom-issue_warning {\n background-color: rgba(163, 82, 1, 0.7);\n}\n.abledom-issue_info {\n background-color: rgba(0, 0, 255, 0.7);\n}\n\n.abledom-issue-group {\n margin: 5px 0 0 0;\n}\n\n.abledom-issue-group-issues .abledom-issue {\n background-color: rgba(198, 198, 198, 0.7);\n border: 1px solid #ccc;\n color: #000;\n}\n\n.abledom-issue-group-issues .abledom-issue .button.close,\n.abledom-issue-group-issues .abledom-issue .button.help {\n color: #000;\n}\n\n.abledom-issue .button {\n all: unset;\n background: linear-gradient(\n 180deg,\n rgba(255, 255, 255, 1) 0%,\n rgba(200, 200, 200, 1) 100%\n );\n border-radius: 6px;\n border: 1px solid rgba(255, 255, 255, 0.4);\n box-sizing: border-box;\n color: #000;\n cursor: pointer;\n line-height: 0px;\n margin-right: 4px;\n max-height: 26px;\n padding: 2px;\n text-decoration: none;\n}\n\n.abledom-issue .button:hover {\n opacity: 0.7;\n}\n\n.abledom-issue .button.close {\n background: none;\n border-color: transparent;\n color: #fff;\n margin: 0;\n}\n\n.abledom-issue .button.help {\n background: none;\n border-color: transparent;\n color: #fff;\n margin: 0 0 0 2px;\n}\n\n.abledom-issue-group-count {\n background-color: #444;\n border-radius: 10px;\n border: 1px solid black;\n box-sizing: border-box;\n color: #fff;\n display: inline-block;\n height: 20px;\n min-width: 20px;\n padding: 0 5px;\n text-align: center;\n}\n\n.abledom-issue .button.toggle {\n display: flex;\n line-height: 20px;\n}\n\n.abledom-issue .button.toggle svg:nth-child(1) {\n display: none;\n}\n\n.abledom-issue .button.toggle.collapsed svg:nth-child(1) {\n display: inline;\n}\n.abledom-issue .button.toggle.collapsed svg:nth-child(2) {\n display: none;\n}\n";
62
67
 
63
68
  // inline-file:/Users/marata/tmp/abledom/src/ui/highlighter.css
64
69
  var highlighter_default = ".abledom-highlight {\n background-color: yellow;\n box-sizing: border-box;\n display: none;\n opacity: 0.6;\n position: fixed;\n z-index: 100499;\n}\n\n.abledom-highlight-border1 {\n border-top: 2px solid red;\n border-bottom: 2px solid red;\n box-sizing: border-box;\n position: absolute;\n top: -2px;\n width: calc(100% + 20px);\n height: calc(100% + 4px);\n margin: 0 -10px;\n}\n\n.abledom-highlight-border2 {\n border-left: 2px solid red;\n border-right: 2px solid red;\n box-sizing: border-box;\n position: absolute;\n width: calc(100% + 4px);\n left: -2px;\n height: calc(100% + 20px);\n margin: -10px 0;\n}\n";
@@ -71,27 +76,29 @@ var DOMBuilder = class {
71
76
  this._doc = parent.ownerDocument;
72
77
  this._stack = [parent];
73
78
  }
74
- openTag(tagName, attributes, callback, namespace) {
79
+ openTag(tagName, attributes, callback, namespace, skip) {
75
80
  var _a, _b;
76
81
  const parent = this._stack[0];
77
- const element = namespace ? (_a = this._doc) == null ? void 0 : _a.createElementNS(namespace, tagName) : (_b = this._doc) == null ? void 0 : _b.createElement(tagName);
78
- if (parent && element) {
79
- element.__abledomui = true;
80
- if (attributes) {
81
- for (const [key, value] of Object.entries(attributes)) {
82
- if (key === "class") {
83
- element.className = value;
84
- } else if (key === "style") {
85
- element.style.cssText = value;
86
- } else {
87
- element.setAttribute(key, value);
82
+ const element = skip ? null : namespace ? (_a = this._doc) == null ? void 0 : _a.createElementNS(namespace, tagName) : (_b = this._doc) == null ? void 0 : _b.createElement(tagName);
83
+ if (parent !== void 0) {
84
+ if (parent && element) {
85
+ element.__abledomui = true;
86
+ if (attributes) {
87
+ for (const [key, value] of Object.entries(attributes)) {
88
+ if (key === "class") {
89
+ element.className = value;
90
+ } else if (key === "style") {
91
+ element.style.cssText = value;
92
+ } else {
93
+ element.setAttribute(key, value);
94
+ }
88
95
  }
89
96
  }
97
+ if (callback) {
98
+ callback(element);
99
+ }
100
+ parent.appendChild(element);
90
101
  }
91
- if (callback) {
92
- callback(element);
93
- }
94
- parent.appendChild(element);
95
102
  this._stack.unshift(element);
96
103
  }
97
104
  return this;
@@ -113,7 +120,8 @@ var DOMBuilder = class {
113
120
  return this;
114
121
  }
115
122
  element(callback) {
116
- callback(this._stack[0]);
123
+ const el = this._stack[0];
124
+ el && callback(el);
117
125
  return this;
118
126
  }
119
127
  };
@@ -286,8 +294,31 @@ var alignbottomleft_default = (function buildSVG12(parent) {
286
294
  return parent.firstElementChild;
287
295
  });
288
296
 
297
+ // inline-file:/Users/marata/tmp/abledom/src/ui/chevrondown.svg
298
+ var chevrondown_default = (function buildSVG13(parent) {
299
+ const builder = new DOMBuilder(parent);
300
+ builder.openTag("svg", { "width": "20", "height": "20", "viewBox": "0 0 24 24", "fill": "none", "stroke": "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "xmlns": "http://www.w3.org/2000/svg" }, void 0, "http://www.w3.org/2000/svg");
301
+ builder.openTag("polyline", { "points": "6 9 12 15 18 9" }, void 0, "http://www.w3.org/2000/svg");
302
+ builder.closeTag();
303
+ builder.closeTag();
304
+ return parent.firstElementChild;
305
+ });
306
+
307
+ // inline-file:/Users/marata/tmp/abledom/src/ui/chevronright.svg
308
+ var chevronright_default = (function buildSVG14(parent) {
309
+ const builder = new DOMBuilder(parent);
310
+ builder.openTag("svg", { "width": "20", "height": "20", "viewBox": "0 0 24 24", "fill": "none", "stroke": "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "xmlns": "http://www.w3.org/2000/svg" }, void 0, "http://www.w3.org/2000/svg");
311
+ builder.openTag("polyline", { "points": "9 6 15 12 9 18" }, void 0, "http://www.w3.org/2000/svg");
312
+ builder.closeTag();
313
+ builder.closeTag();
314
+ return parent.firstElementChild;
315
+ });
316
+
289
317
  // src/ui/ui.ts
290
318
  var pressedClass = "pressed";
319
+ function getIssueTypeClass(type) {
320
+ return type === 2 /* Warning */ ? " abledom-issue_warning" : type === 3 /* Info */ ? " abledom-issue_info" : "";
321
+ }
291
322
  var IssueUI = class {
292
323
  constructor(win, core, rule, issuesUI) {
293
324
  __publicField(this, "_core");
@@ -295,6 +326,7 @@ var IssueUI = class {
295
326
  __publicField(this, "_wrapper");
296
327
  __publicField(this, "_rule");
297
328
  __publicField(this, "_onToggle");
329
+ __publicField(this, "_appended", false);
298
330
  __publicField(this, "isHidden", false);
299
331
  this._core = core;
300
332
  this._rule = rule;
@@ -303,35 +335,62 @@ var IssueUI = class {
303
335
  this._wrapper = win.document.createElement(
304
336
  "div"
305
337
  );
338
+ this._wrapper.__ableDOMIssueUI = this;
339
+ this._wrapper.className = "abledom-issue-container-wrapper";
306
340
  }
307
341
  issuesUI.addIssue(this);
308
342
  }
309
343
  static setOnToggle(instance, onToggle) {
310
344
  instance._onToggle = onToggle;
311
345
  }
312
- static getElement(instance) {
313
- return instance._wrapper;
346
+ static setAppended(instance) {
347
+ instance._appended = true;
314
348
  }
315
349
  update(issue) {
316
- const rule = this._rule;
317
350
  const wrapper = this._wrapper;
318
- const element = issue.element;
319
351
  if (!wrapper) {
320
352
  return;
321
353
  }
354
+ this._appendToIssueContainer(issue);
322
355
  wrapper.__abledomui = true;
323
356
  wrapper.textContent = "";
357
+ this._renderIssueContent(wrapper, issue);
358
+ }
359
+ _appendToIssueContainer(issue) {
360
+ var _a, _b, _c;
361
+ if (!this._appended) {
362
+ return;
363
+ }
364
+ const wrapper = this._wrapper;
365
+ const rule = this._rule;
366
+ if (!wrapper) {
367
+ return;
368
+ }
369
+ const issueContainer = (_a = this._issuesUI) == null ? void 0 : _a.getIssueContainer(
370
+ rule.type,
371
+ rule.groupName,
372
+ issue.help
373
+ );
374
+ if (!issueContainer || wrapper.parentElement === issueContainer) {
375
+ return;
376
+ }
377
+ issueContainer.appendChild(wrapper);
378
+ if (!this.isHidden) {
379
+ if ((_b = issueContainer.parentElement) == null ? void 0 : _b.classList.contains("abledom-issue-group")) {
380
+ issueContainer.parentElement.style.display = "block";
381
+ }
382
+ } else {
383
+ this.toggle(false, true);
384
+ }
385
+ (_c = this._issuesUI) == null ? void 0 : _c.syncGroupIssueCounts();
386
+ }
387
+ _renderIssueContent(wrapper, issue) {
388
+ const rule = this._rule;
389
+ const element = issue.element;
324
390
  new DOMBuilder(wrapper).openTag("div", { class: "abledom-issue-container" }, (container) => {
325
- container.onmouseenter = () => {
326
- var _a;
327
- element && ((_a = this._issuesUI) == null ? void 0 : _a.highlight(element));
328
- };
329
- container.onmouseleave = () => {
330
- var _a;
331
- (_a = this._issuesUI) == null ? void 0 : _a.highlight(null);
332
- };
391
+ this._bindIssueContainerHover(container, element);
333
392
  }).openTag("div", {
334
- class: `abledom-issue${rule.type === 2 /* Warning */ ? " abledom-issue_warning" : rule.type === 3 /* Info */ ? " abledom-issue_info" : ""}`
393
+ class: `abledom-issue${getIssueTypeClass(rule.type)}`
335
394
  }).openTag(
336
395
  "button",
337
396
  {
@@ -339,21 +398,7 @@ var IssueUI = class {
339
398
  title: "Log to Console"
340
399
  },
341
400
  (logButton) => {
342
- logButton.onclick = () => {
343
- const { id, message, element: element2, rel, help, ...extra } = issue;
344
- this._core.log(
345
- "AbleDOM: ",
346
- "\nid:",
347
- id,
348
- "\nmessage:",
349
- message,
350
- "\nelement:",
351
- element2,
352
- ...rel ? ["\nrelative:", rel] : [],
353
- ...help ? ["\nhelp:", help] : [],
354
- ...Object.keys(extra).length > 0 ? ["\nextra:", extra] : []
355
- );
356
- };
401
+ this._bindLogButton(logButton, issue);
357
402
  }
358
403
  ).element(log_default).closeTag().openTag(
359
404
  "button",
@@ -363,16 +408,10 @@ var IssueUI = class {
363
408
  title: "Scroll element into view"
364
409
  },
365
410
  (revealButton) => {
366
- const element2 = issue.element;
367
- if (element2) {
368
- revealButton.onclick = () => {
369
- var _a;
370
- (_a = this._issuesUI) == null ? void 0 : _a.highlight(element2, true);
371
- };
372
- } else {
373
- revealButton.style.display = "none";
374
- }
375
- }
411
+ this._bindRevealButton(revealButton, issue);
412
+ },
413
+ void 0,
414
+ !issue.element
376
415
  ).element(reveal_default).closeTag().openTag(
377
416
  "button",
378
417
  {
@@ -380,33 +419,21 @@ var IssueUI = class {
380
419
  title: "Report bug"
381
420
  },
382
421
  (bugReportButton) => {
383
- var _a, _b;
384
- const bugReport = (_a = this._issuesUI) == null ? void 0 : _a.bugReport;
385
- if (bugReport == null ? void 0 : bugReport.isVisible(issue)) {
386
- const title = (_b = bugReport.getTitle) == null ? void 0 : _b.call(bugReport, issue);
387
- if (title) {
388
- bugReportButton.title = title;
389
- }
390
- bugReportButton.onclick = () => {
391
- bugReport.onClick(issue);
392
- };
393
- } else {
394
- bugReportButton.style.display = "none";
395
- }
422
+ this._bindBugReportButton(bugReportButton, issue);
396
423
  }
397
424
  ).element(bug_default).closeTag().text(issue.message).openTag(
398
425
  "a",
399
426
  {
400
- class: "button close",
427
+ class: "button help",
401
428
  href: issue.help || "/",
402
429
  title: "Open help",
403
430
  target: "_blank"
404
431
  },
405
432
  (help) => {
406
- if (!issue.help) {
407
- help.style.display = "none";
408
- }
409
- }
433
+ this._bindHelpLink(help, issue.help);
434
+ },
435
+ void 0,
436
+ !!rule.groupName
410
437
  ).element(help_default).closeTag().openTag(
411
438
  "button",
412
439
  {
@@ -414,27 +441,116 @@ var IssueUI = class {
414
441
  title: "Hide"
415
442
  },
416
443
  (closeButton) => {
417
- closeButton.onclick = () => {
418
- var _a;
419
- this.toggle(false);
420
- (_a = this._issuesUI) == null ? void 0 : _a.highlight(null);
421
- };
444
+ this._bindCloseButton(closeButton);
422
445
  }
423
446
  ).element(close_default).closeTag().closeTag().closeTag();
424
447
  }
448
+ _bindIssueContainerHover(container, element) {
449
+ container.onmouseenter = () => {
450
+ var _a;
451
+ element && ((_a = this._issuesUI) == null ? void 0 : _a.highlight(element));
452
+ };
453
+ container.onmouseleave = () => {
454
+ var _a;
455
+ (_a = this._issuesUI) == null ? void 0 : _a.highlight(null);
456
+ };
457
+ }
458
+ _bindLogButton(button, issue) {
459
+ button.onclick = () => {
460
+ const { id, message, element, rel, help, ...extra } = issue;
461
+ this._core.log(
462
+ "AbleDOM: ",
463
+ "\nid:",
464
+ id,
465
+ "\nmessage:",
466
+ message,
467
+ "\nelement:",
468
+ element,
469
+ ...rel ? ["\nrelative:", rel] : [],
470
+ ...help ? ["\nhelp:", help] : [],
471
+ ...Object.keys(extra).length > 0 ? ["\nextra:", extra] : []
472
+ );
473
+ };
474
+ }
475
+ _bindRevealButton(button, issue) {
476
+ const element = issue.element;
477
+ if (element) {
478
+ button.onclick = () => {
479
+ var _a;
480
+ (_a = this._issuesUI) == null ? void 0 : _a.highlight(element, true);
481
+ };
482
+ }
483
+ }
484
+ _bindBugReportButton(button, issue) {
485
+ var _a, _b;
486
+ const bugReport = (_a = this._issuesUI) == null ? void 0 : _a.bugReport;
487
+ if (bugReport == null ? void 0 : bugReport.isVisible(issue)) {
488
+ const title = (_b = bugReport.getTitle) == null ? void 0 : _b.call(bugReport, issue);
489
+ if (title) {
490
+ button.title = title;
491
+ }
492
+ button.onclick = () => {
493
+ bugReport.onClick(issue);
494
+ };
495
+ } else {
496
+ button.style.display = "none";
497
+ }
498
+ }
499
+ _bindHelpLink(help, issueHelp) {
500
+ if (!issueHelp) {
501
+ help.style.display = "none";
502
+ }
503
+ }
504
+ _bindCloseButton(button) {
505
+ button.onclick = () => {
506
+ var _a;
507
+ this.toggle(false);
508
+ (_a = this._issuesUI) == null ? void 0 : _a.highlight(null);
509
+ };
510
+ }
425
511
  toggle(show, initial = false) {
426
512
  var _a;
427
513
  if (!this._wrapper) {
428
514
  return;
429
515
  }
430
- this.isHidden = !show;
516
+ if (show === void 0) {
517
+ this.isHidden = !this.isHidden;
518
+ show = !this.isHidden;
519
+ } else {
520
+ this.isHidden = !show;
521
+ }
431
522
  if (!initial) {
432
- (_a = this._onToggle) == null ? void 0 : _a.call(this, this, show);
433
- if (!this._rule.anchored && !show) {
523
+ (_a = this._onToggle) == null ? void 0 : _a.call(this, this, !this.isHidden);
524
+ if (!this._rule.anchored && this.isHidden) {
434
525
  this.dispose();
435
526
  }
436
527
  }
437
528
  this._wrapper.style.display = show ? "block" : "none";
529
+ this._syncGroupVisibility(!!show);
530
+ }
531
+ _syncGroupVisibility(show) {
532
+ const wrapper = this._wrapper;
533
+ if (!wrapper) {
534
+ return;
535
+ }
536
+ const potentiallyGroupIssuesElement = wrapper.parentElement;
537
+ const potentiallyGroupElement = potentiallyGroupIssuesElement == null ? void 0 : potentiallyGroupIssuesElement.parentElement;
538
+ if (!potentiallyGroupIssuesElement || !(potentiallyGroupElement == null ? void 0 : potentiallyGroupElement.classList.contains("abledom-issue-group"))) {
539
+ return;
540
+ }
541
+ if (show) {
542
+ potentiallyGroupElement.style.display = "block";
543
+ return;
544
+ }
545
+ if (potentiallyGroupElement.style.display !== "none" && Array.prototype.every.call(
546
+ potentiallyGroupIssuesElement.children,
547
+ (el) => {
548
+ var _a;
549
+ return el.__ableDOMIssueUI ? (_a = el.__ableDOMIssueUI) == null ? void 0 : _a.isHidden : true;
550
+ }
551
+ )) {
552
+ potentiallyGroupElement.style.display = "none";
553
+ }
438
554
  }
439
555
  dispose() {
440
556
  var _a, _b;
@@ -458,6 +574,8 @@ var IssuesUI = class {
458
574
  __publicField(this, "_alignBottomRightButton");
459
575
  __publicField(this, "_isMuted", false);
460
576
  __publicField(this, "_issues", /* @__PURE__ */ new Set());
577
+ __publicField(this, "_issueGroupContainers", {});
578
+ __publicField(this, "_issueGroupCountElements", {});
461
579
  __publicField(this, "_getHighlighter");
462
580
  __publicField(this, "bugReport");
463
581
  __publicField(this, "headless");
@@ -469,31 +587,54 @@ var IssuesUI = class {
469
587
  return;
470
588
  }
471
589
  const doc = win.document;
472
- const container = this._container = doc.createElement("div");
590
+ const container = this._container = this._createRootContainer(doc);
591
+ this._issuesContainer = this._createIssuesContainer(doc, container);
592
+ const menuElement = this._menuElement = this._createMenuContainer(
593
+ doc,
594
+ container
595
+ );
596
+ this._buildMenu(menuElement);
597
+ doc.body.appendChild(container);
598
+ }
599
+ _createRootContainer(doc) {
600
+ const container = doc.createElement("div");
473
601
  container.__abledomui = true;
474
602
  container.id = "abledom-report";
475
603
  const style = doc.createElement("style");
476
604
  style.type = "text/css";
477
605
  style.appendChild(doc.createTextNode(ui_default));
478
606
  container.appendChild(style);
479
- const issuesContainer = this._issuesContainer = doc.createElement("div");
607
+ return container;
608
+ }
609
+ _createIssuesContainer(doc, container) {
610
+ const issuesContainer = doc.createElement(
611
+ "div"
612
+ );
480
613
  issuesContainer.__abledomui = true;
481
614
  issuesContainer.className = "abledom-issues-container";
482
615
  container.appendChild(issuesContainer);
483
- const menuElement = this._menuElement = doc.createElement("div");
616
+ return issuesContainer;
617
+ }
618
+ _createMenuContainer(doc, container) {
619
+ const menuElement = doc.createElement(
620
+ "div"
621
+ );
484
622
  menuElement.__abledomui = true;
485
623
  menuElement.className = "abledom-menu-container";
486
624
  container.appendChild(menuElement);
487
- new DOMBuilder(menuElement).openTag("div", { class: "abledom-menu" }).openTag(
625
+ return menuElement;
626
+ }
627
+ _buildMenu(menuElement) {
628
+ new DOMBuilder(menuElement).openTag("div", { class: "abledom-menu-wrapper" }).openTag("div", { class: "abledom-menu" }).openTag(
488
629
  "span",
489
630
  {
490
631
  class: "issues-count",
491
632
  title: "Number of issues"
492
633
  },
493
634
  (issueCountElement) => {
494
- this._issueCountElement = issueCountElement;
635
+ this._bindIssueCountElement(issueCountElement);
495
636
  }
496
- ).closeTag().openTag(
637
+ ).closeTag().openTag("div", { class: "controls-wrapper" }).openTag("div", { class: "controls" }).openTag(
497
638
  "button",
498
639
  {
499
640
  class: "button",
@@ -501,9 +642,7 @@ var IssuesUI = class {
501
642
  },
502
643
  (showAllButton) => {
503
644
  this._showAllButton = showAllButton;
504
- showAllButton.onclick = () => {
505
- this.showAll();
506
- };
645
+ this._bindToggleAllButton(showAllButton, true);
507
646
  }
508
647
  ).element(showall_default).closeTag().openTag(
509
648
  "button",
@@ -513,9 +652,7 @@ var IssuesUI = class {
513
652
  },
514
653
  (hideAllButton) => {
515
654
  this._hideAllButton = hideAllButton;
516
- hideAllButton.onclick = () => {
517
- this.hideAll();
518
- };
655
+ this._bindToggleAllButton(hideAllButton, false);
519
656
  }
520
657
  ).element(hideall_default).closeTag().openTag(
521
658
  "button",
@@ -524,14 +661,7 @@ var IssuesUI = class {
524
661
  title: "Mute newly appearing issues"
525
662
  },
526
663
  (muteButton) => {
527
- muteButton.onclick = () => {
528
- const isMuted = this._isMuted = muteButton.classList.toggle(pressedClass);
529
- if (isMuted) {
530
- muteButton.setAttribute("title", "Unmute newly appearing issues");
531
- } else {
532
- muteButton.setAttribute("title", "Mute newly appearing issues");
533
- }
534
- };
664
+ this._bindMuteButton(muteButton);
535
665
  }
536
666
  ).element(muteall_default).closeTag().openTag(
537
667
  "button",
@@ -541,9 +671,10 @@ var IssuesUI = class {
541
671
  },
542
672
  (alignBottomLeftButton) => {
543
673
  this._alignBottomLeftButton = alignBottomLeftButton;
544
- alignBottomLeftButton.onclick = () => {
545
- this.setUIAlignment("bottom-left" /* BottomLeft */);
546
- };
674
+ this._bindAlignmentButton(
675
+ alignBottomLeftButton,
676
+ "bottom-left" /* BottomLeft */
677
+ );
547
678
  }
548
679
  ).element(alignbottomleft_default).closeTag().openTag(
549
680
  "button",
@@ -553,9 +684,7 @@ var IssuesUI = class {
553
684
  },
554
685
  (alignTopLeftButton) => {
555
686
  this._alignTopLeftButton = alignTopLeftButton;
556
- alignTopLeftButton.onclick = () => {
557
- this.setUIAlignment("top-left" /* TopLeft */);
558
- };
687
+ this._bindAlignmentButton(alignTopLeftButton, "top-left" /* TopLeft */);
559
688
  }
560
689
  ).element(aligntopleft_default).closeTag().openTag(
561
690
  "button",
@@ -565,9 +694,7 @@ var IssuesUI = class {
565
694
  },
566
695
  (alignTopRightButton) => {
567
696
  this._alignTopRightButton = alignTopRightButton;
568
- alignTopRightButton.onclick = () => {
569
- this.setUIAlignment("top-right" /* TopRight */);
570
- };
697
+ this._bindAlignmentButton(alignTopRightButton, "top-right" /* TopRight */);
571
698
  }
572
699
  ).element(aligntopright_default).closeTag().openTag(
573
700
  "button",
@@ -577,55 +704,89 @@ var IssuesUI = class {
577
704
  },
578
705
  (alignBottomRightButton) => {
579
706
  this._alignBottomRightButton = alignBottomRightButton;
580
- alignBottomRightButton.onclick = () => {
581
- this.setUIAlignment("bottom-right" /* BottomRight */);
582
- };
707
+ this._bindAlignmentButton(
708
+ alignBottomRightButton,
709
+ "bottom-right" /* BottomRight */
710
+ );
583
711
  }
584
- ).element(alignbottomright_default).closeTag().closeTag();
585
- doc.body.appendChild(container);
712
+ ).element(alignbottomright_default).closeTag().closeTag().closeTag().closeTag().closeTag();
713
+ }
714
+ _bindToggleAllButton(button, show) {
715
+ button.onclick = () => {
716
+ this.toggleAll(show);
717
+ };
718
+ }
719
+ _bindIssueCountElement(element) {
720
+ this._issueCountElement = element;
721
+ element.onclick = () => {
722
+ this.toggleAll();
723
+ };
724
+ }
725
+ _bindMuteButton(button) {
726
+ button.onclick = () => {
727
+ const isMuted = this._isMuted = button.classList.toggle(pressedClass);
728
+ button.setAttribute(
729
+ "title",
730
+ isMuted ? "Unmute newly appearing issues" : "Mute newly appearing issues"
731
+ );
732
+ };
733
+ }
734
+ _bindAlignmentButton(button, alignment) {
735
+ button.onclick = () => {
736
+ this.setUIAlignment(alignment);
737
+ };
586
738
  }
587
739
  setUIAlignment(alignment) {
588
- var _a, _b, _c, _d, _e, _f, _g, _h;
589
740
  if (!this._container || !this._issuesContainer || !this._menuElement) {
590
741
  return;
591
742
  }
592
- (_a = this._alignBottomLeftButton) == null ? void 0 : _a.classList.remove(pressedClass);
593
- (_b = this._alignBottomRightButton) == null ? void 0 : _b.classList.remove(pressedClass);
594
- (_c = this._alignTopLeftButton) == null ? void 0 : _c.classList.remove(pressedClass);
595
- (_d = this._alignTopRightButton) == null ? void 0 : _d.classList.remove(pressedClass);
743
+ this._clearAlignmentButtons();
596
744
  this._container.classList.remove(
597
745
  "abledom-align-left",
598
746
  "abledom-align-right",
599
747
  "abledom-align-top",
600
748
  "abledom-align-bottom"
601
749
  );
750
+ const { containerClasses, issuesFirst, activeButton } = this._getAlignmentLayout(alignment);
751
+ activeButton == null ? void 0 : activeButton.classList.add(pressedClass);
752
+ this._container.classList.add(...containerClasses);
753
+ this._container.insertBefore(
754
+ this._issuesContainer,
755
+ issuesFirst ? this._menuElement : null
756
+ );
757
+ }
758
+ _clearAlignmentButtons() {
759
+ var _a, _b, _c, _d;
760
+ (_a = this._alignBottomLeftButton) == null ? void 0 : _a.classList.remove(pressedClass);
761
+ (_b = this._alignBottomRightButton) == null ? void 0 : _b.classList.remove(pressedClass);
762
+ (_c = this._alignTopLeftButton) == null ? void 0 : _c.classList.remove(pressedClass);
763
+ (_d = this._alignTopRightButton) == null ? void 0 : _d.classList.remove(pressedClass);
764
+ }
765
+ _getAlignmentLayout(alignment) {
602
766
  let containerClasses = [];
603
767
  let issuesFirst = false;
768
+ let activeButton;
604
769
  switch (alignment) {
605
770
  case "bottom-left" /* BottomLeft */:
606
771
  containerClasses = ["abledom-align-left", "abledom-align-bottom"];
607
772
  issuesFirst = true;
608
- (_e = this._alignBottomLeftButton) == null ? void 0 : _e.classList.add(pressedClass);
773
+ activeButton = this._alignBottomLeftButton;
609
774
  break;
610
775
  case "bottom-right" /* BottomRight */:
611
776
  containerClasses = ["abledom-align-right", "abledom-align-bottom"];
612
777
  issuesFirst = true;
613
- (_f = this._alignBottomRightButton) == null ? void 0 : _f.classList.add(pressedClass);
778
+ activeButton = this._alignBottomRightButton;
614
779
  break;
615
780
  case "top-left" /* TopLeft */:
616
781
  containerClasses = ["abledom-align-left", "abledom-align-top"];
617
- (_g = this._alignTopLeftButton) == null ? void 0 : _g.classList.add(pressedClass);
782
+ activeButton = this._alignTopLeftButton;
618
783
  break;
619
784
  case "top-right" /* TopRight */:
620
785
  containerClasses = ["abledom-align-right", "abledom-align-top"];
621
- (_h = this._alignTopRightButton) == null ? void 0 : _h.classList.add(pressedClass);
786
+ activeButton = this._alignTopRightButton;
622
787
  break;
623
788
  }
624
- this._container.classList.add(...containerClasses);
625
- this._container.insertBefore(
626
- this._issuesContainer,
627
- issuesFirst ? this._menuElement : null
628
- );
789
+ return { containerClasses, issuesFirst, activeButton };
629
790
  }
630
791
  _setIssuesCount(count) {
631
792
  if (!this._menuElement) {
@@ -633,11 +794,19 @@ var IssuesUI = class {
633
794
  }
634
795
  const countElement = this._issueCountElement;
635
796
  if (countElement && count > 0) {
636
- countElement.textContent = "";
637
- new DOMBuilder(countElement).openTag("strong").text(`${count}`).closeTag().text(` issue${count > 1 ? "s" : ""}`);
638
- this._menuElement.style.display = "block";
797
+ this._renderIssueCountText(countElement, count);
798
+ this._setMenuVisibility(true);
639
799
  } else {
640
- this._menuElement.style.display = "none";
800
+ this._setMenuVisibility(false);
801
+ }
802
+ }
803
+ _renderIssueCountText(countElement, count) {
804
+ countElement.textContent = "";
805
+ new DOMBuilder(countElement).openTag("strong").text(`${count}`).closeTag().text(` issue${count > 1 ? "s" : ""}`);
806
+ }
807
+ _setMenuVisibility(visible) {
808
+ if (this._menuElement) {
809
+ this._menuElement.style.display = visible ? "block" : "none";
641
810
  }
642
811
  }
643
812
  _setShowHideButtonsVisibility() {
@@ -646,9 +815,14 @@ var IssuesUI = class {
646
815
  if (!showAllButton || !hideAllButton) {
647
816
  return;
648
817
  }
818
+ const { allHidden, allVisible } = this._getIssueVisibilityState();
819
+ hideAllButton.style.display = allHidden ? "none" : "";
820
+ showAllButton.style.display = allVisible ? "none" : "";
821
+ }
822
+ _getIssueVisibilityState() {
649
823
  let allHidden = true;
650
824
  let allVisible = true;
651
- for (let issue of this._issues) {
825
+ for (const issue of this._issues) {
652
826
  if (issue.isHidden) {
653
827
  allVisible = false;
654
828
  } else {
@@ -658,8 +832,11 @@ var IssuesUI = class {
658
832
  break;
659
833
  }
660
834
  }
661
- hideAllButton.style.display = allHidden ? "none" : "block";
662
- showAllButton.style.display = allVisible ? "none" : "block";
835
+ return { allHidden, allVisible };
836
+ }
837
+ _syncMenuState() {
838
+ this._setIssuesCount(this._issues.size);
839
+ this._setShowHideButtonsVisibility();
663
840
  }
664
841
  addIssue(issue) {
665
842
  if (this._issues.has(issue)) {
@@ -675,32 +852,148 @@ var IssuesUI = class {
675
852
  if (this._isMuted) {
676
853
  issue.toggle(false, true);
677
854
  }
678
- const issueUIWraper = IssueUI.getElement(issue);
679
- issueUIWraper && this._issuesContainer.appendChild(issueUIWraper);
855
+ IssueUI.setAppended(issue);
680
856
  IssueUI.setOnToggle(issue, () => {
681
857
  this._setShowHideButtonsVisibility();
682
858
  });
683
- this._setIssuesCount(this._issues.size);
684
- this._setShowHideButtonsVisibility();
859
+ this._syncMenuState();
860
+ }
861
+ getIssueContainer(type, groupName, helpLink) {
862
+ if (!this._issuesContainer) {
863
+ throw new Error("IssuesUI is not initialized");
864
+ }
865
+ if (!groupName) {
866
+ return this._issuesContainer;
867
+ }
868
+ let groupContainer = this._issueGroupContainers[groupName];
869
+ if (!groupContainer) {
870
+ groupContainer = this._createIssueGroup(groupName, type, helpLink);
871
+ }
872
+ return groupContainer;
873
+ }
874
+ syncGroupIssueCounts() {
875
+ this._updateGroupIssueCounts();
876
+ }
877
+ _createIssueGroup(groupName, type, helpLink) {
878
+ if (!this._issuesContainer) {
879
+ throw new Error("IssuesUI is not initialized");
880
+ }
881
+ let groupContainer;
882
+ new DOMBuilder(this._issuesContainer).openTag("div", { class: "abledom-issue-group" }).openTag("div", {
883
+ class: `abledom-issue-group-title abledom-issue${getIssueTypeClass(type)}`
884
+ }).openTag(
885
+ "button",
886
+ {
887
+ class: "button toggle collapsed",
888
+ title: "Toggle group"
889
+ },
890
+ (toggleButton) => {
891
+ this._bindGroupToggleButton(toggleButton, () => groupContainer);
892
+ }
893
+ ).element(chevronright_default).element(chevrondown_default).openTag("span", { class: "abledom-issue-group-count" }, (countEl) => {
894
+ this._issueGroupCountElements[groupName] = countEl;
895
+ }).closeTag().closeTag().text(groupName).openTag(
896
+ "a",
897
+ {
898
+ class: "button help",
899
+ href: helpLink || "/",
900
+ title: "Open help",
901
+ target: "_blank"
902
+ },
903
+ (help) => {
904
+ this._hideHelpLinkIfMissing(help, helpLink);
905
+ }
906
+ ).element(help_default).closeTag().openTag(
907
+ "button",
908
+ {
909
+ class: "button close",
910
+ title: "Hide"
911
+ },
912
+ (closeButton) => {
913
+ this._bindGroupCloseButton(closeButton, () => groupContainer);
914
+ }
915
+ ).element(close_default).closeTag().closeTag().openTag("div", { class: "abledom-issue-group-issues" }, (element) => {
916
+ this._issueGroupContainers[groupName] = groupContainer = element;
917
+ groupContainer.style.display = "none";
918
+ }).closeTag().closeTag();
919
+ if (!groupContainer) {
920
+ throw new Error("Issue group container was not created");
921
+ }
922
+ return groupContainer;
923
+ }
924
+ _bindGroupToggleButton(button, getGroupContainer) {
925
+ let isCollapsed = true;
926
+ button.onclick = () => {
927
+ isCollapsed = !isCollapsed;
928
+ button.classList.toggle("collapsed", isCollapsed);
929
+ const groupContainer = getGroupContainer();
930
+ if (groupContainer) {
931
+ groupContainer.style.display = isCollapsed ? "none" : "";
932
+ }
933
+ };
934
+ }
935
+ _bindGroupCloseButton(button, getGroupContainer) {
936
+ button.onclick = () => {
937
+ const groupContainer = getGroupContainer();
938
+ if (groupContainer) {
939
+ Array.prototype.forEach.call(
940
+ groupContainer.children,
941
+ (el) => {
942
+ var _a;
943
+ (_a = el.__ableDOMIssueUI) == null ? void 0 : _a.toggle(false);
944
+ }
945
+ );
946
+ this._setShowHideButtonsVisibility();
947
+ }
948
+ this.highlight(null);
949
+ };
950
+ }
951
+ _hideHelpLinkIfMissing(help, helpLink) {
952
+ if (!helpLink) {
953
+ help.style.display = "none";
954
+ }
955
+ }
956
+ _updateGroupIssueCounts() {
957
+ for (const [groupName, container] of Object.entries(
958
+ this._issueGroupContainers
959
+ )) {
960
+ const countElement = this._issueGroupCountElements[groupName];
961
+ if (container && countElement) {
962
+ const count = container.children.length;
963
+ if (count === 0) {
964
+ this._removeIssueGroup(groupName, container);
965
+ continue;
966
+ }
967
+ countElement.textContent = `${count}`;
968
+ }
969
+ }
970
+ }
971
+ _removeIssueGroup(groupName, container) {
972
+ const groupElement = container.parentElement;
973
+ if (groupElement == null ? void 0 : groupElement.classList.contains("abledom-issue-group")) {
974
+ groupElement.remove();
975
+ } else {
976
+ container.remove();
977
+ }
978
+ delete this._issueGroupContainers[groupName];
979
+ delete this._issueGroupCountElements[groupName];
685
980
  }
686
981
  removeIssue(issue) {
687
982
  if (!this._issues.has(issue)) {
688
983
  return;
689
984
  }
690
985
  this._issues.delete(issue);
691
- this._setIssuesCount(this._issues.size);
692
- this._setShowHideButtonsVisibility();
986
+ this._syncMenuState();
987
+ this._updateGroupIssueCounts();
693
988
  this.highlight(null);
694
989
  }
695
- hideAll() {
696
- this._issues.forEach((issue) => {
697
- issue.toggle(false);
698
- });
699
- this._setShowHideButtonsVisibility();
700
- }
701
- showAll() {
990
+ toggleAll(show) {
991
+ if (show === void 0) {
992
+ const { allVisible } = this._getIssueVisibilityState();
993
+ show = !allVisible;
994
+ }
702
995
  this._issues.forEach((issue) => {
703
- issue.toggle(true);
996
+ issue.toggle(show);
704
997
  });
705
998
  this._setShowHideButtonsVisibility();
706
999
  }
@@ -794,20 +1087,12 @@ var ElementHighlighter = class {
794
1087
  delete this._cancelAutoHideTimer;
795
1088
  };
796
1089
  }
1090
+ this._unobserve();
797
1091
  this._intersectionObserver = new IntersectionObserver(([entry]) => {
798
- if (entry) {
799
- const rect = entry.boundingClientRect;
800
- const body = win.document.body;
801
- const style = container.style;
802
- if (container.parentElement !== body) {
803
- body.appendChild(container);
804
- }
805
- style.width = `${rect.width}px`;
806
- style.height = `${rect.height}px`;
807
- style.top = `${rect.top}px`;
808
- style.left = `${rect.left}px`;
809
- container.style.display = "block";
1092
+ if (!entry) {
1093
+ return;
810
1094
  }
1095
+ this._renderHighlightRect(entry.boundingClientRect, win.document.body);
811
1096
  });
812
1097
  this._intersectionObserver.observe(element);
813
1098
  }
@@ -822,6 +1107,21 @@ var ElementHighlighter = class {
822
1107
  delete this._container;
823
1108
  delete this._window;
824
1109
  }
1110
+ _renderHighlightRect(rect, body) {
1111
+ const container = this._container;
1112
+ if (!container) {
1113
+ return;
1114
+ }
1115
+ if (container.parentElement !== body) {
1116
+ body.appendChild(container);
1117
+ }
1118
+ const style = container.style;
1119
+ style.width = `${rect.width}px`;
1120
+ style.height = `${rect.height}px`;
1121
+ style.top = `${rect.top}px`;
1122
+ style.left = `${rect.left}px`;
1123
+ style.display = "block";
1124
+ }
825
1125
  _hide() {
826
1126
  this._container && (this._container.style.display = "none");
827
1127
  }
@@ -1547,6 +1847,7 @@ var AtomicRule = class extends ValidationRule {
1547
1847
  __publicField(this, "type", 1 /* Error */);
1548
1848
  __publicField(this, "name", "atomic");
1549
1849
  __publicField(this, "anchored", true);
1850
+ __publicField(this, "groupName", "Atomic violation");
1550
1851
  }
1551
1852
  accept(element) {
1552
1853
  return matchesSelector(element, focusableElementSelector);
@@ -1611,6 +1912,7 @@ var FocusableElementLabelRule = class extends ValidationRule {
1611
1912
  __publicField(this, "type", 1 /* Error */);
1612
1913
  __publicField(this, "name", "FocusableElementLabelRule");
1613
1914
  __publicField(this, "anchored", true);
1915
+ __publicField(this, "groupName", "Missing text label");
1614
1916
  }
1615
1917
  _isAriaHidden(element) {
1616
1918
  return element.ownerDocument.evaluate(
@@ -1786,6 +2088,7 @@ var ContrastRule = class extends ValidationRule {
1786
2088
  __publicField(this, "type", 1 /* Error */);
1787
2089
  __publicField(this, "name", "ContrastRule");
1788
2090
  __publicField(this, "anchored", true);
2091
+ __publicField(this, "groupName", "Insufficient color contrast");
1789
2092
  }
1790
2093
  accept(element) {
1791
2094
  if (!isElementVisible(element)) {
@@ -1875,6 +2178,7 @@ var ExistingIdRule = class extends ValidationRule {
1875
2178
  __publicField(this, "type", 1 /* Error */);
1876
2179
  __publicField(this, "name", "existing-id");
1877
2180
  __publicField(this, "anchored", true);
2181
+ __publicField(this, "groupName", "Referenced element not found");
1878
2182
  }
1879
2183
  accept(element) {
1880
2184
  return element.hasAttribute("aria-labelledby") || element.hasAttribute("aria-describedby") || element.tagName === "LABEL" && !!element.htmlFor;
@@ -1914,6 +2218,7 @@ var FocusLostRule = class extends ValidationRule {
1914
2218
  __publicField(this, "type", 1 /* Error */);
1915
2219
  __publicField(this, "name", "focus-lost");
1916
2220
  __publicField(this, "anchored", false);
2221
+ __publicField(this, "groupName", "Focus lost");
1917
2222
  __publicField(this, "_focusLostTimeout", 2e3);
1918
2223
  // For now reporting lost focus after 2 seconds of it being lost.
1919
2224
  __publicField(this, "_clearScheduledFocusLost");
@@ -2023,6 +2328,7 @@ var BadFocusRule = class extends ValidationRule {
2023
2328
  __publicField(this, "type", 1 /* Error */);
2024
2329
  __publicField(this, "name", "bad-focus");
2025
2330
  __publicField(this, "anchored", false);
2331
+ __publicField(this, "groupName", "Bad focus");
2026
2332
  __publicField(this, "_lastFocusStack");
2027
2333
  __publicField(this, "_lastBlurStack");
2028
2334
  __publicField(this, "_clearCheckTimer");
@@ -2074,6 +2380,7 @@ var FindElementRule = class extends ValidationRule {
2074
2380
  __publicField(this, "type", 2 /* Warning */);
2075
2381
  __publicField(this, "name", "find-element");
2076
2382
  __publicField(this, "anchored", true);
2383
+ __publicField(this, "groupName", "Element found");
2077
2384
  __publicField(this, "_conditions", {});
2078
2385
  }
2079
2386
  addCondition(name, condition) {
@@ -2122,6 +2429,7 @@ var RequiredParentRule = class extends ValidationRule {
2122
2429
  __publicField(this, "type", 1 /* Error */);
2123
2430
  __publicField(this, "name", "aria-required-parent");
2124
2431
  __publicField(this, "anchored", true);
2432
+ __publicField(this, "groupName", "Missing required parent");
2125
2433
  __publicField(this, "parentRequirements", /* @__PURE__ */ new Map([
2126
2434
  [
2127
2435
  "LI",
@@ -2438,6 +2746,7 @@ var NestedInteractiveElementRule = class extends ValidationRule {
2438
2746
  __publicField(this, "type", 1 /* Error */);
2439
2747
  __publicField(this, "name", "NestedInteractiveElementRule");
2440
2748
  __publicField(this, "anchored", true);
2749
+ __publicField(this, "groupName", "Nested interactive element");
2441
2750
  }
2442
2751
  _isAriaHidden(element) {
2443
2752
  return element.ownerDocument.evaluate(
@@ -2535,6 +2844,7 @@ var TabIndexRule = class extends ValidationRule {
2535
2844
  __publicField(this, "type", 2 /* Warning */);
2536
2845
  __publicField(this, "name", "tabindex");
2537
2846
  __publicField(this, "anchored", true);
2847
+ __publicField(this, "groupName", "Positive tabindex");
2538
2848
  }
2539
2849
  accept(element) {
2540
2850
  return element.hasAttribute("tabindex");