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/index.js
CHANGED
|
@@ -31,6 +31,9 @@ __export(index_exports, {
|
|
|
31
31
|
FindElementRule: () => FindElementRule,
|
|
32
32
|
FocusLostRule: () => FocusLostRule,
|
|
33
33
|
FocusableElementLabelRule: () => FocusableElementLabelRule,
|
|
34
|
+
NestedInteractiveElementRule: () => NestedInteractiveElementRule,
|
|
35
|
+
RequiredParentRule: () => RequiredParentRule,
|
|
36
|
+
TabIndexRule: () => TabIndexRule,
|
|
34
37
|
ValidationRule: () => ValidationRule,
|
|
35
38
|
ValidationRuleType: () => ValidationRuleType,
|
|
36
39
|
hasAccessibilityAttribute: () => hasAccessibilityAttribute,
|
|
@@ -97,7 +100,10 @@ var ValidationRule = class {
|
|
|
97
100
|
};
|
|
98
101
|
|
|
99
102
|
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/ui.css
|
|
100
|
-
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
|
|
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";
|
|
104
|
+
|
|
105
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/highlighter.css
|
|
106
|
+
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";
|
|
101
107
|
|
|
102
108
|
// src/ui/domBuilder.ts
|
|
103
109
|
var DOMBuilder = class {
|
|
@@ -403,8 +409,7 @@ var IssueUI = class {
|
|
|
403
409
|
if (element2) {
|
|
404
410
|
revealButton.onclick = () => {
|
|
405
411
|
var _a;
|
|
406
|
-
|
|
407
|
-
(_a = this._issuesUI) == null ? void 0 : _a.highlight(element2);
|
|
412
|
+
(_a = this._issuesUI) == null ? void 0 : _a.highlight(element2, true);
|
|
408
413
|
};
|
|
409
414
|
} else {
|
|
410
415
|
revealButton.style.display = "none";
|
|
@@ -481,7 +486,8 @@ var IssueUI = class {
|
|
|
481
486
|
}
|
|
482
487
|
};
|
|
483
488
|
var IssuesUI = class {
|
|
484
|
-
constructor(win, props) {
|
|
489
|
+
constructor(win, getHighlighter, props) {
|
|
490
|
+
__publicField(this, "_win");
|
|
485
491
|
__publicField(this, "_container");
|
|
486
492
|
__publicField(this, "_issuesContainer");
|
|
487
493
|
__publicField(this, "_menuElement");
|
|
@@ -494,9 +500,11 @@ var IssuesUI = class {
|
|
|
494
500
|
__publicField(this, "_alignBottomRightButton");
|
|
495
501
|
__publicField(this, "_isMuted", false);
|
|
496
502
|
__publicField(this, "_issues", /* @__PURE__ */ new Set());
|
|
497
|
-
__publicField(this, "
|
|
503
|
+
__publicField(this, "_getHighlighter");
|
|
498
504
|
__publicField(this, "bugReport");
|
|
499
505
|
__publicField(this, "headless");
|
|
506
|
+
this._win = win;
|
|
507
|
+
this._getHighlighter = getHighlighter;
|
|
500
508
|
this.bugReport = props.bugReport;
|
|
501
509
|
this.headless = !!props.headless;
|
|
502
510
|
if (this.headless) {
|
|
@@ -617,7 +625,6 @@ var IssuesUI = class {
|
|
|
617
625
|
}
|
|
618
626
|
).element(alignbottomright_default).closeTag().closeTag();
|
|
619
627
|
doc.body.appendChild(container);
|
|
620
|
-
this._highlighter = new ElementHighlighter(win);
|
|
621
628
|
}
|
|
622
629
|
setUIAlignment(alignment) {
|
|
623
630
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
@@ -739,15 +746,15 @@ var IssuesUI = class {
|
|
|
739
746
|
});
|
|
740
747
|
this._setShowHideButtonsVisibility();
|
|
741
748
|
}
|
|
742
|
-
highlight(element) {
|
|
743
|
-
var _a;
|
|
744
|
-
(_a = this.
|
|
749
|
+
highlight(element, scrollIntoView, autoHideTime) {
|
|
750
|
+
var _a, _b;
|
|
751
|
+
(_b = (_a = this._getHighlighter) == null ? void 0 : _a.call(this)) == null ? void 0 : _b.highlight(element, scrollIntoView, autoHideTime);
|
|
745
752
|
}
|
|
746
753
|
dispose() {
|
|
747
|
-
var _a
|
|
748
|
-
(_a = this.
|
|
749
|
-
|
|
750
|
-
delete this.
|
|
754
|
+
var _a;
|
|
755
|
+
(_a = this._container) == null ? void 0 : _a.remove();
|
|
756
|
+
delete this._win;
|
|
757
|
+
delete this._getHighlighter;
|
|
751
758
|
delete this._container;
|
|
752
759
|
delete this._issuesContainer;
|
|
753
760
|
delete this._menuElement;
|
|
@@ -767,6 +774,7 @@ var ElementHighlighter = class {
|
|
|
767
774
|
__publicField(this, "_element");
|
|
768
775
|
__publicField(this, "_cancelScrollTimer");
|
|
769
776
|
__publicField(this, "_intersectionObserver");
|
|
777
|
+
__publicField(this, "_cancelAutoHideTimer");
|
|
770
778
|
__publicField(this, "_onScroll", () => {
|
|
771
779
|
var _a;
|
|
772
780
|
(_a = this._cancelScrollTimer) == null ? void 0 : _a.call(this);
|
|
@@ -787,10 +795,19 @@ var ElementHighlighter = class {
|
|
|
787
795
|
const container = this._container = win.document.createElement("div");
|
|
788
796
|
container.__abledomui = true;
|
|
789
797
|
container.className = "abledom-highlight";
|
|
798
|
+
const doc = win.document;
|
|
799
|
+
const style = doc.createElement("style");
|
|
800
|
+
style.type = "text/css";
|
|
801
|
+
style.appendChild(doc.createTextNode(highlighter_default));
|
|
802
|
+
container.appendChild(style);
|
|
790
803
|
new DOMBuilder(container).openTag("div", { class: "abledom-highlight-border1" }).closeTag().openTag("div", { class: "abledom-highlight-border2" }).closeTag();
|
|
791
804
|
win.addEventListener("scroll", this._onScroll, true);
|
|
792
805
|
}
|
|
793
|
-
highlight(element) {
|
|
806
|
+
highlight(element, scrollIntoView, autoHideTime) {
|
|
807
|
+
var _a;
|
|
808
|
+
if (this._cancelAutoHideTimer && element !== this._element) {
|
|
809
|
+
this._cancelAutoHideTimer();
|
|
810
|
+
}
|
|
794
811
|
if (!element) {
|
|
795
812
|
delete this._element;
|
|
796
813
|
this._unobserve();
|
|
@@ -803,6 +820,22 @@ var ElementHighlighter = class {
|
|
|
803
820
|
return;
|
|
804
821
|
}
|
|
805
822
|
this._element = element;
|
|
823
|
+
if (scrollIntoView) {
|
|
824
|
+
element.scrollIntoView({ block: "center" });
|
|
825
|
+
}
|
|
826
|
+
if (autoHideTime) {
|
|
827
|
+
(_a = this._cancelAutoHideTimer) == null ? void 0 : _a.call(this);
|
|
828
|
+
const autoHideTimeout = win.setTimeout(() => {
|
|
829
|
+
if (this._cancelAutoHideTimer) {
|
|
830
|
+
this.highlight(null);
|
|
831
|
+
delete this._cancelAutoHideTimer;
|
|
832
|
+
}
|
|
833
|
+
}, autoHideTime);
|
|
834
|
+
this._cancelAutoHideTimer = () => {
|
|
835
|
+
win.clearTimeout(autoHideTimeout);
|
|
836
|
+
delete this._cancelAutoHideTimer;
|
|
837
|
+
};
|
|
838
|
+
}
|
|
806
839
|
this._intersectionObserver = new IntersectionObserver(([entry]) => {
|
|
807
840
|
if (entry) {
|
|
808
841
|
const rect = entry.boundingClientRect;
|
|
@@ -821,11 +854,12 @@ var ElementHighlighter = class {
|
|
|
821
854
|
this._intersectionObserver.observe(element);
|
|
822
855
|
}
|
|
823
856
|
dispose() {
|
|
824
|
-
var _a, _b, _c;
|
|
857
|
+
var _a, _b, _c, _d;
|
|
825
858
|
this._unobserve();
|
|
826
859
|
(_a = this._cancelScrollTimer) == null ? void 0 : _a.call(this);
|
|
827
|
-
(_b = this.
|
|
828
|
-
(_c = this.
|
|
860
|
+
(_b = this._cancelAutoHideTimer) == null ? void 0 : _b.call(this);
|
|
861
|
+
(_c = this._window) == null ? void 0 : _c.removeEventListener("scroll", this._onScroll, true);
|
|
862
|
+
(_d = this._container) == null ? void 0 : _d.remove();
|
|
829
863
|
delete this._element;
|
|
830
864
|
delete this._container;
|
|
831
865
|
delete this._window;
|
|
@@ -868,10 +902,17 @@ var AccessibilityAffectingElements = {
|
|
|
868
902
|
aside: true,
|
|
869
903
|
body: true,
|
|
870
904
|
button: true,
|
|
905
|
+
caption: true,
|
|
906
|
+
col: true,
|
|
907
|
+
colgroup: true,
|
|
871
908
|
datalist: true,
|
|
909
|
+
dd: true,
|
|
872
910
|
details: true,
|
|
873
911
|
dialog: true,
|
|
874
912
|
dl: true,
|
|
913
|
+
dt: true,
|
|
914
|
+
figcaption: true,
|
|
915
|
+
figure: true,
|
|
875
916
|
form: true,
|
|
876
917
|
h1: true,
|
|
877
918
|
h2: true,
|
|
@@ -883,6 +924,7 @@ var AccessibilityAffectingElements = {
|
|
|
883
924
|
iframe: true,
|
|
884
925
|
img: true,
|
|
885
926
|
input: true,
|
|
927
|
+
legend: true,
|
|
886
928
|
li: true,
|
|
887
929
|
link: true,
|
|
888
930
|
main: true,
|
|
@@ -892,15 +934,22 @@ var AccessibilityAffectingElements = {
|
|
|
892
934
|
nav: true,
|
|
893
935
|
object: true,
|
|
894
936
|
ol: true,
|
|
937
|
+
optgroup: true,
|
|
895
938
|
option: true,
|
|
896
939
|
progress: true,
|
|
897
940
|
section: true,
|
|
898
941
|
select: true,
|
|
942
|
+
source: true,
|
|
943
|
+
summary: true,
|
|
944
|
+
table: true,
|
|
899
945
|
tbody: true,
|
|
946
|
+
td: true,
|
|
900
947
|
textarea: true,
|
|
901
948
|
tfoot: true,
|
|
902
949
|
th: true,
|
|
903
950
|
thead: true,
|
|
951
|
+
tr: true,
|
|
952
|
+
track: true,
|
|
904
953
|
ul: true
|
|
905
954
|
};
|
|
906
955
|
var AccessibilityAttributes = {
|
|
@@ -1033,6 +1082,7 @@ function getStackTrace() {
|
|
|
1033
1082
|
var AbleDOM = class {
|
|
1034
1083
|
constructor(win, props = {}) {
|
|
1035
1084
|
__publicField(this, "_win");
|
|
1085
|
+
__publicField(this, "_isDisposed", false);
|
|
1036
1086
|
__publicField(this, "_props");
|
|
1037
1087
|
__publicField(this, "_observer");
|
|
1038
1088
|
__publicField(this, "_clearValidationTimeout");
|
|
@@ -1045,8 +1095,17 @@ var AbleDOM = class {
|
|
|
1045
1095
|
__publicField(this, "_startFunc");
|
|
1046
1096
|
__publicField(this, "_isStarted", false);
|
|
1047
1097
|
__publicField(this, "_issuesUI");
|
|
1098
|
+
__publicField(this, "_elementHighlighter");
|
|
1048
1099
|
__publicField(this, "_idlePromise");
|
|
1049
1100
|
__publicField(this, "_idleResolve");
|
|
1101
|
+
__publicField(this, "_currentAnchoredIssues", /* @__PURE__ */ new Map());
|
|
1102
|
+
__publicField(this, "_currentNotAnchoredIssues", []);
|
|
1103
|
+
__publicField(this, "_getHighlighter", () => {
|
|
1104
|
+
if (!this._elementHighlighter && !this._isDisposed) {
|
|
1105
|
+
this._elementHighlighter = new ElementHighlighter(this._win);
|
|
1106
|
+
}
|
|
1107
|
+
return this._elementHighlighter;
|
|
1108
|
+
});
|
|
1050
1109
|
__publicField(this, "_onFocusIn", (event) => {
|
|
1051
1110
|
var _a;
|
|
1052
1111
|
const target = event.target;
|
|
@@ -1214,9 +1273,9 @@ var AbleDOM = class {
|
|
|
1214
1273
|
}
|
|
1215
1274
|
}
|
|
1216
1275
|
_addIssue(rule, issue) {
|
|
1217
|
-
var _a, _b
|
|
1276
|
+
var _a, _b;
|
|
1218
1277
|
if (!this._issuesUI) {
|
|
1219
|
-
this._issuesUI = new IssuesUI(this._win, {
|
|
1278
|
+
this._issuesUI = new IssuesUI(this._win, this._getHighlighter, {
|
|
1220
1279
|
bugReport: (_a = this._props) == null ? void 0 : _a.bugReport,
|
|
1221
1280
|
headless: (_b = this._props) == null ? void 0 : _b.headless
|
|
1222
1281
|
});
|
|
@@ -1242,26 +1301,21 @@ var AbleDOM = class {
|
|
|
1242
1301
|
issueUI = new IssueUI(this._win, this, rule, this._issuesUI);
|
|
1243
1302
|
issues.set(rule, issueUI);
|
|
1244
1303
|
justUpdate = false;
|
|
1245
|
-
|
|
1304
|
+
this._onIssueAdded(element, rule, issue);
|
|
1246
1305
|
}
|
|
1247
1306
|
this._elementsWithIssues.add(element);
|
|
1248
1307
|
} else {
|
|
1249
1308
|
issueUI = new IssueUI(this._win, this, rule, this._issuesUI);
|
|
1250
1309
|
justUpdate = false;
|
|
1251
|
-
|
|
1310
|
+
this._onIssueAdded(null, rule, issue);
|
|
1252
1311
|
}
|
|
1253
1312
|
issueUI.update(issue);
|
|
1254
|
-
if (justUpdate) {
|
|
1255
|
-
|
|
1256
|
-
_j,
|
|
1257
|
-
rule.anchored && element ? element : null,
|
|
1258
|
-
rule,
|
|
1259
|
-
issue
|
|
1260
|
-
);
|
|
1313
|
+
if (justUpdate && rule.anchored && element) {
|
|
1314
|
+
this._onIssueUpdated(element, rule, issue);
|
|
1261
1315
|
}
|
|
1262
1316
|
}
|
|
1263
1317
|
_removeIssue(element, rule) {
|
|
1264
|
-
var _a
|
|
1318
|
+
var _a;
|
|
1265
1319
|
if (!rule.anchored) {
|
|
1266
1320
|
return;
|
|
1267
1321
|
}
|
|
@@ -1273,7 +1327,7 @@ var AbleDOM = class {
|
|
|
1273
1327
|
if (issue) {
|
|
1274
1328
|
issue.dispose();
|
|
1275
1329
|
issues.delete(rule);
|
|
1276
|
-
|
|
1330
|
+
this._onIssueRemoved(element, rule);
|
|
1277
1331
|
}
|
|
1278
1332
|
if (issues.size === 0) {
|
|
1279
1333
|
this._elementsWithIssues.delete(element);
|
|
@@ -1359,6 +1413,42 @@ var AbleDOM = class {
|
|
|
1359
1413
|
this._dependantIdsByElement.set(element, dependsOnIds);
|
|
1360
1414
|
}
|
|
1361
1415
|
}
|
|
1416
|
+
_updateCurrentAnchoredIssues(element, rule, issue) {
|
|
1417
|
+
let issuesByElement = this._currentAnchoredIssues.get(element);
|
|
1418
|
+
if (!issuesByElement && issue) {
|
|
1419
|
+
issuesByElement = /* @__PURE__ */ new Map();
|
|
1420
|
+
this._currentAnchoredIssues.set(element, issuesByElement);
|
|
1421
|
+
}
|
|
1422
|
+
if (issuesByElement) {
|
|
1423
|
+
if (issue) {
|
|
1424
|
+
issuesByElement.set(rule, issue);
|
|
1425
|
+
} else {
|
|
1426
|
+
issuesByElement.delete(rule);
|
|
1427
|
+
if (issuesByElement.size === 0) {
|
|
1428
|
+
this._currentAnchoredIssues.delete(element);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
_onIssueAdded(element, rule, issue) {
|
|
1434
|
+
var _a, _b, _c;
|
|
1435
|
+
if (element) {
|
|
1436
|
+
this._updateCurrentAnchoredIssues(element, rule, issue);
|
|
1437
|
+
} else {
|
|
1438
|
+
this._currentNotAnchoredIssues.push(issue);
|
|
1439
|
+
}
|
|
1440
|
+
(_c = (_b = (_a = this._props) == null ? void 0 : _a.callbacks) == null ? void 0 : _b.onIssueAdded) == null ? void 0 : _c.call(_b, element, rule, issue);
|
|
1441
|
+
}
|
|
1442
|
+
_onIssueUpdated(element, rule, issue) {
|
|
1443
|
+
var _a, _b, _c;
|
|
1444
|
+
this._updateCurrentAnchoredIssues(element, rule, issue);
|
|
1445
|
+
(_c = (_b = (_a = this._props) == null ? void 0 : _a.callbacks) == null ? void 0 : _b.onIssueUpdated) == null ? void 0 : _c.call(_b, element, rule, issue);
|
|
1446
|
+
}
|
|
1447
|
+
_onIssueRemoved(element, rule) {
|
|
1448
|
+
var _a, _b, _c;
|
|
1449
|
+
this._updateCurrentAnchoredIssues(element, rule, null);
|
|
1450
|
+
(_c = (_b = (_a = this._props) == null ? void 0 : _a.callbacks) == null ? void 0 : _b.onIssueRemoved) == null ? void 0 : _c.call(_b, element, rule);
|
|
1451
|
+
}
|
|
1362
1452
|
_remove(elements) {
|
|
1363
1453
|
elements.forEach((element) => {
|
|
1364
1454
|
var _a, _b;
|
|
@@ -1366,21 +1456,42 @@ var AbleDOM = class {
|
|
|
1366
1456
|
rules.forEach((rule) => this._removeIssue(element, rule));
|
|
1367
1457
|
});
|
|
1368
1458
|
}
|
|
1459
|
+
_getCurrentIssues() {
|
|
1460
|
+
const issues = this._currentNotAnchoredIssues.slice(0);
|
|
1461
|
+
this._currentAnchoredIssues.forEach((issueByRule) => {
|
|
1462
|
+
issueByRule.forEach((issue) => {
|
|
1463
|
+
issues.push(issue);
|
|
1464
|
+
});
|
|
1465
|
+
});
|
|
1466
|
+
return issues;
|
|
1467
|
+
}
|
|
1369
1468
|
idle() {
|
|
1370
1469
|
if (!this._clearValidationTimeout) {
|
|
1371
|
-
return Promise.resolve();
|
|
1470
|
+
return Promise.resolve(this._getCurrentIssues());
|
|
1372
1471
|
}
|
|
1373
1472
|
if (!this._idlePromise) {
|
|
1374
1473
|
this._idlePromise = new Promise((resolve) => {
|
|
1375
1474
|
this._idleResolve = () => {
|
|
1376
1475
|
delete this._idlePromise;
|
|
1377
1476
|
delete this._idleResolve;
|
|
1378
|
-
resolve();
|
|
1477
|
+
resolve(this._getCurrentIssues());
|
|
1379
1478
|
};
|
|
1380
1479
|
});
|
|
1381
1480
|
}
|
|
1382
1481
|
return this._idlePromise;
|
|
1383
1482
|
}
|
|
1483
|
+
clearCurrentIssues(anchored = true, notAnchored = true) {
|
|
1484
|
+
if (anchored) {
|
|
1485
|
+
this._currentAnchoredIssues.clear();
|
|
1486
|
+
}
|
|
1487
|
+
if (notAnchored) {
|
|
1488
|
+
this._currentNotAnchoredIssues = [];
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
highlightElement(element, scrollIntoView, autoHideTime) {
|
|
1492
|
+
var _a;
|
|
1493
|
+
(_a = this._getHighlighter()) == null ? void 0 : _a.highlight(element, scrollIntoView, autoHideTime);
|
|
1494
|
+
}
|
|
1384
1495
|
addRule(rule) {
|
|
1385
1496
|
this._rules.push(rule);
|
|
1386
1497
|
}
|
|
@@ -1407,6 +1518,7 @@ var AbleDOM = class {
|
|
|
1407
1518
|
}
|
|
1408
1519
|
dispose() {
|
|
1409
1520
|
var _a, _b, _c, _d;
|
|
1521
|
+
this._isDisposed = true;
|
|
1410
1522
|
const doc = this._win.document;
|
|
1411
1523
|
doc.addEventListener("focusin", this._onFocusIn, true);
|
|
1412
1524
|
doc.addEventListener("focusout", this._onFocusOut, true);
|
|
@@ -1415,6 +1527,7 @@ var AbleDOM = class {
|
|
|
1415
1527
|
this._dependantIdsByElement.clear();
|
|
1416
1528
|
this._elementsDependingOnId.clear();
|
|
1417
1529
|
this._idByElement.clear();
|
|
1530
|
+
this.clearCurrentIssues();
|
|
1418
1531
|
(_a = this._issuesUI) == null ? void 0 : _a.dispose();
|
|
1419
1532
|
delete this._issuesUI;
|
|
1420
1533
|
(_b = this._clearValidationTimeout) == null ? void 0 : _b.call(this);
|
|
@@ -2006,6 +2119,475 @@ var CustomNotifyRule = class extends ValidationRule {
|
|
|
2006
2119
|
});
|
|
2007
2120
|
}
|
|
2008
2121
|
};
|
|
2122
|
+
|
|
2123
|
+
// src/rules/requiredparent.ts
|
|
2124
|
+
var RequiredParentRule = class extends ValidationRule {
|
|
2125
|
+
constructor() {
|
|
2126
|
+
super(...arguments);
|
|
2127
|
+
__publicField(this, "type", 1 /* Error */);
|
|
2128
|
+
__publicField(this, "name", "aria-required-parent");
|
|
2129
|
+
__publicField(this, "anchored", true);
|
|
2130
|
+
__publicField(this, "parentRequirements", /* @__PURE__ */ new Map([
|
|
2131
|
+
[
|
|
2132
|
+
"LI",
|
|
2133
|
+
{
|
|
2134
|
+
allowedParents: ["UL", "OL"],
|
|
2135
|
+
allowedParentRoles: ["list"]
|
|
2136
|
+
}
|
|
2137
|
+
],
|
|
2138
|
+
[
|
|
2139
|
+
"DT",
|
|
2140
|
+
{
|
|
2141
|
+
allowedParents: ["DL"],
|
|
2142
|
+
allowIntermediateWrappers: true,
|
|
2143
|
+
allowedWrappers: ["DIV"]
|
|
2144
|
+
}
|
|
2145
|
+
],
|
|
2146
|
+
[
|
|
2147
|
+
"DD",
|
|
2148
|
+
{
|
|
2149
|
+
allowedParents: ["DL"],
|
|
2150
|
+
allowIntermediateWrappers: true,
|
|
2151
|
+
allowedWrappers: ["DIV"]
|
|
2152
|
+
}
|
|
2153
|
+
],
|
|
2154
|
+
[
|
|
2155
|
+
"TR",
|
|
2156
|
+
{
|
|
2157
|
+
allowedParents: ["TABLE", "THEAD", "TBODY", "TFOOT"],
|
|
2158
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2159
|
+
}
|
|
2160
|
+
],
|
|
2161
|
+
[
|
|
2162
|
+
"TH",
|
|
2163
|
+
{
|
|
2164
|
+
allowedParents: ["TR"],
|
|
2165
|
+
allowedParentRoles: ["row"]
|
|
2166
|
+
}
|
|
2167
|
+
],
|
|
2168
|
+
[
|
|
2169
|
+
"TD",
|
|
2170
|
+
{
|
|
2171
|
+
allowedParents: ["TR"],
|
|
2172
|
+
allowedParentRoles: ["row"]
|
|
2173
|
+
}
|
|
2174
|
+
],
|
|
2175
|
+
[
|
|
2176
|
+
"THEAD",
|
|
2177
|
+
{
|
|
2178
|
+
allowedParents: ["TABLE"],
|
|
2179
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2180
|
+
}
|
|
2181
|
+
],
|
|
2182
|
+
[
|
|
2183
|
+
"TBODY",
|
|
2184
|
+
{
|
|
2185
|
+
allowedParents: ["TABLE"],
|
|
2186
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2187
|
+
}
|
|
2188
|
+
],
|
|
2189
|
+
[
|
|
2190
|
+
"TFOOT",
|
|
2191
|
+
{
|
|
2192
|
+
allowedParents: ["TABLE"],
|
|
2193
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2194
|
+
}
|
|
2195
|
+
],
|
|
2196
|
+
[
|
|
2197
|
+
"CAPTION",
|
|
2198
|
+
{
|
|
2199
|
+
allowedParents: ["TABLE"]
|
|
2200
|
+
}
|
|
2201
|
+
],
|
|
2202
|
+
[
|
|
2203
|
+
"COLGROUP",
|
|
2204
|
+
{
|
|
2205
|
+
allowedParents: ["TABLE"]
|
|
2206
|
+
}
|
|
2207
|
+
],
|
|
2208
|
+
[
|
|
2209
|
+
"COL",
|
|
2210
|
+
{
|
|
2211
|
+
allowedParents: ["COLGROUP"]
|
|
2212
|
+
}
|
|
2213
|
+
],
|
|
2214
|
+
[
|
|
2215
|
+
"FIGCAPTION",
|
|
2216
|
+
{
|
|
2217
|
+
allowedParents: ["FIGURE"]
|
|
2218
|
+
}
|
|
2219
|
+
],
|
|
2220
|
+
[
|
|
2221
|
+
"OPTION",
|
|
2222
|
+
{
|
|
2223
|
+
allowedParents: ["SELECT", "OPTGROUP", "DATALIST"]
|
|
2224
|
+
}
|
|
2225
|
+
],
|
|
2226
|
+
[
|
|
2227
|
+
"OPTGROUP",
|
|
2228
|
+
{
|
|
2229
|
+
allowedParents: ["SELECT"]
|
|
2230
|
+
}
|
|
2231
|
+
],
|
|
2232
|
+
[
|
|
2233
|
+
"LEGEND",
|
|
2234
|
+
{
|
|
2235
|
+
allowedParents: ["FIELDSET"]
|
|
2236
|
+
}
|
|
2237
|
+
],
|
|
2238
|
+
[
|
|
2239
|
+
"SUMMARY",
|
|
2240
|
+
{
|
|
2241
|
+
allowedParents: ["DETAILS"]
|
|
2242
|
+
}
|
|
2243
|
+
],
|
|
2244
|
+
[
|
|
2245
|
+
"SOURCE",
|
|
2246
|
+
{
|
|
2247
|
+
allowedParents: ["AUDIO", "VIDEO", "PICTURE"]
|
|
2248
|
+
}
|
|
2249
|
+
],
|
|
2250
|
+
[
|
|
2251
|
+
"TRACK",
|
|
2252
|
+
{
|
|
2253
|
+
allowedParents: ["AUDIO", "VIDEO"]
|
|
2254
|
+
}
|
|
2255
|
+
],
|
|
2256
|
+
[
|
|
2257
|
+
"role=menuitem",
|
|
2258
|
+
{
|
|
2259
|
+
allowedParentRoles: ["menu", "menubar", "group"]
|
|
2260
|
+
}
|
|
2261
|
+
],
|
|
2262
|
+
[
|
|
2263
|
+
"role=menuitemcheckbox",
|
|
2264
|
+
{
|
|
2265
|
+
allowedParentRoles: ["menu", "menubar", "group"]
|
|
2266
|
+
}
|
|
2267
|
+
],
|
|
2268
|
+
[
|
|
2269
|
+
"role=menuitemradio",
|
|
2270
|
+
{
|
|
2271
|
+
allowedParentRoles: ["menu", "menubar", "group"]
|
|
2272
|
+
}
|
|
2273
|
+
],
|
|
2274
|
+
[
|
|
2275
|
+
"role=listitem",
|
|
2276
|
+
{
|
|
2277
|
+
allowedParentRoles: ["list", "group"]
|
|
2278
|
+
}
|
|
2279
|
+
],
|
|
2280
|
+
[
|
|
2281
|
+
"role=treeitem",
|
|
2282
|
+
{
|
|
2283
|
+
allowedParentRoles: ["tree", "group"]
|
|
2284
|
+
}
|
|
2285
|
+
],
|
|
2286
|
+
[
|
|
2287
|
+
"role=tab",
|
|
2288
|
+
{
|
|
2289
|
+
allowedParentRoles: ["tablist"]
|
|
2290
|
+
}
|
|
2291
|
+
],
|
|
2292
|
+
[
|
|
2293
|
+
"role=row",
|
|
2294
|
+
{
|
|
2295
|
+
allowedParentRoles: ["table", "grid", "treegrid", "rowgroup"]
|
|
2296
|
+
}
|
|
2297
|
+
],
|
|
2298
|
+
[
|
|
2299
|
+
"role=cell",
|
|
2300
|
+
{
|
|
2301
|
+
allowedParentRoles: ["row"]
|
|
2302
|
+
}
|
|
2303
|
+
],
|
|
2304
|
+
[
|
|
2305
|
+
"role=gridcell",
|
|
2306
|
+
{
|
|
2307
|
+
allowedParentRoles: ["row"]
|
|
2308
|
+
}
|
|
2309
|
+
],
|
|
2310
|
+
[
|
|
2311
|
+
"role=columnheader",
|
|
2312
|
+
{
|
|
2313
|
+
allowedParentRoles: ["row"]
|
|
2314
|
+
}
|
|
2315
|
+
],
|
|
2316
|
+
[
|
|
2317
|
+
"role=rowheader",
|
|
2318
|
+
{
|
|
2319
|
+
allowedParentRoles: ["row"]
|
|
2320
|
+
}
|
|
2321
|
+
],
|
|
2322
|
+
[
|
|
2323
|
+
"role=rowgroup",
|
|
2324
|
+
{
|
|
2325
|
+
allowedParentRoles: ["table", "grid", "treegrid"]
|
|
2326
|
+
}
|
|
2327
|
+
],
|
|
2328
|
+
[
|
|
2329
|
+
"role=option",
|
|
2330
|
+
{
|
|
2331
|
+
allowedParentRoles: ["listbox", "group"]
|
|
2332
|
+
}
|
|
2333
|
+
]
|
|
2334
|
+
]));
|
|
2335
|
+
}
|
|
2336
|
+
accept(element) {
|
|
2337
|
+
const tagName = element.tagName;
|
|
2338
|
+
const role = element.getAttribute("role");
|
|
2339
|
+
if (this.parentRequirements.has(tagName)) {
|
|
2340
|
+
return true;
|
|
2341
|
+
}
|
|
2342
|
+
if (role && this.parentRequirements.has(`role=${role}`)) {
|
|
2343
|
+
return true;
|
|
2344
|
+
}
|
|
2345
|
+
return false;
|
|
2346
|
+
}
|
|
2347
|
+
validate(element) {
|
|
2348
|
+
const tagName = element.tagName;
|
|
2349
|
+
const role = element.getAttribute("role");
|
|
2350
|
+
let requirement;
|
|
2351
|
+
let identifier = "";
|
|
2352
|
+
if (role && this.parentRequirements.has(`role=${role}`)) {
|
|
2353
|
+
requirement = this.parentRequirements.get(`role=${role}`);
|
|
2354
|
+
identifier = `role="${role}"`;
|
|
2355
|
+
} else if (this.parentRequirements.has(tagName)) {
|
|
2356
|
+
requirement = this.parentRequirements.get(tagName);
|
|
2357
|
+
identifier = `<${tagName.toLowerCase()}>`;
|
|
2358
|
+
}
|
|
2359
|
+
if (!requirement) {
|
|
2360
|
+
return null;
|
|
2361
|
+
}
|
|
2362
|
+
if (requirement.customValidator) {
|
|
2363
|
+
if (requirement.customValidator(element)) {
|
|
2364
|
+
return null;
|
|
2365
|
+
} else {
|
|
2366
|
+
return this.createIssue(element, identifier, requirement);
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
if (this.hasValidParent(element, requirement)) {
|
|
2370
|
+
return null;
|
|
2371
|
+
}
|
|
2372
|
+
return this.createIssue(element, identifier, requirement);
|
|
2373
|
+
}
|
|
2374
|
+
hasValidParent(element, requirement) {
|
|
2375
|
+
var _a, _b, _c;
|
|
2376
|
+
let parent = element.parentElement;
|
|
2377
|
+
let depth = 0;
|
|
2378
|
+
const maxDepth = requirement.allowIntermediateWrappers ? 2 : 1;
|
|
2379
|
+
while (parent && depth < maxDepth) {
|
|
2380
|
+
if ((_a = requirement.allowedParents) == null ? void 0 : _a.includes(parent.tagName)) {
|
|
2381
|
+
return true;
|
|
2382
|
+
}
|
|
2383
|
+
const parentRole = parent.getAttribute("role");
|
|
2384
|
+
if (parentRole && ((_b = requirement.allowedParentRoles) == null ? void 0 : _b.includes(parentRole))) {
|
|
2385
|
+
return true;
|
|
2386
|
+
}
|
|
2387
|
+
if (depth === 0 && !requirement.allowIntermediateWrappers) {
|
|
2388
|
+
break;
|
|
2389
|
+
}
|
|
2390
|
+
if (depth === 0 && requirement.allowIntermediateWrappers) {
|
|
2391
|
+
if (!((_c = requirement.allowedWrappers) == null ? void 0 : _c.includes(parent.tagName))) {
|
|
2392
|
+
break;
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
parent = parent.parentElement;
|
|
2396
|
+
depth++;
|
|
2397
|
+
}
|
|
2398
|
+
return false;
|
|
2399
|
+
}
|
|
2400
|
+
createIssue(element, identifier, requirement) {
|
|
2401
|
+
var _a, _b;
|
|
2402
|
+
const allowedParentsText = [
|
|
2403
|
+
...((_a = requirement.allowedParents) == null ? void 0 : _a.map((p) => `<${p.toLowerCase()}>`)) || [],
|
|
2404
|
+
...((_b = requirement.allowedParentRoles) == null ? void 0 : _b.map((r) => `role="${r}"`)) || []
|
|
2405
|
+
].join(", ");
|
|
2406
|
+
const message = `${identifier} must be contained by ${allowedParentsText}`;
|
|
2407
|
+
return {
|
|
2408
|
+
issue: {
|
|
2409
|
+
id: "aria-required-parent",
|
|
2410
|
+
message,
|
|
2411
|
+
element,
|
|
2412
|
+
help: "https://dequeuniversity.com/rules/axe/4.2/aria-required-parent"
|
|
2413
|
+
}
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
};
|
|
2417
|
+
|
|
2418
|
+
// src/rules/nestedInteractive.ts
|
|
2419
|
+
var interactiveElementSelector = [
|
|
2420
|
+
"a[href]",
|
|
2421
|
+
"button",
|
|
2422
|
+
"input:not([type='hidden'])",
|
|
2423
|
+
"select",
|
|
2424
|
+
"textarea",
|
|
2425
|
+
"details",
|
|
2426
|
+
"audio[controls]",
|
|
2427
|
+
"video[controls]",
|
|
2428
|
+
"*[role='button']",
|
|
2429
|
+
"*[role='link']",
|
|
2430
|
+
"*[role='checkbox']",
|
|
2431
|
+
"*[role='radio']",
|
|
2432
|
+
"*[role='switch']",
|
|
2433
|
+
"*[role='tab']",
|
|
2434
|
+
"*[role='menuitem']",
|
|
2435
|
+
"*[role='menuitemcheckbox']",
|
|
2436
|
+
"*[role='menuitemradio']",
|
|
2437
|
+
"*[role='option']",
|
|
2438
|
+
"*[role='treeitem']"
|
|
2439
|
+
].join(", ");
|
|
2440
|
+
var NestedInteractiveElementRule = class extends ValidationRule {
|
|
2441
|
+
constructor() {
|
|
2442
|
+
super(...arguments);
|
|
2443
|
+
__publicField(this, "type", 1 /* Error */);
|
|
2444
|
+
__publicField(this, "name", "NestedInteractiveElementRule");
|
|
2445
|
+
__publicField(this, "anchored", true);
|
|
2446
|
+
}
|
|
2447
|
+
_isAriaHidden(element) {
|
|
2448
|
+
return element.ownerDocument.evaluate(
|
|
2449
|
+
`ancestor-or-self::*[@aria-hidden = 'true' or @hidden]`,
|
|
2450
|
+
element,
|
|
2451
|
+
null,
|
|
2452
|
+
XPathResult.BOOLEAN_TYPE,
|
|
2453
|
+
null
|
|
2454
|
+
).booleanValue;
|
|
2455
|
+
}
|
|
2456
|
+
_isInteractive(element) {
|
|
2457
|
+
return matchesSelector(element, interactiveElementSelector);
|
|
2458
|
+
}
|
|
2459
|
+
_findNestedInteractive(element) {
|
|
2460
|
+
const descendants = element.querySelectorAll(interactiveElementSelector);
|
|
2461
|
+
for (let i = 0; i < descendants.length; i++) {
|
|
2462
|
+
const descendant = descendants[i];
|
|
2463
|
+
if (this._isAriaHidden(descendant)) {
|
|
2464
|
+
continue;
|
|
2465
|
+
}
|
|
2466
|
+
return descendant;
|
|
2467
|
+
}
|
|
2468
|
+
return null;
|
|
2469
|
+
}
|
|
2470
|
+
accept(element) {
|
|
2471
|
+
return this._isInteractive(element);
|
|
2472
|
+
}
|
|
2473
|
+
validate(element) {
|
|
2474
|
+
if (this._isAriaHidden(element)) {
|
|
2475
|
+
return null;
|
|
2476
|
+
}
|
|
2477
|
+
const nestedElement = this._findNestedInteractive(element);
|
|
2478
|
+
if (nestedElement) {
|
|
2479
|
+
const elementTag = element.tagName.toLowerCase();
|
|
2480
|
+
const elementRole = element.getAttribute("role");
|
|
2481
|
+
const nestedTag = nestedElement.tagName.toLowerCase();
|
|
2482
|
+
const nestedRole = nestedElement.getAttribute("role");
|
|
2483
|
+
const elementDesc = elementRole ? `${elementTag}[role="${elementRole}"]` : elementTag;
|
|
2484
|
+
const nestedDesc = nestedRole ? `${nestedTag}[role="${nestedRole}"]` : nestedTag;
|
|
2485
|
+
return {
|
|
2486
|
+
issue: isElementVisible(element) ? {
|
|
2487
|
+
id: "nested-interactive",
|
|
2488
|
+
message: `Interactive element <${elementDesc}> contains a nested interactive element <${nestedDesc}>. This can confuse users and assistive technologies.`,
|
|
2489
|
+
element,
|
|
2490
|
+
rel: nestedElement,
|
|
2491
|
+
help: "https://dequeuniversity.com/rules/axe/4.4/nested-interactive"
|
|
2492
|
+
} : void 0
|
|
2493
|
+
};
|
|
2494
|
+
}
|
|
2495
|
+
return null;
|
|
2496
|
+
}
|
|
2497
|
+
};
|
|
2498
|
+
|
|
2499
|
+
// src/rules/tabindex.ts
|
|
2500
|
+
var INTERACTIVE_ELEMENTS = /* @__PURE__ */ new Set([
|
|
2501
|
+
"A",
|
|
2502
|
+
"BUTTON",
|
|
2503
|
+
"INPUT",
|
|
2504
|
+
"SELECT",
|
|
2505
|
+
"TEXTAREA",
|
|
2506
|
+
"DETAILS",
|
|
2507
|
+
"SUMMARY",
|
|
2508
|
+
"AUDIO",
|
|
2509
|
+
"VIDEO"
|
|
2510
|
+
]);
|
|
2511
|
+
var INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
|
|
2512
|
+
"button",
|
|
2513
|
+
"link",
|
|
2514
|
+
"checkbox",
|
|
2515
|
+
"radio",
|
|
2516
|
+
"textbox",
|
|
2517
|
+
"combobox",
|
|
2518
|
+
"listbox",
|
|
2519
|
+
"menu",
|
|
2520
|
+
"menubar",
|
|
2521
|
+
"menuitem",
|
|
2522
|
+
"menuitemcheckbox",
|
|
2523
|
+
"menuitemradio",
|
|
2524
|
+
"option",
|
|
2525
|
+
"searchbox",
|
|
2526
|
+
"slider",
|
|
2527
|
+
"spinbutton",
|
|
2528
|
+
"switch",
|
|
2529
|
+
"tab",
|
|
2530
|
+
"tablist",
|
|
2531
|
+
"tree",
|
|
2532
|
+
"treegrid",
|
|
2533
|
+
"treeitem",
|
|
2534
|
+
"grid",
|
|
2535
|
+
"gridcell"
|
|
2536
|
+
]);
|
|
2537
|
+
var TabIndexRule = class extends ValidationRule {
|
|
2538
|
+
constructor() {
|
|
2539
|
+
super(...arguments);
|
|
2540
|
+
__publicField(this, "type", 2 /* Warning */);
|
|
2541
|
+
__publicField(this, "name", "tabindex");
|
|
2542
|
+
__publicField(this, "anchored", true);
|
|
2543
|
+
}
|
|
2544
|
+
accept(element) {
|
|
2545
|
+
return element.hasAttribute("tabindex");
|
|
2546
|
+
}
|
|
2547
|
+
isInteractiveElement(element) {
|
|
2548
|
+
if (INTERACTIVE_ELEMENTS.has(element.tagName)) {
|
|
2549
|
+
if (element.hasAttribute("disabled")) {
|
|
2550
|
+
return false;
|
|
2551
|
+
}
|
|
2552
|
+
if (element.tagName === "A" && !element.hasAttribute("href")) {
|
|
2553
|
+
return false;
|
|
2554
|
+
}
|
|
2555
|
+
return true;
|
|
2556
|
+
}
|
|
2557
|
+
const role = element.getAttribute("role");
|
|
2558
|
+
if (role && INTERACTIVE_ROLES.has(role)) {
|
|
2559
|
+
return true;
|
|
2560
|
+
}
|
|
2561
|
+
if (element.isContentEditable) {
|
|
2562
|
+
return true;
|
|
2563
|
+
}
|
|
2564
|
+
return false;
|
|
2565
|
+
}
|
|
2566
|
+
validate(element) {
|
|
2567
|
+
const tabindex = parseInt(element.getAttribute("tabindex") || "0", 10);
|
|
2568
|
+
if (tabindex > 0 && this.isInteractiveElement(element)) {
|
|
2569
|
+
return {
|
|
2570
|
+
issue: {
|
|
2571
|
+
id: "tabindex",
|
|
2572
|
+
message: `Avoid positive tabindex values (found: ${tabindex})`,
|
|
2573
|
+
element,
|
|
2574
|
+
help: "https://dequeuniversity.com/rules/axe/4.2/tabindex"
|
|
2575
|
+
}
|
|
2576
|
+
};
|
|
2577
|
+
}
|
|
2578
|
+
if (!this.isInteractiveElement(element)) {
|
|
2579
|
+
return {
|
|
2580
|
+
issue: {
|
|
2581
|
+
id: "tabindex-non-interactive",
|
|
2582
|
+
message: `Avoid using tabindex on non-interactive elements (<${element.tagName.toLowerCase()}>). Consider adding an interactive role or making the element naturally interactive.`,
|
|
2583
|
+
element,
|
|
2584
|
+
help: "https://dequeuniversity.com/rules/axe/4.2/tabindex"
|
|
2585
|
+
}
|
|
2586
|
+
};
|
|
2587
|
+
}
|
|
2588
|
+
return null;
|
|
2589
|
+
}
|
|
2590
|
+
};
|
|
2009
2591
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2010
2592
|
0 && (module.exports = {
|
|
2011
2593
|
AbleDOM,
|
|
@@ -2017,6 +2599,9 @@ var CustomNotifyRule = class extends ValidationRule {
|
|
|
2017
2599
|
FindElementRule,
|
|
2018
2600
|
FocusLostRule,
|
|
2019
2601
|
FocusableElementLabelRule,
|
|
2602
|
+
NestedInteractiveElementRule,
|
|
2603
|
+
RequiredParentRule,
|
|
2604
|
+
TabIndexRule,
|
|
2020
2605
|
ValidationRule,
|
|
2021
2606
|
ValidationRuleType,
|
|
2022
2607
|
hasAccessibilityAttribute,
|