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/index.js CHANGED
@@ -56,6 +56,11 @@ var ValidationRule = class {
56
56
  __publicField(this, "_window");
57
57
  __publicField(this, "_exceptions", []);
58
58
  __publicField(this, "_onIssue");
59
+ /**
60
+ * A short friendly group name for grouping issues in the UI.
61
+ * If undefined, the issue will not be grouped.
62
+ */
63
+ __publicField(this, "groupName");
59
64
  }
60
65
  static init(instance, window, onIssue) {
61
66
  instance._window = window;
@@ -100,7 +105,7 @@ var ValidationRule = class {
100
105
  };
101
106
 
102
107
  // inline-file:/Users/marata/tmp/abledom/src/ui/ui.css
103
- 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";
108
+ 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";
104
109
 
105
110
  // inline-file:/Users/marata/tmp/abledom/src/ui/highlighter.css
106
111
  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";
@@ -113,27 +118,29 @@ var DOMBuilder = class {
113
118
  this._doc = parent.ownerDocument;
114
119
  this._stack = [parent];
115
120
  }
116
- openTag(tagName, attributes, callback, namespace) {
121
+ openTag(tagName, attributes, callback, namespace, skip) {
117
122
  var _a, _b;
118
123
  const parent = this._stack[0];
119
- const element = namespace ? (_a = this._doc) == null ? void 0 : _a.createElementNS(namespace, tagName) : (_b = this._doc) == null ? void 0 : _b.createElement(tagName);
120
- if (parent && element) {
121
- element.__abledomui = true;
122
- if (attributes) {
123
- for (const [key, value] of Object.entries(attributes)) {
124
- if (key === "class") {
125
- element.className = value;
126
- } else if (key === "style") {
127
- element.style.cssText = value;
128
- } else {
129
- element.setAttribute(key, value);
124
+ const element = skip ? null : namespace ? (_a = this._doc) == null ? void 0 : _a.createElementNS(namespace, tagName) : (_b = this._doc) == null ? void 0 : _b.createElement(tagName);
125
+ if (parent !== void 0) {
126
+ if (parent && element) {
127
+ element.__abledomui = true;
128
+ if (attributes) {
129
+ for (const [key, value] of Object.entries(attributes)) {
130
+ if (key === "class") {
131
+ element.className = value;
132
+ } else if (key === "style") {
133
+ element.style.cssText = value;
134
+ } else {
135
+ element.setAttribute(key, value);
136
+ }
130
137
  }
131
138
  }
139
+ if (callback) {
140
+ callback(element);
141
+ }
142
+ parent.appendChild(element);
132
143
  }
133
- if (callback) {
134
- callback(element);
135
- }
136
- parent.appendChild(element);
137
144
  this._stack.unshift(element);
138
145
  }
139
146
  return this;
@@ -155,7 +162,8 @@ var DOMBuilder = class {
155
162
  return this;
156
163
  }
157
164
  element(callback) {
158
- callback(this._stack[0]);
165
+ const el = this._stack[0];
166
+ el && callback(el);
159
167
  return this;
160
168
  }
161
169
  };
@@ -328,8 +336,31 @@ var alignbottomleft_default = (function buildSVG12(parent) {
328
336
  return parent.firstElementChild;
329
337
  });
330
338
 
339
+ // inline-file:/Users/marata/tmp/abledom/src/ui/chevrondown.svg
340
+ var chevrondown_default = (function buildSVG13(parent) {
341
+ const builder = new DOMBuilder(parent);
342
+ 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");
343
+ builder.openTag("polyline", { "points": "6 9 12 15 18 9" }, void 0, "http://www.w3.org/2000/svg");
344
+ builder.closeTag();
345
+ builder.closeTag();
346
+ return parent.firstElementChild;
347
+ });
348
+
349
+ // inline-file:/Users/marata/tmp/abledom/src/ui/chevronright.svg
350
+ var chevronright_default = (function buildSVG14(parent) {
351
+ const builder = new DOMBuilder(parent);
352
+ 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");
353
+ builder.openTag("polyline", { "points": "9 6 15 12 9 18" }, void 0, "http://www.w3.org/2000/svg");
354
+ builder.closeTag();
355
+ builder.closeTag();
356
+ return parent.firstElementChild;
357
+ });
358
+
331
359
  // src/ui/ui.ts
332
360
  var pressedClass = "pressed";
361
+ function getIssueTypeClass(type) {
362
+ return type === 2 /* Warning */ ? " abledom-issue_warning" : type === 3 /* Info */ ? " abledom-issue_info" : "";
363
+ }
333
364
  var IssueUI = class {
334
365
  constructor(win, core, rule, issuesUI) {
335
366
  __publicField(this, "_core");
@@ -337,6 +368,7 @@ var IssueUI = class {
337
368
  __publicField(this, "_wrapper");
338
369
  __publicField(this, "_rule");
339
370
  __publicField(this, "_onToggle");
371
+ __publicField(this, "_appended", false);
340
372
  __publicField(this, "isHidden", false);
341
373
  this._core = core;
342
374
  this._rule = rule;
@@ -345,35 +377,62 @@ var IssueUI = class {
345
377
  this._wrapper = win.document.createElement(
346
378
  "div"
347
379
  );
380
+ this._wrapper.__ableDOMIssueUI = this;
381
+ this._wrapper.className = "abledom-issue-container-wrapper";
348
382
  }
349
383
  issuesUI.addIssue(this);
350
384
  }
351
385
  static setOnToggle(instance, onToggle) {
352
386
  instance._onToggle = onToggle;
353
387
  }
354
- static getElement(instance) {
355
- return instance._wrapper;
388
+ static setAppended(instance) {
389
+ instance._appended = true;
356
390
  }
357
391
  update(issue) {
358
- const rule = this._rule;
359
392
  const wrapper = this._wrapper;
360
- const element = issue.element;
361
393
  if (!wrapper) {
362
394
  return;
363
395
  }
396
+ this._appendToIssueContainer(issue);
364
397
  wrapper.__abledomui = true;
365
398
  wrapper.textContent = "";
399
+ this._renderIssueContent(wrapper, issue);
400
+ }
401
+ _appendToIssueContainer(issue) {
402
+ var _a, _b, _c;
403
+ if (!this._appended) {
404
+ return;
405
+ }
406
+ const wrapper = this._wrapper;
407
+ const rule = this._rule;
408
+ if (!wrapper) {
409
+ return;
410
+ }
411
+ const issueContainer = (_a = this._issuesUI) == null ? void 0 : _a.getIssueContainer(
412
+ rule.type,
413
+ rule.groupName,
414
+ issue.help
415
+ );
416
+ if (!issueContainer || wrapper.parentElement === issueContainer) {
417
+ return;
418
+ }
419
+ issueContainer.appendChild(wrapper);
420
+ if (!this.isHidden) {
421
+ if ((_b = issueContainer.parentElement) == null ? void 0 : _b.classList.contains("abledom-issue-group")) {
422
+ issueContainer.parentElement.style.display = "block";
423
+ }
424
+ } else {
425
+ this.toggle(false, true);
426
+ }
427
+ (_c = this._issuesUI) == null ? void 0 : _c.syncGroupIssueCounts();
428
+ }
429
+ _renderIssueContent(wrapper, issue) {
430
+ const rule = this._rule;
431
+ const element = issue.element;
366
432
  new DOMBuilder(wrapper).openTag("div", { class: "abledom-issue-container" }, (container) => {
367
- container.onmouseenter = () => {
368
- var _a;
369
- element && ((_a = this._issuesUI) == null ? void 0 : _a.highlight(element));
370
- };
371
- container.onmouseleave = () => {
372
- var _a;
373
- (_a = this._issuesUI) == null ? void 0 : _a.highlight(null);
374
- };
433
+ this._bindIssueContainerHover(container, element);
375
434
  }).openTag("div", {
376
- class: `abledom-issue${rule.type === 2 /* Warning */ ? " abledom-issue_warning" : rule.type === 3 /* Info */ ? " abledom-issue_info" : ""}`
435
+ class: `abledom-issue${getIssueTypeClass(rule.type)}`
377
436
  }).openTag(
378
437
  "button",
379
438
  {
@@ -381,21 +440,7 @@ var IssueUI = class {
381
440
  title: "Log to Console"
382
441
  },
383
442
  (logButton) => {
384
- logButton.onclick = () => {
385
- const { id, message, element: element2, rel, help, ...extra } = issue;
386
- this._core.log(
387
- "AbleDOM: ",
388
- "\nid:",
389
- id,
390
- "\nmessage:",
391
- message,
392
- "\nelement:",
393
- element2,
394
- ...rel ? ["\nrelative:", rel] : [],
395
- ...help ? ["\nhelp:", help] : [],
396
- ...Object.keys(extra).length > 0 ? ["\nextra:", extra] : []
397
- );
398
- };
443
+ this._bindLogButton(logButton, issue);
399
444
  }
400
445
  ).element(log_default).closeTag().openTag(
401
446
  "button",
@@ -405,16 +450,10 @@ var IssueUI = class {
405
450
  title: "Scroll element into view"
406
451
  },
407
452
  (revealButton) => {
408
- const element2 = issue.element;
409
- if (element2) {
410
- revealButton.onclick = () => {
411
- var _a;
412
- (_a = this._issuesUI) == null ? void 0 : _a.highlight(element2, true);
413
- };
414
- } else {
415
- revealButton.style.display = "none";
416
- }
417
- }
453
+ this._bindRevealButton(revealButton, issue);
454
+ },
455
+ void 0,
456
+ !issue.element
418
457
  ).element(reveal_default).closeTag().openTag(
419
458
  "button",
420
459
  {
@@ -422,33 +461,21 @@ var IssueUI = class {
422
461
  title: "Report bug"
423
462
  },
424
463
  (bugReportButton) => {
425
- var _a, _b;
426
- const bugReport = (_a = this._issuesUI) == null ? void 0 : _a.bugReport;
427
- if (bugReport == null ? void 0 : bugReport.isVisible(issue)) {
428
- const title = (_b = bugReport.getTitle) == null ? void 0 : _b.call(bugReport, issue);
429
- if (title) {
430
- bugReportButton.title = title;
431
- }
432
- bugReportButton.onclick = () => {
433
- bugReport.onClick(issue);
434
- };
435
- } else {
436
- bugReportButton.style.display = "none";
437
- }
464
+ this._bindBugReportButton(bugReportButton, issue);
438
465
  }
439
466
  ).element(bug_default).closeTag().text(issue.message).openTag(
440
467
  "a",
441
468
  {
442
- class: "button close",
469
+ class: "button help",
443
470
  href: issue.help || "/",
444
471
  title: "Open help",
445
472
  target: "_blank"
446
473
  },
447
474
  (help) => {
448
- if (!issue.help) {
449
- help.style.display = "none";
450
- }
451
- }
475
+ this._bindHelpLink(help, issue.help);
476
+ },
477
+ void 0,
478
+ !!rule.groupName
452
479
  ).element(help_default).closeTag().openTag(
453
480
  "button",
454
481
  {
@@ -456,27 +483,116 @@ var IssueUI = class {
456
483
  title: "Hide"
457
484
  },
458
485
  (closeButton) => {
459
- closeButton.onclick = () => {
460
- var _a;
461
- this.toggle(false);
462
- (_a = this._issuesUI) == null ? void 0 : _a.highlight(null);
463
- };
486
+ this._bindCloseButton(closeButton);
464
487
  }
465
488
  ).element(close_default).closeTag().closeTag().closeTag();
466
489
  }
490
+ _bindIssueContainerHover(container, element) {
491
+ container.onmouseenter = () => {
492
+ var _a;
493
+ element && ((_a = this._issuesUI) == null ? void 0 : _a.highlight(element));
494
+ };
495
+ container.onmouseleave = () => {
496
+ var _a;
497
+ (_a = this._issuesUI) == null ? void 0 : _a.highlight(null);
498
+ };
499
+ }
500
+ _bindLogButton(button, issue) {
501
+ button.onclick = () => {
502
+ const { id, message, element, rel, help, ...extra } = issue;
503
+ this._core.log(
504
+ "AbleDOM: ",
505
+ "\nid:",
506
+ id,
507
+ "\nmessage:",
508
+ message,
509
+ "\nelement:",
510
+ element,
511
+ ...rel ? ["\nrelative:", rel] : [],
512
+ ...help ? ["\nhelp:", help] : [],
513
+ ...Object.keys(extra).length > 0 ? ["\nextra:", extra] : []
514
+ );
515
+ };
516
+ }
517
+ _bindRevealButton(button, issue) {
518
+ const element = issue.element;
519
+ if (element) {
520
+ button.onclick = () => {
521
+ var _a;
522
+ (_a = this._issuesUI) == null ? void 0 : _a.highlight(element, true);
523
+ };
524
+ }
525
+ }
526
+ _bindBugReportButton(button, issue) {
527
+ var _a, _b;
528
+ const bugReport = (_a = this._issuesUI) == null ? void 0 : _a.bugReport;
529
+ if (bugReport == null ? void 0 : bugReport.isVisible(issue)) {
530
+ const title = (_b = bugReport.getTitle) == null ? void 0 : _b.call(bugReport, issue);
531
+ if (title) {
532
+ button.title = title;
533
+ }
534
+ button.onclick = () => {
535
+ bugReport.onClick(issue);
536
+ };
537
+ } else {
538
+ button.style.display = "none";
539
+ }
540
+ }
541
+ _bindHelpLink(help, issueHelp) {
542
+ if (!issueHelp) {
543
+ help.style.display = "none";
544
+ }
545
+ }
546
+ _bindCloseButton(button) {
547
+ button.onclick = () => {
548
+ var _a;
549
+ this.toggle(false);
550
+ (_a = this._issuesUI) == null ? void 0 : _a.highlight(null);
551
+ };
552
+ }
467
553
  toggle(show, initial = false) {
468
554
  var _a;
469
555
  if (!this._wrapper) {
470
556
  return;
471
557
  }
472
- this.isHidden = !show;
558
+ if (show === void 0) {
559
+ this.isHidden = !this.isHidden;
560
+ show = !this.isHidden;
561
+ } else {
562
+ this.isHidden = !show;
563
+ }
473
564
  if (!initial) {
474
- (_a = this._onToggle) == null ? void 0 : _a.call(this, this, show);
475
- if (!this._rule.anchored && !show) {
565
+ (_a = this._onToggle) == null ? void 0 : _a.call(this, this, !this.isHidden);
566
+ if (!this._rule.anchored && this.isHidden) {
476
567
  this.dispose();
477
568
  }
478
569
  }
479
570
  this._wrapper.style.display = show ? "block" : "none";
571
+ this._syncGroupVisibility(!!show);
572
+ }
573
+ _syncGroupVisibility(show) {
574
+ const wrapper = this._wrapper;
575
+ if (!wrapper) {
576
+ return;
577
+ }
578
+ const potentiallyGroupIssuesElement = wrapper.parentElement;
579
+ const potentiallyGroupElement = potentiallyGroupIssuesElement == null ? void 0 : potentiallyGroupIssuesElement.parentElement;
580
+ if (!potentiallyGroupIssuesElement || !(potentiallyGroupElement == null ? void 0 : potentiallyGroupElement.classList.contains("abledom-issue-group"))) {
581
+ return;
582
+ }
583
+ if (show) {
584
+ potentiallyGroupElement.style.display = "block";
585
+ return;
586
+ }
587
+ if (potentiallyGroupElement.style.display !== "none" && Array.prototype.every.call(
588
+ potentiallyGroupIssuesElement.children,
589
+ (el) => {
590
+ var _a;
591
+ return el.__ableDOMIssueUI ? (_a = el.__ableDOMIssueUI) == null ? void 0 : _a.isHidden : true;
592
+ }
593
+ )) {
594
+ potentiallyGroupElement.style.display = "none";
595
+ }
480
596
  }
481
597
  dispose() {
482
598
  var _a, _b;
@@ -500,6 +616,8 @@ var IssuesUI = class {
500
616
  __publicField(this, "_alignBottomRightButton");
501
617
  __publicField(this, "_isMuted", false);
502
618
  __publicField(this, "_issues", /* @__PURE__ */ new Set());
619
+ __publicField(this, "_issueGroupContainers", {});
620
+ __publicField(this, "_issueGroupCountElements", {});
503
621
  __publicField(this, "_getHighlighter");
504
622
  __publicField(this, "bugReport");
505
623
  __publicField(this, "headless");
@@ -511,31 +629,54 @@ var IssuesUI = class {
511
629
  return;
512
630
  }
513
631
  const doc = win.document;
514
- const container = this._container = doc.createElement("div");
632
+ const container = this._container = this._createRootContainer(doc);
633
+ this._issuesContainer = this._createIssuesContainer(doc, container);
634
+ const menuElement = this._menuElement = this._createMenuContainer(
635
+ doc,
636
+ container
637
+ );
638
+ this._buildMenu(menuElement);
639
+ doc.body.appendChild(container);
640
+ }
641
+ _createRootContainer(doc) {
642
+ const container = doc.createElement("div");
515
643
  container.__abledomui = true;
516
644
  container.id = "abledom-report";
517
645
  const style = doc.createElement("style");
518
646
  style.type = "text/css";
519
647
  style.appendChild(doc.createTextNode(ui_default));
520
648
  container.appendChild(style);
521
- const issuesContainer = this._issuesContainer = doc.createElement("div");
649
+ return container;
650
+ }
651
+ _createIssuesContainer(doc, container) {
652
+ const issuesContainer = doc.createElement(
653
+ "div"
654
+ );
522
655
  issuesContainer.__abledomui = true;
523
656
  issuesContainer.className = "abledom-issues-container";
524
657
  container.appendChild(issuesContainer);
525
- const menuElement = this._menuElement = doc.createElement("div");
658
+ return issuesContainer;
659
+ }
660
+ _createMenuContainer(doc, container) {
661
+ const menuElement = doc.createElement(
662
+ "div"
663
+ );
526
664
  menuElement.__abledomui = true;
527
665
  menuElement.className = "abledom-menu-container";
528
666
  container.appendChild(menuElement);
529
- new DOMBuilder(menuElement).openTag("div", { class: "abledom-menu" }).openTag(
667
+ return menuElement;
668
+ }
669
+ _buildMenu(menuElement) {
670
+ new DOMBuilder(menuElement).openTag("div", { class: "abledom-menu-wrapper" }).openTag("div", { class: "abledom-menu" }).openTag(
530
671
  "span",
531
672
  {
532
673
  class: "issues-count",
533
674
  title: "Number of issues"
534
675
  },
535
676
  (issueCountElement) => {
536
- this._issueCountElement = issueCountElement;
677
+ this._bindIssueCountElement(issueCountElement);
537
678
  }
538
- ).closeTag().openTag(
679
+ ).closeTag().openTag("div", { class: "controls-wrapper" }).openTag("div", { class: "controls" }).openTag(
539
680
  "button",
540
681
  {
541
682
  class: "button",
@@ -543,9 +684,7 @@ var IssuesUI = class {
543
684
  },
544
685
  (showAllButton) => {
545
686
  this._showAllButton = showAllButton;
546
- showAllButton.onclick = () => {
547
- this.showAll();
548
- };
687
+ this._bindToggleAllButton(showAllButton, true);
549
688
  }
550
689
  ).element(showall_default).closeTag().openTag(
551
690
  "button",
@@ -555,9 +694,7 @@ var IssuesUI = class {
555
694
  },
556
695
  (hideAllButton) => {
557
696
  this._hideAllButton = hideAllButton;
558
- hideAllButton.onclick = () => {
559
- this.hideAll();
560
- };
697
+ this._bindToggleAllButton(hideAllButton, false);
561
698
  }
562
699
  ).element(hideall_default).closeTag().openTag(
563
700
  "button",
@@ -566,14 +703,7 @@ var IssuesUI = class {
566
703
  title: "Mute newly appearing issues"
567
704
  },
568
705
  (muteButton) => {
569
- muteButton.onclick = () => {
570
- const isMuted = this._isMuted = muteButton.classList.toggle(pressedClass);
571
- if (isMuted) {
572
- muteButton.setAttribute("title", "Unmute newly appearing issues");
573
- } else {
574
- muteButton.setAttribute("title", "Mute newly appearing issues");
575
- }
576
- };
706
+ this._bindMuteButton(muteButton);
577
707
  }
578
708
  ).element(muteall_default).closeTag().openTag(
579
709
  "button",
@@ -583,9 +713,10 @@ var IssuesUI = class {
583
713
  },
584
714
  (alignBottomLeftButton) => {
585
715
  this._alignBottomLeftButton = alignBottomLeftButton;
586
- alignBottomLeftButton.onclick = () => {
587
- this.setUIAlignment("bottom-left" /* BottomLeft */);
588
- };
716
+ this._bindAlignmentButton(
717
+ alignBottomLeftButton,
718
+ "bottom-left" /* BottomLeft */
719
+ );
589
720
  }
590
721
  ).element(alignbottomleft_default).closeTag().openTag(
591
722
  "button",
@@ -595,9 +726,7 @@ var IssuesUI = class {
595
726
  },
596
727
  (alignTopLeftButton) => {
597
728
  this._alignTopLeftButton = alignTopLeftButton;
598
- alignTopLeftButton.onclick = () => {
599
- this.setUIAlignment("top-left" /* TopLeft */);
600
- };
729
+ this._bindAlignmentButton(alignTopLeftButton, "top-left" /* TopLeft */);
601
730
  }
602
731
  ).element(aligntopleft_default).closeTag().openTag(
603
732
  "button",
@@ -607,9 +736,7 @@ var IssuesUI = class {
607
736
  },
608
737
  (alignTopRightButton) => {
609
738
  this._alignTopRightButton = alignTopRightButton;
610
- alignTopRightButton.onclick = () => {
611
- this.setUIAlignment("top-right" /* TopRight */);
612
- };
739
+ this._bindAlignmentButton(alignTopRightButton, "top-right" /* TopRight */);
613
740
  }
614
741
  ).element(aligntopright_default).closeTag().openTag(
615
742
  "button",
@@ -619,55 +746,89 @@ var IssuesUI = class {
619
746
  },
620
747
  (alignBottomRightButton) => {
621
748
  this._alignBottomRightButton = alignBottomRightButton;
622
- alignBottomRightButton.onclick = () => {
623
- this.setUIAlignment("bottom-right" /* BottomRight */);
624
- };
749
+ this._bindAlignmentButton(
750
+ alignBottomRightButton,
751
+ "bottom-right" /* BottomRight */
752
+ );
625
753
  }
626
- ).element(alignbottomright_default).closeTag().closeTag();
627
- doc.body.appendChild(container);
754
+ ).element(alignbottomright_default).closeTag().closeTag().closeTag().closeTag().closeTag();
755
+ }
756
+ _bindToggleAllButton(button, show) {
757
+ button.onclick = () => {
758
+ this.toggleAll(show);
759
+ };
760
+ }
761
+ _bindIssueCountElement(element) {
762
+ this._issueCountElement = element;
763
+ element.onclick = () => {
764
+ this.toggleAll();
765
+ };
766
+ }
767
+ _bindMuteButton(button) {
768
+ button.onclick = () => {
769
+ const isMuted = this._isMuted = button.classList.toggle(pressedClass);
770
+ button.setAttribute(
771
+ "title",
772
+ isMuted ? "Unmute newly appearing issues" : "Mute newly appearing issues"
773
+ );
774
+ };
775
+ }
776
+ _bindAlignmentButton(button, alignment) {
777
+ button.onclick = () => {
778
+ this.setUIAlignment(alignment);
779
+ };
628
780
  }
629
781
  setUIAlignment(alignment) {
630
- var _a, _b, _c, _d, _e, _f, _g, _h;
631
782
  if (!this._container || !this._issuesContainer || !this._menuElement) {
632
783
  return;
633
784
  }
634
- (_a = this._alignBottomLeftButton) == null ? void 0 : _a.classList.remove(pressedClass);
635
- (_b = this._alignBottomRightButton) == null ? void 0 : _b.classList.remove(pressedClass);
636
- (_c = this._alignTopLeftButton) == null ? void 0 : _c.classList.remove(pressedClass);
637
- (_d = this._alignTopRightButton) == null ? void 0 : _d.classList.remove(pressedClass);
785
+ this._clearAlignmentButtons();
638
786
  this._container.classList.remove(
639
787
  "abledom-align-left",
640
788
  "abledom-align-right",
641
789
  "abledom-align-top",
642
790
  "abledom-align-bottom"
643
791
  );
792
+ const { containerClasses, issuesFirst, activeButton } = this._getAlignmentLayout(alignment);
793
+ activeButton == null ? void 0 : activeButton.classList.add(pressedClass);
794
+ this._container.classList.add(...containerClasses);
795
+ this._container.insertBefore(
796
+ this._issuesContainer,
797
+ issuesFirst ? this._menuElement : null
798
+ );
799
+ }
800
+ _clearAlignmentButtons() {
801
+ var _a, _b, _c, _d;
802
+ (_a = this._alignBottomLeftButton) == null ? void 0 : _a.classList.remove(pressedClass);
803
+ (_b = this._alignBottomRightButton) == null ? void 0 : _b.classList.remove(pressedClass);
804
+ (_c = this._alignTopLeftButton) == null ? void 0 : _c.classList.remove(pressedClass);
805
+ (_d = this._alignTopRightButton) == null ? void 0 : _d.classList.remove(pressedClass);
806
+ }
807
+ _getAlignmentLayout(alignment) {
644
808
  let containerClasses = [];
645
809
  let issuesFirst = false;
810
+ let activeButton;
646
811
  switch (alignment) {
647
812
  case "bottom-left" /* BottomLeft */:
648
813
  containerClasses = ["abledom-align-left", "abledom-align-bottom"];
649
814
  issuesFirst = true;
650
- (_e = this._alignBottomLeftButton) == null ? void 0 : _e.classList.add(pressedClass);
815
+ activeButton = this._alignBottomLeftButton;
651
816
  break;
652
817
  case "bottom-right" /* BottomRight */:
653
818
  containerClasses = ["abledom-align-right", "abledom-align-bottom"];
654
819
  issuesFirst = true;
655
- (_f = this._alignBottomRightButton) == null ? void 0 : _f.classList.add(pressedClass);
820
+ activeButton = this._alignBottomRightButton;
656
821
  break;
657
822
  case "top-left" /* TopLeft */:
658
823
  containerClasses = ["abledom-align-left", "abledom-align-top"];
659
- (_g = this._alignTopLeftButton) == null ? void 0 : _g.classList.add(pressedClass);
824
+ activeButton = this._alignTopLeftButton;
660
825
  break;
661
826
  case "top-right" /* TopRight */:
662
827
  containerClasses = ["abledom-align-right", "abledom-align-top"];
663
- (_h = this._alignTopRightButton) == null ? void 0 : _h.classList.add(pressedClass);
828
+ activeButton = this._alignTopRightButton;
664
829
  break;
665
830
  }
666
- this._container.classList.add(...containerClasses);
667
- this._container.insertBefore(
668
- this._issuesContainer,
669
- issuesFirst ? this._menuElement : null
670
- );
831
+ return { containerClasses, issuesFirst, activeButton };
671
832
  }
672
833
  _setIssuesCount(count) {
673
834
  if (!this._menuElement) {
@@ -675,11 +836,19 @@ var IssuesUI = class {
675
836
  }
676
837
  const countElement = this._issueCountElement;
677
838
  if (countElement && count > 0) {
678
- countElement.textContent = "";
679
- new DOMBuilder(countElement).openTag("strong").text(`${count}`).closeTag().text(` issue${count > 1 ? "s" : ""}`);
680
- this._menuElement.style.display = "block";
839
+ this._renderIssueCountText(countElement, count);
840
+ this._setMenuVisibility(true);
681
841
  } else {
682
- this._menuElement.style.display = "none";
842
+ this._setMenuVisibility(false);
843
+ }
844
+ }
845
+ _renderIssueCountText(countElement, count) {
846
+ countElement.textContent = "";
847
+ new DOMBuilder(countElement).openTag("strong").text(`${count}`).closeTag().text(` issue${count > 1 ? "s" : ""}`);
848
+ }
849
+ _setMenuVisibility(visible) {
850
+ if (this._menuElement) {
851
+ this._menuElement.style.display = visible ? "block" : "none";
683
852
  }
684
853
  }
685
854
  _setShowHideButtonsVisibility() {
@@ -688,9 +857,14 @@ var IssuesUI = class {
688
857
  if (!showAllButton || !hideAllButton) {
689
858
  return;
690
859
  }
860
+ const { allHidden, allVisible } = this._getIssueVisibilityState();
861
+ hideAllButton.style.display = allHidden ? "none" : "";
862
+ showAllButton.style.display = allVisible ? "none" : "";
863
+ }
864
+ _getIssueVisibilityState() {
691
865
  let allHidden = true;
692
866
  let allVisible = true;
693
- for (let issue of this._issues) {
867
+ for (const issue of this._issues) {
694
868
  if (issue.isHidden) {
695
869
  allVisible = false;
696
870
  } else {
@@ -700,8 +874,11 @@ var IssuesUI = class {
700
874
  break;
701
875
  }
702
876
  }
703
- hideAllButton.style.display = allHidden ? "none" : "block";
704
- showAllButton.style.display = allVisible ? "none" : "block";
877
+ return { allHidden, allVisible };
878
+ }
879
+ _syncMenuState() {
880
+ this._setIssuesCount(this._issues.size);
881
+ this._setShowHideButtonsVisibility();
705
882
  }
706
883
  addIssue(issue) {
707
884
  if (this._issues.has(issue)) {
@@ -717,32 +894,134 @@ var IssuesUI = class {
717
894
  if (this._isMuted) {
718
895
  issue.toggle(false, true);
719
896
  }
720
- const issueUIWraper = IssueUI.getElement(issue);
721
- issueUIWraper && this._issuesContainer.appendChild(issueUIWraper);
897
+ IssueUI.setAppended(issue);
722
898
  IssueUI.setOnToggle(issue, () => {
723
899
  this._setShowHideButtonsVisibility();
724
900
  });
725
- this._setIssuesCount(this._issues.size);
726
- this._setShowHideButtonsVisibility();
901
+ this._syncMenuState();
902
+ }
903
+ getIssueContainer(type, groupName, helpLink) {
904
+ if (!this._issuesContainer) {
905
+ throw new Error("IssuesUI is not initialized");
906
+ }
907
+ if (!groupName) {
908
+ return this._issuesContainer;
909
+ }
910
+ let groupContainer = this._issueGroupContainers[groupName];
911
+ if (!groupContainer) {
912
+ groupContainer = this._createIssueGroup(groupName, type, helpLink);
913
+ }
914
+ return groupContainer;
915
+ }
916
+ syncGroupIssueCounts() {
917
+ this._updateGroupIssueCounts();
918
+ }
919
+ _createIssueGroup(groupName, type, helpLink) {
920
+ if (!this._issuesContainer) {
921
+ throw new Error("IssuesUI is not initialized");
922
+ }
923
+ let groupContainer;
924
+ new DOMBuilder(this._issuesContainer).openTag("div", { class: "abledom-issue-group" }).openTag("div", {
925
+ class: `abledom-issue-group-title abledom-issue${getIssueTypeClass(type)}`
926
+ }).openTag(
927
+ "button",
928
+ {
929
+ class: "button toggle collapsed",
930
+ title: "Toggle group"
931
+ },
932
+ (toggleButton) => {
933
+ this._bindGroupToggleButton(toggleButton, () => groupContainer);
934
+ }
935
+ ).element(chevronright_default).element(chevrondown_default).openTag("span", { class: "abledom-issue-group-count" }, (countEl) => {
936
+ this._issueGroupCountElements[groupName] = countEl;
937
+ }).closeTag().closeTag().text(groupName).openTag(
938
+ "a",
939
+ {
940
+ class: "button help",
941
+ href: helpLink || "/",
942
+ title: "Open help",
943
+ target: "_blank"
944
+ },
945
+ (help) => {
946
+ this._hideHelpLinkIfMissing(help, helpLink);
947
+ }
948
+ ).element(help_default).closeTag().openTag(
949
+ "button",
950
+ {
951
+ class: "button close",
952
+ title: "Hide"
953
+ },
954
+ (closeButton) => {
955
+ this._bindGroupCloseButton(closeButton, () => groupContainer);
956
+ }
957
+ ).element(close_default).closeTag().closeTag().openTag("div", { class: "abledom-issue-group-issues" }, (element) => {
958
+ this._issueGroupContainers[groupName] = groupContainer = element;
959
+ groupContainer.style.display = "none";
960
+ }).closeTag().closeTag();
961
+ if (!groupContainer) {
962
+ throw new Error("Issue group container was not created");
963
+ }
964
+ return groupContainer;
965
+ }
966
+ _bindGroupToggleButton(button, getGroupContainer) {
967
+ let isCollapsed = true;
968
+ button.onclick = () => {
969
+ isCollapsed = !isCollapsed;
970
+ button.classList.toggle("collapsed", isCollapsed);
971
+ const groupContainer = getGroupContainer();
972
+ if (groupContainer) {
973
+ groupContainer.style.display = isCollapsed ? "none" : "";
974
+ }
975
+ };
976
+ }
977
+ _bindGroupCloseButton(button, getGroupContainer) {
978
+ button.onclick = () => {
979
+ const groupContainer = getGroupContainer();
980
+ if (groupContainer) {
981
+ Array.prototype.forEach.call(
982
+ groupContainer.children,
983
+ (el) => {
984
+ var _a;
985
+ (_a = el.__ableDOMIssueUI) == null ? void 0 : _a.toggle(false);
986
+ }
987
+ );
988
+ this._setShowHideButtonsVisibility();
989
+ }
990
+ this.highlight(null);
991
+ };
992
+ }
993
+ _hideHelpLinkIfMissing(help, helpLink) {
994
+ if (!helpLink) {
995
+ help.style.display = "none";
996
+ }
997
+ }
998
+ _updateGroupIssueCounts() {
999
+ for (const [groupName, container] of Object.entries(
1000
+ this._issueGroupContainers
1001
+ )) {
1002
+ const countElement = this._issueGroupCountElements[groupName];
1003
+ if (container && countElement) {
1004
+ const count = container.children.length;
1005
+ countElement.textContent = `${count}`;
1006
+ }
1007
+ }
727
1008
  }
728
1009
  removeIssue(issue) {
729
1010
  if (!this._issues.has(issue)) {
730
1011
  return;
731
1012
  }
732
1013
  this._issues.delete(issue);
733
- this._setIssuesCount(this._issues.size);
734
- this._setShowHideButtonsVisibility();
1014
+ this._syncMenuState();
1015
+ this._updateGroupIssueCounts();
735
1016
  this.highlight(null);
736
1017
  }
737
- hideAll() {
738
- this._issues.forEach((issue) => {
739
- issue.toggle(false);
740
- });
741
- this._setShowHideButtonsVisibility();
742
- }
743
- showAll() {
1018
+ toggleAll(show) {
1019
+ if (show === void 0) {
1020
+ const { allVisible } = this._getIssueVisibilityState();
1021
+ show = !allVisible;
1022
+ }
744
1023
  this._issues.forEach((issue) => {
745
- issue.toggle(true);
1024
+ issue.toggle(show);
746
1025
  });
747
1026
  this._setShowHideButtonsVisibility();
748
1027
  }
@@ -836,20 +1115,12 @@ var ElementHighlighter = class {
836
1115
  delete this._cancelAutoHideTimer;
837
1116
  };
838
1117
  }
1118
+ this._unobserve();
839
1119
  this._intersectionObserver = new IntersectionObserver(([entry]) => {
840
- if (entry) {
841
- const rect = entry.boundingClientRect;
842
- const body = win.document.body;
843
- const style = container.style;
844
- if (container.parentElement !== body) {
845
- body.appendChild(container);
846
- }
847
- style.width = `${rect.width}px`;
848
- style.height = `${rect.height}px`;
849
- style.top = `${rect.top}px`;
850
- style.left = `${rect.left}px`;
851
- container.style.display = "block";
1120
+ if (!entry) {
1121
+ return;
852
1122
  }
1123
+ this._renderHighlightRect(entry.boundingClientRect, win.document.body);
853
1124
  });
854
1125
  this._intersectionObserver.observe(element);
855
1126
  }
@@ -864,6 +1135,21 @@ var ElementHighlighter = class {
864
1135
  delete this._container;
865
1136
  delete this._window;
866
1137
  }
1138
+ _renderHighlightRect(rect, body) {
1139
+ const container = this._container;
1140
+ if (!container) {
1141
+ return;
1142
+ }
1143
+ if (container.parentElement !== body) {
1144
+ body.appendChild(container);
1145
+ }
1146
+ const style = container.style;
1147
+ style.width = `${rect.width}px`;
1148
+ style.height = `${rect.height}px`;
1149
+ style.top = `${rect.top}px`;
1150
+ style.left = `${rect.left}px`;
1151
+ style.display = "block";
1152
+ }
867
1153
  _hide() {
868
1154
  this._container && (this._container.style.display = "none");
869
1155
  }
@@ -1589,6 +1875,7 @@ var AtomicRule = class extends ValidationRule {
1589
1875
  __publicField(this, "type", 1 /* Error */);
1590
1876
  __publicField(this, "name", "atomic");
1591
1877
  __publicField(this, "anchored", true);
1878
+ __publicField(this, "groupName", "Atomic violation");
1592
1879
  }
1593
1880
  accept(element) {
1594
1881
  return matchesSelector(element, focusableElementSelector);
@@ -1653,6 +1940,7 @@ var FocusableElementLabelRule = class extends ValidationRule {
1653
1940
  __publicField(this, "type", 1 /* Error */);
1654
1941
  __publicField(this, "name", "FocusableElementLabelRule");
1655
1942
  __publicField(this, "anchored", true);
1943
+ __publicField(this, "groupName", "Missing text label");
1656
1944
  }
1657
1945
  _isAriaHidden(element) {
1658
1946
  return element.ownerDocument.evaluate(
@@ -1828,6 +2116,7 @@ var ContrastRule = class extends ValidationRule {
1828
2116
  __publicField(this, "type", 1 /* Error */);
1829
2117
  __publicField(this, "name", "ContrastRule");
1830
2118
  __publicField(this, "anchored", true);
2119
+ __publicField(this, "groupName", "Insufficient color contrast");
1831
2120
  }
1832
2121
  accept(element) {
1833
2122
  if (!isElementVisible(element)) {
@@ -1917,6 +2206,7 @@ var ExistingIdRule = class extends ValidationRule {
1917
2206
  __publicField(this, "type", 1 /* Error */);
1918
2207
  __publicField(this, "name", "existing-id");
1919
2208
  __publicField(this, "anchored", true);
2209
+ __publicField(this, "groupName", "Referenced element not found");
1920
2210
  }
1921
2211
  accept(element) {
1922
2212
  return element.hasAttribute("aria-labelledby") || element.hasAttribute("aria-describedby") || element.tagName === "LABEL" && !!element.htmlFor;
@@ -1956,6 +2246,7 @@ var FocusLostRule = class extends ValidationRule {
1956
2246
  __publicField(this, "type", 1 /* Error */);
1957
2247
  __publicField(this, "name", "focus-lost");
1958
2248
  __publicField(this, "anchored", false);
2249
+ __publicField(this, "groupName", "Focus lost");
1959
2250
  __publicField(this, "_focusLostTimeout", 2e3);
1960
2251
  // For now reporting lost focus after 2 seconds of it being lost.
1961
2252
  __publicField(this, "_clearScheduledFocusLost");
@@ -2065,6 +2356,7 @@ var BadFocusRule = class extends ValidationRule {
2065
2356
  __publicField(this, "type", 1 /* Error */);
2066
2357
  __publicField(this, "name", "bad-focus");
2067
2358
  __publicField(this, "anchored", false);
2359
+ __publicField(this, "groupName", "Bad focus");
2068
2360
  __publicField(this, "_lastFocusStack");
2069
2361
  __publicField(this, "_lastBlurStack");
2070
2362
  __publicField(this, "_clearCheckTimer");
@@ -2116,6 +2408,7 @@ var FindElementRule = class extends ValidationRule {
2116
2408
  __publicField(this, "type", 2 /* Warning */);
2117
2409
  __publicField(this, "name", "find-element");
2118
2410
  __publicField(this, "anchored", true);
2411
+ __publicField(this, "groupName", "Element found");
2119
2412
  __publicField(this, "_conditions", {});
2120
2413
  }
2121
2414
  addCondition(name, condition) {
@@ -2164,6 +2457,7 @@ var RequiredParentRule = class extends ValidationRule {
2164
2457
  __publicField(this, "type", 1 /* Error */);
2165
2458
  __publicField(this, "name", "aria-required-parent");
2166
2459
  __publicField(this, "anchored", true);
2460
+ __publicField(this, "groupName", "Missing required parent");
2167
2461
  __publicField(this, "parentRequirements", /* @__PURE__ */ new Map([
2168
2462
  [
2169
2463
  "LI",
@@ -2480,6 +2774,7 @@ var NestedInteractiveElementRule = class extends ValidationRule {
2480
2774
  __publicField(this, "type", 1 /* Error */);
2481
2775
  __publicField(this, "name", "NestedInteractiveElementRule");
2482
2776
  __publicField(this, "anchored", true);
2777
+ __publicField(this, "groupName", "Nested interactive element");
2483
2778
  }
2484
2779
  _isAriaHidden(element) {
2485
2780
  return element.ownerDocument.evaluate(
@@ -2577,6 +2872,7 @@ var TabIndexRule = class extends ValidationRule {
2577
2872
  __publicField(this, "type", 2 /* Warning */);
2578
2873
  __publicField(this, "name", "tabindex");
2579
2874
  __publicField(this, "anchored", true);
2875
+ __publicField(this, "groupName", "Positive tabindex");
2580
2876
  }
2581
2877
  accept(element) {
2582
2878
  return element.hasAttribute("tabindex");