abledom 0.6.5 → 0.7.0

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-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,134 @@ 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
+ countElement.textContent = `${count}`;
964
+ }
965
+ }
685
966
  }
686
967
  removeIssue(issue) {
687
968
  if (!this._issues.has(issue)) {
688
969
  return;
689
970
  }
690
971
  this._issues.delete(issue);
691
- this._setIssuesCount(this._issues.size);
692
- this._setShowHideButtonsVisibility();
972
+ this._syncMenuState();
973
+ this._updateGroupIssueCounts();
693
974
  this.highlight(null);
694
975
  }
695
- hideAll() {
696
- this._issues.forEach((issue) => {
697
- issue.toggle(false);
698
- });
699
- this._setShowHideButtonsVisibility();
700
- }
701
- showAll() {
976
+ toggleAll(show) {
977
+ if (show === void 0) {
978
+ const { allVisible } = this._getIssueVisibilityState();
979
+ show = !allVisible;
980
+ }
702
981
  this._issues.forEach((issue) => {
703
- issue.toggle(true);
982
+ issue.toggle(show);
704
983
  });
705
984
  this._setShowHideButtonsVisibility();
706
985
  }
@@ -794,20 +1073,12 @@ var ElementHighlighter = class {
794
1073
  delete this._cancelAutoHideTimer;
795
1074
  };
796
1075
  }
1076
+ this._unobserve();
797
1077
  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";
1078
+ if (!entry) {
1079
+ return;
810
1080
  }
1081
+ this._renderHighlightRect(entry.boundingClientRect, win.document.body);
811
1082
  });
812
1083
  this._intersectionObserver.observe(element);
813
1084
  }
@@ -822,6 +1093,21 @@ var ElementHighlighter = class {
822
1093
  delete this._container;
823
1094
  delete this._window;
824
1095
  }
1096
+ _renderHighlightRect(rect, body) {
1097
+ const container = this._container;
1098
+ if (!container) {
1099
+ return;
1100
+ }
1101
+ if (container.parentElement !== body) {
1102
+ body.appendChild(container);
1103
+ }
1104
+ const style = container.style;
1105
+ style.width = `${rect.width}px`;
1106
+ style.height = `${rect.height}px`;
1107
+ style.top = `${rect.top}px`;
1108
+ style.left = `${rect.left}px`;
1109
+ style.display = "block";
1110
+ }
825
1111
  _hide() {
826
1112
  this._container && (this._container.style.display = "none");
827
1113
  }
@@ -1547,6 +1833,7 @@ var AtomicRule = class extends ValidationRule {
1547
1833
  __publicField(this, "type", 1 /* Error */);
1548
1834
  __publicField(this, "name", "atomic");
1549
1835
  __publicField(this, "anchored", true);
1836
+ __publicField(this, "groupName", "Atomic violation");
1550
1837
  }
1551
1838
  accept(element) {
1552
1839
  return matchesSelector(element, focusableElementSelector);
@@ -1611,6 +1898,7 @@ var FocusableElementLabelRule = class extends ValidationRule {
1611
1898
  __publicField(this, "type", 1 /* Error */);
1612
1899
  __publicField(this, "name", "FocusableElementLabelRule");
1613
1900
  __publicField(this, "anchored", true);
1901
+ __publicField(this, "groupName", "Missing text label");
1614
1902
  }
1615
1903
  _isAriaHidden(element) {
1616
1904
  return element.ownerDocument.evaluate(
@@ -1786,6 +2074,7 @@ var ContrastRule = class extends ValidationRule {
1786
2074
  __publicField(this, "type", 1 /* Error */);
1787
2075
  __publicField(this, "name", "ContrastRule");
1788
2076
  __publicField(this, "anchored", true);
2077
+ __publicField(this, "groupName", "Insufficient color contrast");
1789
2078
  }
1790
2079
  accept(element) {
1791
2080
  if (!isElementVisible(element)) {
@@ -1875,6 +2164,7 @@ var ExistingIdRule = class extends ValidationRule {
1875
2164
  __publicField(this, "type", 1 /* Error */);
1876
2165
  __publicField(this, "name", "existing-id");
1877
2166
  __publicField(this, "anchored", true);
2167
+ __publicField(this, "groupName", "Referenced element not found");
1878
2168
  }
1879
2169
  accept(element) {
1880
2170
  return element.hasAttribute("aria-labelledby") || element.hasAttribute("aria-describedby") || element.tagName === "LABEL" && !!element.htmlFor;
@@ -1914,6 +2204,7 @@ var FocusLostRule = class extends ValidationRule {
1914
2204
  __publicField(this, "type", 1 /* Error */);
1915
2205
  __publicField(this, "name", "focus-lost");
1916
2206
  __publicField(this, "anchored", false);
2207
+ __publicField(this, "groupName", "Focus lost");
1917
2208
  __publicField(this, "_focusLostTimeout", 2e3);
1918
2209
  // For now reporting lost focus after 2 seconds of it being lost.
1919
2210
  __publicField(this, "_clearScheduledFocusLost");
@@ -2023,6 +2314,7 @@ var BadFocusRule = class extends ValidationRule {
2023
2314
  __publicField(this, "type", 1 /* Error */);
2024
2315
  __publicField(this, "name", "bad-focus");
2025
2316
  __publicField(this, "anchored", false);
2317
+ __publicField(this, "groupName", "Bad focus");
2026
2318
  __publicField(this, "_lastFocusStack");
2027
2319
  __publicField(this, "_lastBlurStack");
2028
2320
  __publicField(this, "_clearCheckTimer");
@@ -2074,6 +2366,7 @@ var FindElementRule = class extends ValidationRule {
2074
2366
  __publicField(this, "type", 2 /* Warning */);
2075
2367
  __publicField(this, "name", "find-element");
2076
2368
  __publicField(this, "anchored", true);
2369
+ __publicField(this, "groupName", "Element found");
2077
2370
  __publicField(this, "_conditions", {});
2078
2371
  }
2079
2372
  addCondition(name, condition) {
@@ -2122,6 +2415,7 @@ var RequiredParentRule = class extends ValidationRule {
2122
2415
  __publicField(this, "type", 1 /* Error */);
2123
2416
  __publicField(this, "name", "aria-required-parent");
2124
2417
  __publicField(this, "anchored", true);
2418
+ __publicField(this, "groupName", "Missing required parent");
2125
2419
  __publicField(this, "parentRequirements", /* @__PURE__ */ new Map([
2126
2420
  [
2127
2421
  "LI",
@@ -2438,6 +2732,7 @@ var NestedInteractiveElementRule = class extends ValidationRule {
2438
2732
  __publicField(this, "type", 1 /* Error */);
2439
2733
  __publicField(this, "name", "NestedInteractiveElementRule");
2440
2734
  __publicField(this, "anchored", true);
2735
+ __publicField(this, "groupName", "Nested interactive element");
2441
2736
  }
2442
2737
  _isAriaHidden(element) {
2443
2738
  return element.ownerDocument.evaluate(
@@ -2535,6 +2830,7 @@ var TabIndexRule = class extends ValidationRule {
2535
2830
  __publicField(this, "type", 2 /* Warning */);
2536
2831
  __publicField(this, "name", "tabindex");
2537
2832
  __publicField(this, "anchored", true);
2833
+ __publicField(this, "groupName", "Positive tabindex");
2538
2834
  }
2539
2835
  accept(element) {
2540
2836
  return element.hasAttribute("tabindex");