abledom 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/index.js +614 -32
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.cts +62 -4
- package/dist/index.d.ts +62 -4
- package/dist/index.js +617 -32
- package/dist/index.js.map +1 -1
- package/dist/ts3.9/index.d.ts +56 -4
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -58,7 +58,10 @@ var ValidationRule = class {
|
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
// inline-file:/Users/marata/Documents/Work/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
|
|
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";
|
|
62
|
+
|
|
63
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/highlighter.css
|
|
64
|
+
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";
|
|
62
65
|
|
|
63
66
|
// src/ui/domBuilder.ts
|
|
64
67
|
var DOMBuilder = class {
|
|
@@ -364,8 +367,7 @@ var IssueUI = class {
|
|
|
364
367
|
if (element2) {
|
|
365
368
|
revealButton.onclick = () => {
|
|
366
369
|
var _a;
|
|
367
|
-
|
|
368
|
-
(_a = this._issuesUI) == null ? void 0 : _a.highlight(element2);
|
|
370
|
+
(_a = this._issuesUI) == null ? void 0 : _a.highlight(element2, true);
|
|
369
371
|
};
|
|
370
372
|
} else {
|
|
371
373
|
revealButton.style.display = "none";
|
|
@@ -442,7 +444,8 @@ var IssueUI = class {
|
|
|
442
444
|
}
|
|
443
445
|
};
|
|
444
446
|
var IssuesUI = class {
|
|
445
|
-
constructor(win, props) {
|
|
447
|
+
constructor(win, getHighlighter, props) {
|
|
448
|
+
__publicField(this, "_win");
|
|
446
449
|
__publicField(this, "_container");
|
|
447
450
|
__publicField(this, "_issuesContainer");
|
|
448
451
|
__publicField(this, "_menuElement");
|
|
@@ -455,9 +458,11 @@ var IssuesUI = class {
|
|
|
455
458
|
__publicField(this, "_alignBottomRightButton");
|
|
456
459
|
__publicField(this, "_isMuted", false);
|
|
457
460
|
__publicField(this, "_issues", /* @__PURE__ */ new Set());
|
|
458
|
-
__publicField(this, "
|
|
461
|
+
__publicField(this, "_getHighlighter");
|
|
459
462
|
__publicField(this, "bugReport");
|
|
460
463
|
__publicField(this, "headless");
|
|
464
|
+
this._win = win;
|
|
465
|
+
this._getHighlighter = getHighlighter;
|
|
461
466
|
this.bugReport = props.bugReport;
|
|
462
467
|
this.headless = !!props.headless;
|
|
463
468
|
if (this.headless) {
|
|
@@ -578,7 +583,6 @@ var IssuesUI = class {
|
|
|
578
583
|
}
|
|
579
584
|
).element(alignbottomright_default).closeTag().closeTag();
|
|
580
585
|
doc.body.appendChild(container);
|
|
581
|
-
this._highlighter = new ElementHighlighter(win);
|
|
582
586
|
}
|
|
583
587
|
setUIAlignment(alignment) {
|
|
584
588
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
@@ -700,15 +704,15 @@ var IssuesUI = class {
|
|
|
700
704
|
});
|
|
701
705
|
this._setShowHideButtonsVisibility();
|
|
702
706
|
}
|
|
703
|
-
highlight(element) {
|
|
704
|
-
var _a;
|
|
705
|
-
(_a = this.
|
|
707
|
+
highlight(element, scrollIntoView, autoHideTime) {
|
|
708
|
+
var _a, _b;
|
|
709
|
+
(_b = (_a = this._getHighlighter) == null ? void 0 : _a.call(this)) == null ? void 0 : _b.highlight(element, scrollIntoView, autoHideTime);
|
|
706
710
|
}
|
|
707
711
|
dispose() {
|
|
708
|
-
var _a
|
|
709
|
-
(_a = this.
|
|
710
|
-
|
|
711
|
-
delete this.
|
|
712
|
+
var _a;
|
|
713
|
+
(_a = this._container) == null ? void 0 : _a.remove();
|
|
714
|
+
delete this._win;
|
|
715
|
+
delete this._getHighlighter;
|
|
712
716
|
delete this._container;
|
|
713
717
|
delete this._issuesContainer;
|
|
714
718
|
delete this._menuElement;
|
|
@@ -728,6 +732,7 @@ var ElementHighlighter = class {
|
|
|
728
732
|
__publicField(this, "_element");
|
|
729
733
|
__publicField(this, "_cancelScrollTimer");
|
|
730
734
|
__publicField(this, "_intersectionObserver");
|
|
735
|
+
__publicField(this, "_cancelAutoHideTimer");
|
|
731
736
|
__publicField(this, "_onScroll", () => {
|
|
732
737
|
var _a;
|
|
733
738
|
(_a = this._cancelScrollTimer) == null ? void 0 : _a.call(this);
|
|
@@ -748,10 +753,19 @@ var ElementHighlighter = class {
|
|
|
748
753
|
const container = this._container = win.document.createElement("div");
|
|
749
754
|
container.__abledomui = true;
|
|
750
755
|
container.className = "abledom-highlight";
|
|
756
|
+
const doc = win.document;
|
|
757
|
+
const style = doc.createElement("style");
|
|
758
|
+
style.type = "text/css";
|
|
759
|
+
style.appendChild(doc.createTextNode(highlighter_default));
|
|
760
|
+
container.appendChild(style);
|
|
751
761
|
new DOMBuilder(container).openTag("div", { class: "abledom-highlight-border1" }).closeTag().openTag("div", { class: "abledom-highlight-border2" }).closeTag();
|
|
752
762
|
win.addEventListener("scroll", this._onScroll, true);
|
|
753
763
|
}
|
|
754
|
-
highlight(element) {
|
|
764
|
+
highlight(element, scrollIntoView, autoHideTime) {
|
|
765
|
+
var _a;
|
|
766
|
+
if (this._cancelAutoHideTimer && element !== this._element) {
|
|
767
|
+
this._cancelAutoHideTimer();
|
|
768
|
+
}
|
|
755
769
|
if (!element) {
|
|
756
770
|
delete this._element;
|
|
757
771
|
this._unobserve();
|
|
@@ -764,6 +778,22 @@ var ElementHighlighter = class {
|
|
|
764
778
|
return;
|
|
765
779
|
}
|
|
766
780
|
this._element = element;
|
|
781
|
+
if (scrollIntoView) {
|
|
782
|
+
element.scrollIntoView({ block: "center" });
|
|
783
|
+
}
|
|
784
|
+
if (autoHideTime) {
|
|
785
|
+
(_a = this._cancelAutoHideTimer) == null ? void 0 : _a.call(this);
|
|
786
|
+
const autoHideTimeout = win.setTimeout(() => {
|
|
787
|
+
if (this._cancelAutoHideTimer) {
|
|
788
|
+
this.highlight(null);
|
|
789
|
+
delete this._cancelAutoHideTimer;
|
|
790
|
+
}
|
|
791
|
+
}, autoHideTime);
|
|
792
|
+
this._cancelAutoHideTimer = () => {
|
|
793
|
+
win.clearTimeout(autoHideTimeout);
|
|
794
|
+
delete this._cancelAutoHideTimer;
|
|
795
|
+
};
|
|
796
|
+
}
|
|
767
797
|
this._intersectionObserver = new IntersectionObserver(([entry]) => {
|
|
768
798
|
if (entry) {
|
|
769
799
|
const rect = entry.boundingClientRect;
|
|
@@ -782,11 +812,12 @@ var ElementHighlighter = class {
|
|
|
782
812
|
this._intersectionObserver.observe(element);
|
|
783
813
|
}
|
|
784
814
|
dispose() {
|
|
785
|
-
var _a, _b, _c;
|
|
815
|
+
var _a, _b, _c, _d;
|
|
786
816
|
this._unobserve();
|
|
787
817
|
(_a = this._cancelScrollTimer) == null ? void 0 : _a.call(this);
|
|
788
|
-
(_b = this.
|
|
789
|
-
(_c = this.
|
|
818
|
+
(_b = this._cancelAutoHideTimer) == null ? void 0 : _b.call(this);
|
|
819
|
+
(_c = this._window) == null ? void 0 : _c.removeEventListener("scroll", this._onScroll, true);
|
|
820
|
+
(_d = this._container) == null ? void 0 : _d.remove();
|
|
790
821
|
delete this._element;
|
|
791
822
|
delete this._container;
|
|
792
823
|
delete this._window;
|
|
@@ -829,10 +860,17 @@ var AccessibilityAffectingElements = {
|
|
|
829
860
|
aside: true,
|
|
830
861
|
body: true,
|
|
831
862
|
button: true,
|
|
863
|
+
caption: true,
|
|
864
|
+
col: true,
|
|
865
|
+
colgroup: true,
|
|
832
866
|
datalist: true,
|
|
867
|
+
dd: true,
|
|
833
868
|
details: true,
|
|
834
869
|
dialog: true,
|
|
835
870
|
dl: true,
|
|
871
|
+
dt: true,
|
|
872
|
+
figcaption: true,
|
|
873
|
+
figure: true,
|
|
836
874
|
form: true,
|
|
837
875
|
h1: true,
|
|
838
876
|
h2: true,
|
|
@@ -844,6 +882,7 @@ var AccessibilityAffectingElements = {
|
|
|
844
882
|
iframe: true,
|
|
845
883
|
img: true,
|
|
846
884
|
input: true,
|
|
885
|
+
legend: true,
|
|
847
886
|
li: true,
|
|
848
887
|
link: true,
|
|
849
888
|
main: true,
|
|
@@ -853,15 +892,22 @@ var AccessibilityAffectingElements = {
|
|
|
853
892
|
nav: true,
|
|
854
893
|
object: true,
|
|
855
894
|
ol: true,
|
|
895
|
+
optgroup: true,
|
|
856
896
|
option: true,
|
|
857
897
|
progress: true,
|
|
858
898
|
section: true,
|
|
859
899
|
select: true,
|
|
900
|
+
source: true,
|
|
901
|
+
summary: true,
|
|
902
|
+
table: true,
|
|
860
903
|
tbody: true,
|
|
904
|
+
td: true,
|
|
861
905
|
textarea: true,
|
|
862
906
|
tfoot: true,
|
|
863
907
|
th: true,
|
|
864
908
|
thead: true,
|
|
909
|
+
tr: true,
|
|
910
|
+
track: true,
|
|
865
911
|
ul: true
|
|
866
912
|
};
|
|
867
913
|
var AccessibilityAttributes = {
|
|
@@ -994,6 +1040,7 @@ function getStackTrace() {
|
|
|
994
1040
|
var AbleDOM = class {
|
|
995
1041
|
constructor(win, props = {}) {
|
|
996
1042
|
__publicField(this, "_win");
|
|
1043
|
+
__publicField(this, "_isDisposed", false);
|
|
997
1044
|
__publicField(this, "_props");
|
|
998
1045
|
__publicField(this, "_observer");
|
|
999
1046
|
__publicField(this, "_clearValidationTimeout");
|
|
@@ -1006,8 +1053,17 @@ var AbleDOM = class {
|
|
|
1006
1053
|
__publicField(this, "_startFunc");
|
|
1007
1054
|
__publicField(this, "_isStarted", false);
|
|
1008
1055
|
__publicField(this, "_issuesUI");
|
|
1056
|
+
__publicField(this, "_elementHighlighter");
|
|
1009
1057
|
__publicField(this, "_idlePromise");
|
|
1010
1058
|
__publicField(this, "_idleResolve");
|
|
1059
|
+
__publicField(this, "_currentAnchoredIssues", /* @__PURE__ */ new Map());
|
|
1060
|
+
__publicField(this, "_currentNotAnchoredIssues", []);
|
|
1061
|
+
__publicField(this, "_getHighlighter", () => {
|
|
1062
|
+
if (!this._elementHighlighter && !this._isDisposed) {
|
|
1063
|
+
this._elementHighlighter = new ElementHighlighter(this._win);
|
|
1064
|
+
}
|
|
1065
|
+
return this._elementHighlighter;
|
|
1066
|
+
});
|
|
1011
1067
|
__publicField(this, "_onFocusIn", (event) => {
|
|
1012
1068
|
var _a;
|
|
1013
1069
|
const target = event.target;
|
|
@@ -1175,9 +1231,9 @@ var AbleDOM = class {
|
|
|
1175
1231
|
}
|
|
1176
1232
|
}
|
|
1177
1233
|
_addIssue(rule, issue) {
|
|
1178
|
-
var _a, _b
|
|
1234
|
+
var _a, _b;
|
|
1179
1235
|
if (!this._issuesUI) {
|
|
1180
|
-
this._issuesUI = new IssuesUI(this._win, {
|
|
1236
|
+
this._issuesUI = new IssuesUI(this._win, this._getHighlighter, {
|
|
1181
1237
|
bugReport: (_a = this._props) == null ? void 0 : _a.bugReport,
|
|
1182
1238
|
headless: (_b = this._props) == null ? void 0 : _b.headless
|
|
1183
1239
|
});
|
|
@@ -1203,26 +1259,21 @@ var AbleDOM = class {
|
|
|
1203
1259
|
issueUI = new IssueUI(this._win, this, rule, this._issuesUI);
|
|
1204
1260
|
issues.set(rule, issueUI);
|
|
1205
1261
|
justUpdate = false;
|
|
1206
|
-
|
|
1262
|
+
this._onIssueAdded(element, rule, issue);
|
|
1207
1263
|
}
|
|
1208
1264
|
this._elementsWithIssues.add(element);
|
|
1209
1265
|
} else {
|
|
1210
1266
|
issueUI = new IssueUI(this._win, this, rule, this._issuesUI);
|
|
1211
1267
|
justUpdate = false;
|
|
1212
|
-
|
|
1268
|
+
this._onIssueAdded(null, rule, issue);
|
|
1213
1269
|
}
|
|
1214
1270
|
issueUI.update(issue);
|
|
1215
|
-
if (justUpdate) {
|
|
1216
|
-
|
|
1217
|
-
_j,
|
|
1218
|
-
rule.anchored && element ? element : null,
|
|
1219
|
-
rule,
|
|
1220
|
-
issue
|
|
1221
|
-
);
|
|
1271
|
+
if (justUpdate && rule.anchored && element) {
|
|
1272
|
+
this._onIssueUpdated(element, rule, issue);
|
|
1222
1273
|
}
|
|
1223
1274
|
}
|
|
1224
1275
|
_removeIssue(element, rule) {
|
|
1225
|
-
var _a
|
|
1276
|
+
var _a;
|
|
1226
1277
|
if (!rule.anchored) {
|
|
1227
1278
|
return;
|
|
1228
1279
|
}
|
|
@@ -1234,7 +1285,7 @@ var AbleDOM = class {
|
|
|
1234
1285
|
if (issue) {
|
|
1235
1286
|
issue.dispose();
|
|
1236
1287
|
issues.delete(rule);
|
|
1237
|
-
|
|
1288
|
+
this._onIssueRemoved(element, rule);
|
|
1238
1289
|
}
|
|
1239
1290
|
if (issues.size === 0) {
|
|
1240
1291
|
this._elementsWithIssues.delete(element);
|
|
@@ -1320,6 +1371,42 @@ var AbleDOM = class {
|
|
|
1320
1371
|
this._dependantIdsByElement.set(element, dependsOnIds);
|
|
1321
1372
|
}
|
|
1322
1373
|
}
|
|
1374
|
+
_updateCurrentAnchoredIssues(element, rule, issue) {
|
|
1375
|
+
let issuesByElement = this._currentAnchoredIssues.get(element);
|
|
1376
|
+
if (!issuesByElement && issue) {
|
|
1377
|
+
issuesByElement = /* @__PURE__ */ new Map();
|
|
1378
|
+
this._currentAnchoredIssues.set(element, issuesByElement);
|
|
1379
|
+
}
|
|
1380
|
+
if (issuesByElement) {
|
|
1381
|
+
if (issue) {
|
|
1382
|
+
issuesByElement.set(rule, issue);
|
|
1383
|
+
} else {
|
|
1384
|
+
issuesByElement.delete(rule);
|
|
1385
|
+
if (issuesByElement.size === 0) {
|
|
1386
|
+
this._currentAnchoredIssues.delete(element);
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
_onIssueAdded(element, rule, issue) {
|
|
1392
|
+
var _a, _b, _c;
|
|
1393
|
+
if (element) {
|
|
1394
|
+
this._updateCurrentAnchoredIssues(element, rule, issue);
|
|
1395
|
+
} else {
|
|
1396
|
+
this._currentNotAnchoredIssues.push(issue);
|
|
1397
|
+
}
|
|
1398
|
+
(_c = (_b = (_a = this._props) == null ? void 0 : _a.callbacks) == null ? void 0 : _b.onIssueAdded) == null ? void 0 : _c.call(_b, element, rule, issue);
|
|
1399
|
+
}
|
|
1400
|
+
_onIssueUpdated(element, rule, issue) {
|
|
1401
|
+
var _a, _b, _c;
|
|
1402
|
+
this._updateCurrentAnchoredIssues(element, rule, issue);
|
|
1403
|
+
(_c = (_b = (_a = this._props) == null ? void 0 : _a.callbacks) == null ? void 0 : _b.onIssueUpdated) == null ? void 0 : _c.call(_b, element, rule, issue);
|
|
1404
|
+
}
|
|
1405
|
+
_onIssueRemoved(element, rule) {
|
|
1406
|
+
var _a, _b, _c;
|
|
1407
|
+
this._updateCurrentAnchoredIssues(element, rule, null);
|
|
1408
|
+
(_c = (_b = (_a = this._props) == null ? void 0 : _a.callbacks) == null ? void 0 : _b.onIssueRemoved) == null ? void 0 : _c.call(_b, element, rule);
|
|
1409
|
+
}
|
|
1323
1410
|
_remove(elements) {
|
|
1324
1411
|
elements.forEach((element) => {
|
|
1325
1412
|
var _a, _b;
|
|
@@ -1327,21 +1414,42 @@ var AbleDOM = class {
|
|
|
1327
1414
|
rules.forEach((rule) => this._removeIssue(element, rule));
|
|
1328
1415
|
});
|
|
1329
1416
|
}
|
|
1417
|
+
_getCurrentIssues() {
|
|
1418
|
+
const issues = this._currentNotAnchoredIssues.slice(0);
|
|
1419
|
+
this._currentAnchoredIssues.forEach((issueByRule) => {
|
|
1420
|
+
issueByRule.forEach((issue) => {
|
|
1421
|
+
issues.push(issue);
|
|
1422
|
+
});
|
|
1423
|
+
});
|
|
1424
|
+
return issues;
|
|
1425
|
+
}
|
|
1330
1426
|
idle() {
|
|
1331
1427
|
if (!this._clearValidationTimeout) {
|
|
1332
|
-
return Promise.resolve();
|
|
1428
|
+
return Promise.resolve(this._getCurrentIssues());
|
|
1333
1429
|
}
|
|
1334
1430
|
if (!this._idlePromise) {
|
|
1335
1431
|
this._idlePromise = new Promise((resolve) => {
|
|
1336
1432
|
this._idleResolve = () => {
|
|
1337
1433
|
delete this._idlePromise;
|
|
1338
1434
|
delete this._idleResolve;
|
|
1339
|
-
resolve();
|
|
1435
|
+
resolve(this._getCurrentIssues());
|
|
1340
1436
|
};
|
|
1341
1437
|
});
|
|
1342
1438
|
}
|
|
1343
1439
|
return this._idlePromise;
|
|
1344
1440
|
}
|
|
1441
|
+
clearCurrentIssues(anchored = true, notAnchored = true) {
|
|
1442
|
+
if (anchored) {
|
|
1443
|
+
this._currentAnchoredIssues.clear();
|
|
1444
|
+
}
|
|
1445
|
+
if (notAnchored) {
|
|
1446
|
+
this._currentNotAnchoredIssues = [];
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
highlightElement(element, scrollIntoView, autoHideTime) {
|
|
1450
|
+
var _a;
|
|
1451
|
+
(_a = this._getHighlighter()) == null ? void 0 : _a.highlight(element, scrollIntoView, autoHideTime);
|
|
1452
|
+
}
|
|
1345
1453
|
addRule(rule) {
|
|
1346
1454
|
this._rules.push(rule);
|
|
1347
1455
|
}
|
|
@@ -1368,6 +1476,7 @@ var AbleDOM = class {
|
|
|
1368
1476
|
}
|
|
1369
1477
|
dispose() {
|
|
1370
1478
|
var _a, _b, _c, _d;
|
|
1479
|
+
this._isDisposed = true;
|
|
1371
1480
|
const doc = this._win.document;
|
|
1372
1481
|
doc.addEventListener("focusin", this._onFocusIn, true);
|
|
1373
1482
|
doc.addEventListener("focusout", this._onFocusOut, true);
|
|
@@ -1376,6 +1485,7 @@ var AbleDOM = class {
|
|
|
1376
1485
|
this._dependantIdsByElement.clear();
|
|
1377
1486
|
this._elementsDependingOnId.clear();
|
|
1378
1487
|
this._idByElement.clear();
|
|
1488
|
+
this.clearCurrentIssues();
|
|
1379
1489
|
(_a = this._issuesUI) == null ? void 0 : _a.dispose();
|
|
1380
1490
|
delete this._issuesUI;
|
|
1381
1491
|
(_b = this._clearValidationTimeout) == null ? void 0 : _b.call(this);
|
|
@@ -1967,6 +2077,475 @@ var CustomNotifyRule = class extends ValidationRule {
|
|
|
1967
2077
|
});
|
|
1968
2078
|
}
|
|
1969
2079
|
};
|
|
2080
|
+
|
|
2081
|
+
// src/rules/requiredparent.ts
|
|
2082
|
+
var RequiredParentRule = class extends ValidationRule {
|
|
2083
|
+
constructor() {
|
|
2084
|
+
super(...arguments);
|
|
2085
|
+
__publicField(this, "type", 1 /* Error */);
|
|
2086
|
+
__publicField(this, "name", "aria-required-parent");
|
|
2087
|
+
__publicField(this, "anchored", true);
|
|
2088
|
+
__publicField(this, "parentRequirements", /* @__PURE__ */ new Map([
|
|
2089
|
+
[
|
|
2090
|
+
"LI",
|
|
2091
|
+
{
|
|
2092
|
+
allowedParents: ["UL", "OL"],
|
|
2093
|
+
allowedParentRoles: ["list"]
|
|
2094
|
+
}
|
|
2095
|
+
],
|
|
2096
|
+
[
|
|
2097
|
+
"DT",
|
|
2098
|
+
{
|
|
2099
|
+
allowedParents: ["DL"],
|
|
2100
|
+
allowIntermediateWrappers: true,
|
|
2101
|
+
allowedWrappers: ["DIV"]
|
|
2102
|
+
}
|
|
2103
|
+
],
|
|
2104
|
+
[
|
|
2105
|
+
"DD",
|
|
2106
|
+
{
|
|
2107
|
+
allowedParents: ["DL"],
|
|
2108
|
+
allowIntermediateWrappers: true,
|
|
2109
|
+
allowedWrappers: ["DIV"]
|
|
2110
|
+
}
|
|
2111
|
+
],
|
|
2112
|
+
[
|
|
2113
|
+
"TR",
|
|
2114
|
+
{
|
|
2115
|
+
allowedParents: ["TABLE", "THEAD", "TBODY", "TFOOT"],
|
|
2116
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2117
|
+
}
|
|
2118
|
+
],
|
|
2119
|
+
[
|
|
2120
|
+
"TH",
|
|
2121
|
+
{
|
|
2122
|
+
allowedParents: ["TR"],
|
|
2123
|
+
allowedParentRoles: ["row"]
|
|
2124
|
+
}
|
|
2125
|
+
],
|
|
2126
|
+
[
|
|
2127
|
+
"TD",
|
|
2128
|
+
{
|
|
2129
|
+
allowedParents: ["TR"],
|
|
2130
|
+
allowedParentRoles: ["row"]
|
|
2131
|
+
}
|
|
2132
|
+
],
|
|
2133
|
+
[
|
|
2134
|
+
"THEAD",
|
|
2135
|
+
{
|
|
2136
|
+
allowedParents: ["TABLE"],
|
|
2137
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2138
|
+
}
|
|
2139
|
+
],
|
|
2140
|
+
[
|
|
2141
|
+
"TBODY",
|
|
2142
|
+
{
|
|
2143
|
+
allowedParents: ["TABLE"],
|
|
2144
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2145
|
+
}
|
|
2146
|
+
],
|
|
2147
|
+
[
|
|
2148
|
+
"TFOOT",
|
|
2149
|
+
{
|
|
2150
|
+
allowedParents: ["TABLE"],
|
|
2151
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2152
|
+
}
|
|
2153
|
+
],
|
|
2154
|
+
[
|
|
2155
|
+
"CAPTION",
|
|
2156
|
+
{
|
|
2157
|
+
allowedParents: ["TABLE"]
|
|
2158
|
+
}
|
|
2159
|
+
],
|
|
2160
|
+
[
|
|
2161
|
+
"COLGROUP",
|
|
2162
|
+
{
|
|
2163
|
+
allowedParents: ["TABLE"]
|
|
2164
|
+
}
|
|
2165
|
+
],
|
|
2166
|
+
[
|
|
2167
|
+
"COL",
|
|
2168
|
+
{
|
|
2169
|
+
allowedParents: ["COLGROUP"]
|
|
2170
|
+
}
|
|
2171
|
+
],
|
|
2172
|
+
[
|
|
2173
|
+
"FIGCAPTION",
|
|
2174
|
+
{
|
|
2175
|
+
allowedParents: ["FIGURE"]
|
|
2176
|
+
}
|
|
2177
|
+
],
|
|
2178
|
+
[
|
|
2179
|
+
"OPTION",
|
|
2180
|
+
{
|
|
2181
|
+
allowedParents: ["SELECT", "OPTGROUP", "DATALIST"]
|
|
2182
|
+
}
|
|
2183
|
+
],
|
|
2184
|
+
[
|
|
2185
|
+
"OPTGROUP",
|
|
2186
|
+
{
|
|
2187
|
+
allowedParents: ["SELECT"]
|
|
2188
|
+
}
|
|
2189
|
+
],
|
|
2190
|
+
[
|
|
2191
|
+
"LEGEND",
|
|
2192
|
+
{
|
|
2193
|
+
allowedParents: ["FIELDSET"]
|
|
2194
|
+
}
|
|
2195
|
+
],
|
|
2196
|
+
[
|
|
2197
|
+
"SUMMARY",
|
|
2198
|
+
{
|
|
2199
|
+
allowedParents: ["DETAILS"]
|
|
2200
|
+
}
|
|
2201
|
+
],
|
|
2202
|
+
[
|
|
2203
|
+
"SOURCE",
|
|
2204
|
+
{
|
|
2205
|
+
allowedParents: ["AUDIO", "VIDEO", "PICTURE"]
|
|
2206
|
+
}
|
|
2207
|
+
],
|
|
2208
|
+
[
|
|
2209
|
+
"TRACK",
|
|
2210
|
+
{
|
|
2211
|
+
allowedParents: ["AUDIO", "VIDEO"]
|
|
2212
|
+
}
|
|
2213
|
+
],
|
|
2214
|
+
[
|
|
2215
|
+
"role=menuitem",
|
|
2216
|
+
{
|
|
2217
|
+
allowedParentRoles: ["menu", "menubar", "group"]
|
|
2218
|
+
}
|
|
2219
|
+
],
|
|
2220
|
+
[
|
|
2221
|
+
"role=menuitemcheckbox",
|
|
2222
|
+
{
|
|
2223
|
+
allowedParentRoles: ["menu", "menubar", "group"]
|
|
2224
|
+
}
|
|
2225
|
+
],
|
|
2226
|
+
[
|
|
2227
|
+
"role=menuitemradio",
|
|
2228
|
+
{
|
|
2229
|
+
allowedParentRoles: ["menu", "menubar", "group"]
|
|
2230
|
+
}
|
|
2231
|
+
],
|
|
2232
|
+
[
|
|
2233
|
+
"role=listitem",
|
|
2234
|
+
{
|
|
2235
|
+
allowedParentRoles: ["list", "group"]
|
|
2236
|
+
}
|
|
2237
|
+
],
|
|
2238
|
+
[
|
|
2239
|
+
"role=treeitem",
|
|
2240
|
+
{
|
|
2241
|
+
allowedParentRoles: ["tree", "group"]
|
|
2242
|
+
}
|
|
2243
|
+
],
|
|
2244
|
+
[
|
|
2245
|
+
"role=tab",
|
|
2246
|
+
{
|
|
2247
|
+
allowedParentRoles: ["tablist"]
|
|
2248
|
+
}
|
|
2249
|
+
],
|
|
2250
|
+
[
|
|
2251
|
+
"role=row",
|
|
2252
|
+
{
|
|
2253
|
+
allowedParentRoles: ["table", "grid", "treegrid", "rowgroup"]
|
|
2254
|
+
}
|
|
2255
|
+
],
|
|
2256
|
+
[
|
|
2257
|
+
"role=cell",
|
|
2258
|
+
{
|
|
2259
|
+
allowedParentRoles: ["row"]
|
|
2260
|
+
}
|
|
2261
|
+
],
|
|
2262
|
+
[
|
|
2263
|
+
"role=gridcell",
|
|
2264
|
+
{
|
|
2265
|
+
allowedParentRoles: ["row"]
|
|
2266
|
+
}
|
|
2267
|
+
],
|
|
2268
|
+
[
|
|
2269
|
+
"role=columnheader",
|
|
2270
|
+
{
|
|
2271
|
+
allowedParentRoles: ["row"]
|
|
2272
|
+
}
|
|
2273
|
+
],
|
|
2274
|
+
[
|
|
2275
|
+
"role=rowheader",
|
|
2276
|
+
{
|
|
2277
|
+
allowedParentRoles: ["row"]
|
|
2278
|
+
}
|
|
2279
|
+
],
|
|
2280
|
+
[
|
|
2281
|
+
"role=rowgroup",
|
|
2282
|
+
{
|
|
2283
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2284
|
+
}
|
|
2285
|
+
],
|
|
2286
|
+
[
|
|
2287
|
+
"role=option",
|
|
2288
|
+
{
|
|
2289
|
+
allowedParentRoles: ["listbox", "group"]
|
|
2290
|
+
}
|
|
2291
|
+
]
|
|
2292
|
+
]));
|
|
2293
|
+
}
|
|
2294
|
+
accept(element) {
|
|
2295
|
+
const tagName = element.tagName;
|
|
2296
|
+
const role = element.getAttribute("role");
|
|
2297
|
+
if (this.parentRequirements.has(tagName)) {
|
|
2298
|
+
return true;
|
|
2299
|
+
}
|
|
2300
|
+
if (role && this.parentRequirements.has(`role=${role}`)) {
|
|
2301
|
+
return true;
|
|
2302
|
+
}
|
|
2303
|
+
return false;
|
|
2304
|
+
}
|
|
2305
|
+
validate(element) {
|
|
2306
|
+
const tagName = element.tagName;
|
|
2307
|
+
const role = element.getAttribute("role");
|
|
2308
|
+
let requirement;
|
|
2309
|
+
let identifier = "";
|
|
2310
|
+
if (role && this.parentRequirements.has(`role=${role}`)) {
|
|
2311
|
+
requirement = this.parentRequirements.get(`role=${role}`);
|
|
2312
|
+
identifier = `role="${role}"`;
|
|
2313
|
+
} else if (this.parentRequirements.has(tagName)) {
|
|
2314
|
+
requirement = this.parentRequirements.get(tagName);
|
|
2315
|
+
identifier = `<${tagName.toLowerCase()}>`;
|
|
2316
|
+
}
|
|
2317
|
+
if (!requirement) {
|
|
2318
|
+
return null;
|
|
2319
|
+
}
|
|
2320
|
+
if (requirement.customValidator) {
|
|
2321
|
+
if (requirement.customValidator(element)) {
|
|
2322
|
+
return null;
|
|
2323
|
+
} else {
|
|
2324
|
+
return this.createIssue(element, identifier, requirement);
|
|
2325
|
+
}
|
|
2326
|
+
}
|
|
2327
|
+
if (this.hasValidParent(element, requirement)) {
|
|
2328
|
+
return null;
|
|
2329
|
+
}
|
|
2330
|
+
return this.createIssue(element, identifier, requirement);
|
|
2331
|
+
}
|
|
2332
|
+
hasValidParent(element, requirement) {
|
|
2333
|
+
var _a, _b, _c;
|
|
2334
|
+
let parent = element.parentElement;
|
|
2335
|
+
let depth = 0;
|
|
2336
|
+
const maxDepth = requirement.allowIntermediateWrappers ? 2 : 1;
|
|
2337
|
+
while (parent && depth < maxDepth) {
|
|
2338
|
+
if ((_a = requirement.allowedParents) == null ? void 0 : _a.includes(parent.tagName)) {
|
|
2339
|
+
return true;
|
|
2340
|
+
}
|
|
2341
|
+
const parentRole = parent.getAttribute("role");
|
|
2342
|
+
if (parentRole && ((_b = requirement.allowedParentRoles) == null ? void 0 : _b.includes(parentRole))) {
|
|
2343
|
+
return true;
|
|
2344
|
+
}
|
|
2345
|
+
if (depth === 0 && !requirement.allowIntermediateWrappers) {
|
|
2346
|
+
break;
|
|
2347
|
+
}
|
|
2348
|
+
if (depth === 0 && requirement.allowIntermediateWrappers) {
|
|
2349
|
+
if (!((_c = requirement.allowedWrappers) == null ? void 0 : _c.includes(parent.tagName))) {
|
|
2350
|
+
break;
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
parent = parent.parentElement;
|
|
2354
|
+
depth++;
|
|
2355
|
+
}
|
|
2356
|
+
return false;
|
|
2357
|
+
}
|
|
2358
|
+
createIssue(element, identifier, requirement) {
|
|
2359
|
+
var _a, _b;
|
|
2360
|
+
const allowedParentsText = [
|
|
2361
|
+
...((_a = requirement.allowedParents) == null ? void 0 : _a.map((p) => `<${p.toLowerCase()}>`)) || [],
|
|
2362
|
+
...((_b = requirement.allowedParentRoles) == null ? void 0 : _b.map((r) => `role="${r}"`)) || []
|
|
2363
|
+
].join(", ");
|
|
2364
|
+
const message = `${identifier} must be contained by ${allowedParentsText}`;
|
|
2365
|
+
return {
|
|
2366
|
+
issue: {
|
|
2367
|
+
id: "aria-required-parent",
|
|
2368
|
+
message,
|
|
2369
|
+
element,
|
|
2370
|
+
help: "https://dequeuniversity.com/rules/axe/4.2/aria-required-parent"
|
|
2371
|
+
}
|
|
2372
|
+
};
|
|
2373
|
+
}
|
|
2374
|
+
};
|
|
2375
|
+
|
|
2376
|
+
// src/rules/nestedInteractive.ts
|
|
2377
|
+
var interactiveElementSelector = [
|
|
2378
|
+
"a[href]",
|
|
2379
|
+
"button",
|
|
2380
|
+
"input:not([type='hidden'])",
|
|
2381
|
+
"select",
|
|
2382
|
+
"textarea",
|
|
2383
|
+
"details",
|
|
2384
|
+
"audio[controls]",
|
|
2385
|
+
"video[controls]",
|
|
2386
|
+
"*[role='button']",
|
|
2387
|
+
"*[role='link']",
|
|
2388
|
+
"*[role='checkbox']",
|
|
2389
|
+
"*[role='radio']",
|
|
2390
|
+
"*[role='switch']",
|
|
2391
|
+
"*[role='tab']",
|
|
2392
|
+
"*[role='menuitem']",
|
|
2393
|
+
"*[role='menuitemcheckbox']",
|
|
2394
|
+
"*[role='menuitemradio']",
|
|
2395
|
+
"*[role='option']",
|
|
2396
|
+
"*[role='treeitem']"
|
|
2397
|
+
].join(", ");
|
|
2398
|
+
var NestedInteractiveElementRule = class extends ValidationRule {
|
|
2399
|
+
constructor() {
|
|
2400
|
+
super(...arguments);
|
|
2401
|
+
__publicField(this, "type", 1 /* Error */);
|
|
2402
|
+
__publicField(this, "name", "NestedInteractiveElementRule");
|
|
2403
|
+
__publicField(this, "anchored", true);
|
|
2404
|
+
}
|
|
2405
|
+
_isAriaHidden(element) {
|
|
2406
|
+
return element.ownerDocument.evaluate(
|
|
2407
|
+
`ancestor-or-self::*[@aria-hidden = 'true' or @hidden]`,
|
|
2408
|
+
element,
|
|
2409
|
+
null,
|
|
2410
|
+
XPathResult.BOOLEAN_TYPE,
|
|
2411
|
+
null
|
|
2412
|
+
).booleanValue;
|
|
2413
|
+
}
|
|
2414
|
+
_isInteractive(element) {
|
|
2415
|
+
return matchesSelector(element, interactiveElementSelector);
|
|
2416
|
+
}
|
|
2417
|
+
_findNestedInteractive(element) {
|
|
2418
|
+
const descendants = element.querySelectorAll(interactiveElementSelector);
|
|
2419
|
+
for (let i = 0; i < descendants.length; i++) {
|
|
2420
|
+
const descendant = descendants[i];
|
|
2421
|
+
if (this._isAriaHidden(descendant)) {
|
|
2422
|
+
continue;
|
|
2423
|
+
}
|
|
2424
|
+
return descendant;
|
|
2425
|
+
}
|
|
2426
|
+
return null;
|
|
2427
|
+
}
|
|
2428
|
+
accept(element) {
|
|
2429
|
+
return this._isInteractive(element);
|
|
2430
|
+
}
|
|
2431
|
+
validate(element) {
|
|
2432
|
+
if (this._isAriaHidden(element)) {
|
|
2433
|
+
return null;
|
|
2434
|
+
}
|
|
2435
|
+
const nestedElement = this._findNestedInteractive(element);
|
|
2436
|
+
if (nestedElement) {
|
|
2437
|
+
const elementTag = element.tagName.toLowerCase();
|
|
2438
|
+
const elementRole = element.getAttribute("role");
|
|
2439
|
+
const nestedTag = nestedElement.tagName.toLowerCase();
|
|
2440
|
+
const nestedRole = nestedElement.getAttribute("role");
|
|
2441
|
+
const elementDesc = elementRole ? `${elementTag}[role="${elementRole}"]` : elementTag;
|
|
2442
|
+
const nestedDesc = nestedRole ? `${nestedTag}[role="${nestedRole}"]` : nestedTag;
|
|
2443
|
+
return {
|
|
2444
|
+
issue: isElementVisible(element) ? {
|
|
2445
|
+
id: "nested-interactive",
|
|
2446
|
+
message: `Interactive element <${elementDesc}> contains a nested interactive element <${nestedDesc}>. This can confuse users and assistive technologies.`,
|
|
2447
|
+
element,
|
|
2448
|
+
rel: nestedElement,
|
|
2449
|
+
help: "https://dequeuniversity.com/rules/axe/4.4/nested-interactive"
|
|
2450
|
+
} : void 0
|
|
2451
|
+
};
|
|
2452
|
+
}
|
|
2453
|
+
return null;
|
|
2454
|
+
}
|
|
2455
|
+
};
|
|
2456
|
+
|
|
2457
|
+
// src/rules/tabindex.ts
|
|
2458
|
+
var INTERACTIVE_ELEMENTS = /* @__PURE__ */ new Set([
|
|
2459
|
+
"A",
|
|
2460
|
+
"BUTTON",
|
|
2461
|
+
"INPUT",
|
|
2462
|
+
"SELECT",
|
|
2463
|
+
"TEXTAREA",
|
|
2464
|
+
"DETAILS",
|
|
2465
|
+
"SUMMARY",
|
|
2466
|
+
"AUDIO",
|
|
2467
|
+
"VIDEO"
|
|
2468
|
+
]);
|
|
2469
|
+
var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
|
|
2470
|
+
"button",
|
|
2471
|
+
"link",
|
|
2472
|
+
"checkbox",
|
|
2473
|
+
"radio",
|
|
2474
|
+
"textbox",
|
|
2475
|
+
"combobox",
|
|
2476
|
+
"listbox",
|
|
2477
|
+
"menu",
|
|
2478
|
+
"menubar",
|
|
2479
|
+
"menuitem",
|
|
2480
|
+
"menuitemcheckbox",
|
|
2481
|
+
"menuitemradio",
|
|
2482
|
+
"option",
|
|
2483
|
+
"searchbox",
|
|
2484
|
+
"slider",
|
|
2485
|
+
"spinbutton",
|
|
2486
|
+
"switch",
|
|
2487
|
+
"tab",
|
|
2488
|
+
"tablist",
|
|
2489
|
+
"tree",
|
|
2490
|
+
"treegrid",
|
|
2491
|
+
"treeitem",
|
|
2492
|
+
"grid",
|
|
2493
|
+
"gridcell"
|
|
2494
|
+
]);
|
|
2495
|
+
var TabIndexRule = class extends ValidationRule {
|
|
2496
|
+
constructor() {
|
|
2497
|
+
super(...arguments);
|
|
2498
|
+
__publicField(this, "type", 2 /* Warning */);
|
|
2499
|
+
__publicField(this, "name", "tabindex");
|
|
2500
|
+
__publicField(this, "anchored", true);
|
|
2501
|
+
}
|
|
2502
|
+
accept(element) {
|
|
2503
|
+
return element.hasAttribute("tabindex");
|
|
2504
|
+
}
|
|
2505
|
+
isInteractiveElement(element) {
|
|
2506
|
+
if (INTERACTIVE_ELEMENTS.has(element.tagName)) {
|
|
2507
|
+
if (element.hasAttribute("disabled")) {
|
|
2508
|
+
return false;
|
|
2509
|
+
}
|
|
2510
|
+
if (element.tagName === "A" && !element.hasAttribute("href")) {
|
|
2511
|
+
return false;
|
|
2512
|
+
}
|
|
2513
|
+
return true;
|
|
2514
|
+
}
|
|
2515
|
+
const role = element.getAttribute("role");
|
|
2516
|
+
if (role && INTERACTIVE_ROLES.has(role)) {
|
|
2517
|
+
return true;
|
|
2518
|
+
}
|
|
2519
|
+
if (element.isContentEditable) {
|
|
2520
|
+
return true;
|
|
2521
|
+
}
|
|
2522
|
+
return false;
|
|
2523
|
+
}
|
|
2524
|
+
validate(element) {
|
|
2525
|
+
const tabindex = parseInt(element.getAttribute("tabindex") || "0", 10);
|
|
2526
|
+
if (tabindex > 0 && this.isInteractiveElement(element)) {
|
|
2527
|
+
return {
|
|
2528
|
+
issue: {
|
|
2529
|
+
id: "tabindex",
|
|
2530
|
+
message: `Avoid positive tabindex values (found: ${tabindex})`,
|
|
2531
|
+
element,
|
|
2532
|
+
help: "https://dequeuniversity.com/rules/axe/4.2/tabindex"
|
|
2533
|
+
}
|
|
2534
|
+
};
|
|
2535
|
+
}
|
|
2536
|
+
if (!this.isInteractiveElement(element)) {
|
|
2537
|
+
return {
|
|
2538
|
+
issue: {
|
|
2539
|
+
id: "tabindex-non-interactive",
|
|
2540
|
+
message: `Avoid using tabindex on non-interactive elements (<${element.tagName.toLowerCase()}>). Consider adding an interactive role or making the element naturally interactive.`,
|
|
2541
|
+
element,
|
|
2542
|
+
help: "https://dequeuniversity.com/rules/axe/4.2/tabindex"
|
|
2543
|
+
}
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
return null;
|
|
2547
|
+
}
|
|
2548
|
+
};
|
|
1970
2549
|
export {
|
|
1971
2550
|
AbleDOM,
|
|
1972
2551
|
AtomicRule,
|
|
@@ -1977,6 +2556,9 @@ export {
|
|
|
1977
2556
|
FindElementRule,
|
|
1978
2557
|
FocusLostRule,
|
|
1979
2558
|
FocusableElementLabelRule,
|
|
2559
|
+
NestedInteractiveElementRule,
|
|
2560
|
+
RequiredParentRule,
|
|
2561
|
+
TabIndexRule,
|
|
1980
2562
|
ValidationRule,
|
|
1981
2563
|
ValidationRuleType,
|
|
1982
2564
|
hasAccessibilityAttribute,
|