abledom 0.0.0 → 0.0.2
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/README.md +6 -12
- package/dist/esm/index.js +1416 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.d.cts +203 -0
- package/dist/index.d.ts +203 -0
- package/dist/index.js +1455 -0
- package/dist/index.js.map +1 -0
- package/dist/ts3.9/index.d.ts +186 -0
- package/package.json +45 -6
- package/CODE_OF_CONDUCT.md +0 -9
- package/SECURITY.md +0 -41
- package/SUPPORT.md +0 -25
- package/index.js +0 -0
|
@@ -0,0 +1,1416 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
5
|
+
// src/rules/base.ts
|
|
6
|
+
var ValidationRuleType = /* @__PURE__ */ ((ValidationRuleType2) => {
|
|
7
|
+
ValidationRuleType2[ValidationRuleType2["Error"] = 1] = "Error";
|
|
8
|
+
ValidationRuleType2[ValidationRuleType2["Warning"] = 2] = "Warning";
|
|
9
|
+
ValidationRuleType2[ValidationRuleType2["Info"] = 3] = "Info";
|
|
10
|
+
return ValidationRuleType2;
|
|
11
|
+
})(ValidationRuleType || {});
|
|
12
|
+
var ValidationRule = class {
|
|
13
|
+
constructor() {
|
|
14
|
+
__publicField(this, "_window");
|
|
15
|
+
__publicField(this, "_exceptions", []);
|
|
16
|
+
__publicField(this, "_onNotification");
|
|
17
|
+
}
|
|
18
|
+
static init(instance, window, onNotification) {
|
|
19
|
+
instance._window = window;
|
|
20
|
+
instance._onNotification = onNotification;
|
|
21
|
+
}
|
|
22
|
+
static dispose(instance) {
|
|
23
|
+
instance.dispose();
|
|
24
|
+
}
|
|
25
|
+
static checkExceptions(instance, element) {
|
|
26
|
+
for (const exception of instance._exceptions) {
|
|
27
|
+
if (exception(element)) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
dispose() {
|
|
34
|
+
this._window = void 0;
|
|
35
|
+
this._onNotification = void 0;
|
|
36
|
+
this._exceptions = [];
|
|
37
|
+
}
|
|
38
|
+
addException(checkException) {
|
|
39
|
+
var _a;
|
|
40
|
+
(_a = this._exceptions) == null ? void 0 : _a.push(checkException);
|
|
41
|
+
}
|
|
42
|
+
removeException(checkException) {
|
|
43
|
+
const index = this._exceptions.indexOf(checkException);
|
|
44
|
+
if (index >= 0) {
|
|
45
|
+
this._exceptions.splice(index, 1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Window is set when the rule is added to the AbleDOM instance.
|
|
50
|
+
*/
|
|
51
|
+
get window() {
|
|
52
|
+
return this._window;
|
|
53
|
+
}
|
|
54
|
+
notify(notification) {
|
|
55
|
+
var _a;
|
|
56
|
+
(_a = this._onNotification) == null ? void 0 : _a.call(this, this, notification);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
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: absolute;\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 .notifications-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-notifications-container {\n overflow: scroll;\n max-height: calc(100vh - 100px);\n}\n\n#abledom-report.abledom-align-right .abledom-notifications-container {\n text-align: right;\n}\n\n.abledom-notification-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-notification {\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-notification_warning {\n background-color: rgba(163, 82, 1, 0.7);\n}\n.abledom-notification_info {\n background-color: rgba(0, 0, 255, 0.7);\n}\n\n.abledom-notification .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-notification .button:hover {\n opacity: 0.7;\n}\n\n.abledom-notification .button.close {\n background: none;\n border-color: transparent;\n color: #fff;\n margin: 0;\n}\n\n.abledom-highlight {\n background-color: yellow;\n border: 1px solid red;\n box-sizing: border-box;\n display: none;\n opacity: 0.6;\n position: absolute;\n z-index: 100499;\n}\n";
|
|
62
|
+
|
|
63
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/close.svg
|
|
64
|
+
var close_default = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"\n stroke-width="2" stroke-linecap="round" stroke-linejoin="round"\n xmlns="http://www.w3.org/2000/svg">\n <circle cx="12" cy="12" r="10"/>\n <line x1="15" y1="9" x2="9" y2="15"/>\n <line x1="9" y1="9" x2="15" y2="15"/>\n</svg>\n';
|
|
65
|
+
|
|
66
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/help.svg
|
|
67
|
+
var help_default = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none"\n stroke="currentColor" stroke-width="2" stroke-linecap="round"\n stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg">\n <circle cx="12" cy="12" r="10"/>\n <path d="M9.09 9a3 3 0 1 1 5.83 1c-.28 1.02-1.22 1.5-2.01 2.1-.76.58-1 1.1-1 2"/>\n <circle cx="12" cy="17" r="0.5"/>\n</svg>';
|
|
68
|
+
|
|
69
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/log.svg
|
|
70
|
+
var log_default = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"\n stroke-width="2" stroke-linecap="round" stroke-linejoin="round"\n xmlns="http://www.w3.org/2000/svg">\n <polyline points="4 7 9 12 4 17"/>\n <line x1="11" y1="19" x2="20" y2="19"/>\n</svg>';
|
|
71
|
+
|
|
72
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/reveal.svg
|
|
73
|
+
var reveal_default = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor"\n stroke-width="2" stroke-linecap="round" stroke-linejoin="round"\n xmlns="http://www.w3.org/2000/svg">\n <circle cx="12" cy="12" r="10"/>\n <line x1="12" y1="2" x2="12" y2="6"/>\n <line x1="12" y1="18" x2="12" y2="22"/>\n <line x1="2" y1="12" x2="6" y2="12"/>\n <line x1="18" y1="12" x2="22" y2="12"/>\n</svg>';
|
|
74
|
+
|
|
75
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/hideall.svg
|
|
76
|
+
var hideall_default = '<svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">\n <path d="M11.44 17.5a1.67 1.67 0 0 1-2.89 0" stroke-width="1.5"/>\n <path d="M15 6.67a5 5 0 0 0-10 0v4.17a1.67 1.67 0 0 1-.83 1.44L3.33 14.17h13.34l-0.83-1.89a1.67 1.67 0 0 1-.83-1.44V6.67z" stroke-width="1.5"/>\n <line x1="1.67" y1="1.67" x2="18.33" y2="18.33" stroke-width="1.5"/>\n</svg>\n';
|
|
77
|
+
|
|
78
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/muteall.svg
|
|
79
|
+
var muteall_default = '<svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">\n <path d="M11.44 17.5a1.67 1.67 0 0 1-2.89 0" stroke-width="1.5"/>\n <path d="M15 6.67a5 5 0 0 0-10 0v4.17a1.67 1.67 0 0 1-.83 1.44L3.33 14.17h13.34l-0.83-1.89a1.67 1.67 0 0 1-.83-1.44V6.67z" stroke-width="1.5"/>\n <line x1="1.67" y1="1.67" x2="18.33" y2="18.33" stroke-width="1.5"/>\n <line x1="18.33" y1="1.67" x2="1.67" y2="18.33" stroke-width="1.5"/>\n</svg>\n';
|
|
80
|
+
|
|
81
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/showall.svg
|
|
82
|
+
var showall_default = '<svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">\n <path d="M11.44 17.5a1.67 1.67 0 0 1-2.89 0" stroke-width="1.5"/>\n <path d="M15 6.67a5 5 0 0 0-10 0v4.17a1.67 1.67 0 0 1-.83 1.44L3.33 14.17h13.34l-0.83-1.89a1.67 1.67 0 0 1-.83-1.44V6.67z" stroke-width="1.5"/>\n</svg>\n';
|
|
83
|
+
|
|
84
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/aligntopleft.svg
|
|
85
|
+
var aligntopleft_default = '<svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">\n <rect x="3" y="3" width="6" height="6" stroke-width="2"/>\n</svg>\n';
|
|
86
|
+
|
|
87
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/aligntopright.svg
|
|
88
|
+
var aligntopright_default = '<svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">\n <rect x="11" y="3" width="6" height="6" stroke-width="2"/>\n</svg>\n';
|
|
89
|
+
|
|
90
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/alignbottomright.svg
|
|
91
|
+
var alignbottomright_default = '<svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">\n <rect x="11" y="11" width="6" height="6" stroke-width="2"/>\n</svg>\n';
|
|
92
|
+
|
|
93
|
+
// inline-file:/Users/marata/Documents/Work/abledom/src/ui/alignbottomleft.svg
|
|
94
|
+
var alignbottomleft_default = '<svg width="20" height="20" viewBox="0 0 20 20" fill="none" stroke="currentColor">\n <rect x="3" y="11" width="6" height="6" stroke-width="2"/>\n</svg>\n';
|
|
95
|
+
|
|
96
|
+
// src/ui/ui.ts
|
|
97
|
+
var pressedClass = "pressed";
|
|
98
|
+
var _NotificationUI = class _NotificationUI {
|
|
99
|
+
constructor(win, rule) {
|
|
100
|
+
__publicField(this, "_win");
|
|
101
|
+
__publicField(this, "_wrapper");
|
|
102
|
+
__publicField(this, "_rule");
|
|
103
|
+
__publicField(this, "_onToggle");
|
|
104
|
+
__publicField(this, "isHidden", false);
|
|
105
|
+
this._win = win;
|
|
106
|
+
this._rule = rule;
|
|
107
|
+
if (!_NotificationUI._notificationsUI) {
|
|
108
|
+
_NotificationUI._notificationsUI = new NotificationsUI(this._win);
|
|
109
|
+
}
|
|
110
|
+
this._wrapper = win.document.createElement(
|
|
111
|
+
"div"
|
|
112
|
+
);
|
|
113
|
+
if (!_NotificationUI._highlight) {
|
|
114
|
+
_NotificationUI._highlight = new ElementHighlighter(win);
|
|
115
|
+
}
|
|
116
|
+
_NotificationUI._notificationsUI.addNotification(this);
|
|
117
|
+
}
|
|
118
|
+
static setOnToggle(instance, onToggle) {
|
|
119
|
+
instance._onToggle = onToggle;
|
|
120
|
+
}
|
|
121
|
+
static getElement(instance) {
|
|
122
|
+
return instance._wrapper;
|
|
123
|
+
}
|
|
124
|
+
update(notification) {
|
|
125
|
+
var _a;
|
|
126
|
+
const win = this._win;
|
|
127
|
+
const rule = this._rule;
|
|
128
|
+
const wrapper = this._wrapper;
|
|
129
|
+
const element = notification.element;
|
|
130
|
+
wrapper.__abledomui = true;
|
|
131
|
+
wrapper.innerHTML = `
|
|
132
|
+
<div class="abledom-notification-container"><div class="abledom-notification${rule.type === 2 /* Warning */ ? " abledom-notification_warning" : rule.type === 3 /* Info */ ? " abledom-notification_info" : ""}">
|
|
133
|
+
<button class="button" title="Log to Console">${log_default}</button>
|
|
134
|
+
<button class="button" title="Reveal in Elements panel">${reveal_default}</button>
|
|
135
|
+
${notification.message}
|
|
136
|
+
<a href class="button close" href="/" title="Open help" target="_blank">${help_default}</a>
|
|
137
|
+
<button class="button close" class="close" title="Hide">${close_default}</button>
|
|
138
|
+
</div></div>`;
|
|
139
|
+
const container = wrapper.firstElementChild;
|
|
140
|
+
const buttons = wrapper.querySelectorAll("button");
|
|
141
|
+
const logButton = buttons[0];
|
|
142
|
+
const revealButton = buttons[1];
|
|
143
|
+
const closeButton = buttons[2];
|
|
144
|
+
logButton.onclick = () => {
|
|
145
|
+
console.error(
|
|
146
|
+
"AbleDOM: ",
|
|
147
|
+
"\nmessage:",
|
|
148
|
+
notification.message,
|
|
149
|
+
"\nelement:",
|
|
150
|
+
element,
|
|
151
|
+
...notification.rel ? ["\nrelative:", notification.rel] : [],
|
|
152
|
+
"\nnotification:",
|
|
153
|
+
notification
|
|
154
|
+
);
|
|
155
|
+
};
|
|
156
|
+
const hasDevTools = !!((_a = win.__ableDOMDevtools) == null ? void 0 : _a.revealElement) && false;
|
|
157
|
+
if (hasDevTools && element && win.document.body.contains(element)) {
|
|
158
|
+
revealButton.onclick = () => {
|
|
159
|
+
var _a2;
|
|
160
|
+
const revealElement = (_a2 = win.__ableDOMDevtools) == null ? void 0 : _a2.revealElement;
|
|
161
|
+
if (revealElement && win.document.body.contains(element)) {
|
|
162
|
+
revealElement(element).then((revealed) => {
|
|
163
|
+
if (!revealed) {
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
} else {
|
|
169
|
+
revealButton.style.display = "none";
|
|
170
|
+
}
|
|
171
|
+
closeButton.onclick = () => {
|
|
172
|
+
var _a2;
|
|
173
|
+
this.toggle(false);
|
|
174
|
+
(_a2 = _NotificationUI._highlight) == null ? void 0 : _a2.hide();
|
|
175
|
+
};
|
|
176
|
+
container.onmouseover = () => {
|
|
177
|
+
var _a2;
|
|
178
|
+
element && ((_a2 = _NotificationUI._highlight) == null ? void 0 : _a2.highlight(element));
|
|
179
|
+
};
|
|
180
|
+
container.onmouseout = () => {
|
|
181
|
+
var _a2;
|
|
182
|
+
(_a2 = _NotificationUI._highlight) == null ? void 0 : _a2.hide();
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
toggle(show, initial = false) {
|
|
186
|
+
var _a;
|
|
187
|
+
this.isHidden = !show;
|
|
188
|
+
if (!initial) {
|
|
189
|
+
(_a = this._onToggle) == null ? void 0 : _a.call(this, this, show);
|
|
190
|
+
if (!this._rule.anchored && !show) {
|
|
191
|
+
this.dispose();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
this._wrapper.style.display = show ? "block" : "none";
|
|
195
|
+
}
|
|
196
|
+
dispose() {
|
|
197
|
+
var _a;
|
|
198
|
+
this._wrapper.remove();
|
|
199
|
+
(_a = _NotificationUI._notificationsUI) == null ? void 0 : _a.removeNotification(this);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
__publicField(_NotificationUI, "_notificationsUI");
|
|
203
|
+
__publicField(_NotificationUI, "_highlight");
|
|
204
|
+
var NotificationUI = _NotificationUI;
|
|
205
|
+
var NotificationsUI = class {
|
|
206
|
+
constructor(win) {
|
|
207
|
+
__publicField(this, "_container");
|
|
208
|
+
__publicField(this, "_notificationsContainer");
|
|
209
|
+
__publicField(this, "_menuElement");
|
|
210
|
+
__publicField(this, "_notificationCountElement");
|
|
211
|
+
__publicField(this, "_showAllButton");
|
|
212
|
+
__publicField(this, "_hideAllButton");
|
|
213
|
+
__publicField(this, "_alignBottomLeftButton");
|
|
214
|
+
__publicField(this, "_alignTopLeftButton");
|
|
215
|
+
__publicField(this, "_alignTopRightButton");
|
|
216
|
+
__publicField(this, "_alignBottomRightButton");
|
|
217
|
+
__publicField(this, "_isMuted", false);
|
|
218
|
+
__publicField(this, "_notifications", /* @__PURE__ */ new Set());
|
|
219
|
+
var _a;
|
|
220
|
+
const container = this._container = win.document.createElement("div");
|
|
221
|
+
container.__abledomui = true;
|
|
222
|
+
container.id = "abledom-report";
|
|
223
|
+
container.innerHTML = `<style>${ui_default}</style>`;
|
|
224
|
+
const notificationsContainer = this._notificationsContainer = win.document.createElement("div");
|
|
225
|
+
notificationsContainer.className = "abledom-notifications-container";
|
|
226
|
+
container.appendChild(notificationsContainer);
|
|
227
|
+
const menuElement = this._menuElement = win.document.createElement("div");
|
|
228
|
+
menuElement.className = "abledom-menu-container";
|
|
229
|
+
menuElement.innerHTML = `<div class="abledom-menu"><span class="notifications-count"></span
|
|
230
|
+
><button class="button" title="Show all notifications">${showall_default}</button
|
|
231
|
+
><button class="button" title="Hide all notifications">${hideall_default}</button
|
|
232
|
+
><button class="button" title="Mute newly appearing notifications">${muteall_default}</button
|
|
233
|
+
><button class="button align-button align-button-first pressed" title="Attach notifications to bottom left">${alignbottomleft_default}</button
|
|
234
|
+
><button class="button align-button" title="Attach notifications to top left">${aligntopleft_default}</button
|
|
235
|
+
><button class="button align-button" title="Attach notifications to top right">${aligntopright_default}</button
|
|
236
|
+
><button class="button align-button align-button-last" title="Attach notifications to bottom right">${alignbottomright_default}</button
|
|
237
|
+
></div>`;
|
|
238
|
+
const [
|
|
239
|
+
notificationCountElement,
|
|
240
|
+
showAllButton,
|
|
241
|
+
hideAllButton,
|
|
242
|
+
muteButton,
|
|
243
|
+
alignBottomLeftButton,
|
|
244
|
+
alignTopLeftButton,
|
|
245
|
+
alignTopRightButton,
|
|
246
|
+
alignBottomRightButton
|
|
247
|
+
] = ((_a = menuElement.firstElementChild) == null ? void 0 : _a.childNodes) || [];
|
|
248
|
+
if (notificationCountElement instanceof HTMLSpanElement && showAllButton instanceof HTMLButtonElement && hideAllButton instanceof HTMLButtonElement && muteButton instanceof HTMLButtonElement && alignBottomLeftButton instanceof HTMLButtonElement && alignTopLeftButton instanceof HTMLButtonElement && alignTopRightButton instanceof HTMLButtonElement && alignBottomRightButton instanceof HTMLButtonElement) {
|
|
249
|
+
container.appendChild(menuElement);
|
|
250
|
+
this._notificationCountElement = notificationCountElement;
|
|
251
|
+
this._showAllButton = showAllButton;
|
|
252
|
+
this._hideAllButton = hideAllButton;
|
|
253
|
+
this._alignBottomLeftButton = alignBottomLeftButton;
|
|
254
|
+
this._alignTopLeftButton = alignTopLeftButton;
|
|
255
|
+
this._alignTopRightButton = alignTopRightButton;
|
|
256
|
+
this._alignBottomRightButton = alignBottomRightButton;
|
|
257
|
+
showAllButton.onclick = () => {
|
|
258
|
+
this.showAll();
|
|
259
|
+
};
|
|
260
|
+
hideAllButton.onclick = () => {
|
|
261
|
+
this.hideAll();
|
|
262
|
+
};
|
|
263
|
+
muteButton.onclick = () => {
|
|
264
|
+
const isMuted = this._isMuted = muteButton.classList.toggle(pressedClass);
|
|
265
|
+
if (isMuted) {
|
|
266
|
+
muteButton.setAttribute(
|
|
267
|
+
"title",
|
|
268
|
+
"Unmute newly appearing notifications"
|
|
269
|
+
);
|
|
270
|
+
} else {
|
|
271
|
+
muteButton.setAttribute(
|
|
272
|
+
"title",
|
|
273
|
+
"Mute newly appearing notifications"
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
alignBottomLeftButton.onclick = () => {
|
|
278
|
+
this.setUIAlignment("bottom-left" /* BottomLeft */);
|
|
279
|
+
};
|
|
280
|
+
alignBottomRightButton.onclick = () => {
|
|
281
|
+
this.setUIAlignment("bottom-right" /* BottomRight */);
|
|
282
|
+
};
|
|
283
|
+
alignTopLeftButton.onclick = () => {
|
|
284
|
+
this.setUIAlignment("top-left" /* TopLeft */);
|
|
285
|
+
};
|
|
286
|
+
alignTopRightButton.onclick = () => {
|
|
287
|
+
this.setUIAlignment("top-right" /* TopRight */);
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
win.document.body.appendChild(container);
|
|
291
|
+
}
|
|
292
|
+
setUIAlignment(alignment) {
|
|
293
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
294
|
+
(_a = this._alignBottomLeftButton) == null ? void 0 : _a.classList.remove(pressedClass);
|
|
295
|
+
(_b = this._alignBottomRightButton) == null ? void 0 : _b.classList.remove(pressedClass);
|
|
296
|
+
(_c = this._alignTopLeftButton) == null ? void 0 : _c.classList.remove(pressedClass);
|
|
297
|
+
(_d = this._alignTopRightButton) == null ? void 0 : _d.classList.remove(pressedClass);
|
|
298
|
+
this._container.classList.remove(
|
|
299
|
+
"abledom-align-left",
|
|
300
|
+
"abledom-align-right",
|
|
301
|
+
"abledom-align-top",
|
|
302
|
+
"abledom-align-bottom"
|
|
303
|
+
);
|
|
304
|
+
let containerClasses = [];
|
|
305
|
+
let notificationsFirst = false;
|
|
306
|
+
switch (alignment) {
|
|
307
|
+
case "bottom-left" /* BottomLeft */:
|
|
308
|
+
containerClasses = ["abledom-align-left", "abledom-align-bottom"];
|
|
309
|
+
notificationsFirst = true;
|
|
310
|
+
(_e = this._alignBottomLeftButton) == null ? void 0 : _e.classList.add(pressedClass);
|
|
311
|
+
break;
|
|
312
|
+
case "bottom-right" /* BottomRight */:
|
|
313
|
+
containerClasses = ["abledom-align-right", "abledom-align-bottom"];
|
|
314
|
+
notificationsFirst = true;
|
|
315
|
+
(_f = this._alignBottomRightButton) == null ? void 0 : _f.classList.add(pressedClass);
|
|
316
|
+
break;
|
|
317
|
+
case "top-left" /* TopLeft */:
|
|
318
|
+
containerClasses = ["abledom-align-left", "abledom-align-top"];
|
|
319
|
+
(_g = this._alignTopLeftButton) == null ? void 0 : _g.classList.add(pressedClass);
|
|
320
|
+
break;
|
|
321
|
+
case "top-right" /* TopRight */:
|
|
322
|
+
containerClasses = ["abledom-align-right", "abledom-align-top"];
|
|
323
|
+
(_h = this._alignTopRightButton) == null ? void 0 : _h.classList.add(pressedClass);
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
this._container.classList.add(...containerClasses);
|
|
327
|
+
this._container.insertBefore(
|
|
328
|
+
this._notificationsContainer,
|
|
329
|
+
notificationsFirst ? this._menuElement : null
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
_setNotificationsCount(count) {
|
|
333
|
+
const countElement = this._notificationCountElement;
|
|
334
|
+
if (countElement && count > 0) {
|
|
335
|
+
countElement.innerHTML = `<strong>${count}</strong> notification${count > 1 ? "s" : ""}`;
|
|
336
|
+
this._menuElement.style.display = "block";
|
|
337
|
+
} else {
|
|
338
|
+
this._menuElement.style.display = "none";
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
_setShowHideButtonsVisibility() {
|
|
342
|
+
const showAllButton = this._showAllButton;
|
|
343
|
+
const hideAllButton = this._hideAllButton;
|
|
344
|
+
if (!showAllButton || !hideAllButton) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
let allHidden = true;
|
|
348
|
+
let allVisible = true;
|
|
349
|
+
for (let notification of this._notifications) {
|
|
350
|
+
if (notification.isHidden) {
|
|
351
|
+
allVisible = false;
|
|
352
|
+
} else {
|
|
353
|
+
allHidden = false;
|
|
354
|
+
}
|
|
355
|
+
if (!allHidden && !allVisible) {
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
hideAllButton.style.display = allHidden ? "none" : "block";
|
|
360
|
+
showAllButton.style.display = allVisible ? "none" : "block";
|
|
361
|
+
}
|
|
362
|
+
addNotification(notification) {
|
|
363
|
+
if (this._notifications.has(notification)) {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
if (this._isMuted) {
|
|
367
|
+
notification.toggle(false, true);
|
|
368
|
+
}
|
|
369
|
+
this._notifications.add(notification);
|
|
370
|
+
this._notificationsContainer.appendChild(
|
|
371
|
+
NotificationUI.getElement(notification)
|
|
372
|
+
);
|
|
373
|
+
NotificationUI.setOnToggle(notification, () => {
|
|
374
|
+
this._setShowHideButtonsVisibility();
|
|
375
|
+
});
|
|
376
|
+
this._setNotificationsCount(this._notifications.size);
|
|
377
|
+
this._setShowHideButtonsVisibility();
|
|
378
|
+
}
|
|
379
|
+
removeNotification(notification) {
|
|
380
|
+
if (!this._notifications.has(notification)) {
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
this._notifications.delete(notification);
|
|
384
|
+
this._setNotificationsCount(this._notifications.size);
|
|
385
|
+
this._setShowHideButtonsVisibility();
|
|
386
|
+
}
|
|
387
|
+
hideAll() {
|
|
388
|
+
this._notifications.forEach((notification) => {
|
|
389
|
+
notification.toggle(false);
|
|
390
|
+
});
|
|
391
|
+
this._setShowHideButtonsVisibility();
|
|
392
|
+
}
|
|
393
|
+
showAll() {
|
|
394
|
+
this._notifications.forEach((notification) => {
|
|
395
|
+
notification.toggle(true);
|
|
396
|
+
});
|
|
397
|
+
this._setShowHideButtonsVisibility();
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
var ElementHighlighter = class {
|
|
401
|
+
constructor(win) {
|
|
402
|
+
__publicField(this, "_window");
|
|
403
|
+
__publicField(this, "_container");
|
|
404
|
+
this._window = win;
|
|
405
|
+
const container = this._container = win.document.createElement("div");
|
|
406
|
+
container.__abledomui = true;
|
|
407
|
+
container.className = "abledom-highlight";
|
|
408
|
+
}
|
|
409
|
+
highlight(element) {
|
|
410
|
+
const rect = element.getBoundingClientRect();
|
|
411
|
+
if (rect.width === 0 || rect.height === 0) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
const win = this._window;
|
|
415
|
+
const container = this._container;
|
|
416
|
+
const style = container.style;
|
|
417
|
+
if (container.parentElement !== win.document.body) {
|
|
418
|
+
win.document.body.appendChild(container);
|
|
419
|
+
}
|
|
420
|
+
style.width = `${rect.width}px`;
|
|
421
|
+
style.height = `${rect.height}px`;
|
|
422
|
+
style.top = `${rect.top}px`;
|
|
423
|
+
style.left = `${rect.left}px`;
|
|
424
|
+
container.style.display = "block";
|
|
425
|
+
}
|
|
426
|
+
hide() {
|
|
427
|
+
this._container.style.display = "none";
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
function isAbleDOMUIElement(element) {
|
|
431
|
+
for (let el = element; el; el = el.parentElement) {
|
|
432
|
+
if (el.__abledomui) {
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// src/utils.ts
|
|
440
|
+
var focusableElementSelector = [
|
|
441
|
+
"a[href]",
|
|
442
|
+
"button:not([disabled])",
|
|
443
|
+
"input:not([disabled])",
|
|
444
|
+
"select:not([disabled])",
|
|
445
|
+
"textarea:not([disabled])",
|
|
446
|
+
"*[tabindex]",
|
|
447
|
+
"*[contenteditable]",
|
|
448
|
+
"details > summary",
|
|
449
|
+
"audio[controls]",
|
|
450
|
+
"video[controls]"
|
|
451
|
+
].join(", ");
|
|
452
|
+
var AccessibilityAffectingElements = {
|
|
453
|
+
a: true,
|
|
454
|
+
area: true,
|
|
455
|
+
article: true,
|
|
456
|
+
aside: true,
|
|
457
|
+
body: true,
|
|
458
|
+
button: true,
|
|
459
|
+
datalist: true,
|
|
460
|
+
details: true,
|
|
461
|
+
dialog: true,
|
|
462
|
+
dl: true,
|
|
463
|
+
form: true,
|
|
464
|
+
h1: true,
|
|
465
|
+
h2: true,
|
|
466
|
+
h3: true,
|
|
467
|
+
h4: true,
|
|
468
|
+
h5: true,
|
|
469
|
+
h6: true,
|
|
470
|
+
hr: true,
|
|
471
|
+
iframe: true,
|
|
472
|
+
img: true,
|
|
473
|
+
input: true,
|
|
474
|
+
li: true,
|
|
475
|
+
link: true,
|
|
476
|
+
main: true,
|
|
477
|
+
menu: true,
|
|
478
|
+
menuitem: true,
|
|
479
|
+
meter: true,
|
|
480
|
+
nav: true,
|
|
481
|
+
object: true,
|
|
482
|
+
ol: true,
|
|
483
|
+
option: true,
|
|
484
|
+
progress: true,
|
|
485
|
+
section: true,
|
|
486
|
+
select: true,
|
|
487
|
+
tbody: true,
|
|
488
|
+
textarea: true,
|
|
489
|
+
tfoot: true,
|
|
490
|
+
th: true,
|
|
491
|
+
thead: true,
|
|
492
|
+
ul: true
|
|
493
|
+
};
|
|
494
|
+
var AccessibilityAttributes = {
|
|
495
|
+
role: true,
|
|
496
|
+
tabindex: true,
|
|
497
|
+
disabled: true,
|
|
498
|
+
required: true,
|
|
499
|
+
readonly: true,
|
|
500
|
+
hidden: true,
|
|
501
|
+
"aria-activedescendant": true,
|
|
502
|
+
"aria-atomic": true,
|
|
503
|
+
"aria-autocomplete": true,
|
|
504
|
+
"aria-busy": true,
|
|
505
|
+
"aria-checked": true,
|
|
506
|
+
"aria-colcount": true,
|
|
507
|
+
"aria-colindex": true,
|
|
508
|
+
"aria-colspan": true,
|
|
509
|
+
"aria-controls": true,
|
|
510
|
+
"aria-current": true,
|
|
511
|
+
"aria-describedby": true,
|
|
512
|
+
"aria-details": true,
|
|
513
|
+
"aria-disabled": true,
|
|
514
|
+
"aria-dropeffect": true,
|
|
515
|
+
"aria-errormessage": true,
|
|
516
|
+
"aria-expanded": true,
|
|
517
|
+
"aria-flowto": true,
|
|
518
|
+
"aria-grabbed": true,
|
|
519
|
+
"aria-haspopup": true,
|
|
520
|
+
"aria-hidden": true,
|
|
521
|
+
"aria-invalid": true,
|
|
522
|
+
"aria-keyshortcuts": true,
|
|
523
|
+
"aria-label": true,
|
|
524
|
+
"aria-labelledby": true,
|
|
525
|
+
"aria-level": true,
|
|
526
|
+
"aria-live": true,
|
|
527
|
+
"aria-modal": true,
|
|
528
|
+
"aria-multiline": true,
|
|
529
|
+
"aria-multiselectable": true,
|
|
530
|
+
"aria-orientation": true,
|
|
531
|
+
"aria-owns": true,
|
|
532
|
+
"aria-placeholder": true,
|
|
533
|
+
"aria-posinset": true,
|
|
534
|
+
"aria-pressed": true,
|
|
535
|
+
"aria-readonly": true,
|
|
536
|
+
"aria-relevant": true,
|
|
537
|
+
"aria-required": true,
|
|
538
|
+
"aria-roledescription": true,
|
|
539
|
+
"aria-rowcount": true,
|
|
540
|
+
"aria-rowindex": true,
|
|
541
|
+
"aria-rowspan": true,
|
|
542
|
+
"aria-selected": true,
|
|
543
|
+
"aria-setsize": true,
|
|
544
|
+
"aria-sort": true,
|
|
545
|
+
"aria-valuemax": true,
|
|
546
|
+
"aria-valuemin": true,
|
|
547
|
+
"aria-valuenow": true,
|
|
548
|
+
"aria-valuetext": true
|
|
549
|
+
};
|
|
550
|
+
function isAccessibilityAffectingElement(element) {
|
|
551
|
+
const tagName = element.tagName.toLowerCase();
|
|
552
|
+
const attributes = getAttributes(element);
|
|
553
|
+
return tagName in AccessibilityAffectingElements || hasAccessibilityAttribute(attributes);
|
|
554
|
+
}
|
|
555
|
+
function hasAccessibilityAttribute(attributes) {
|
|
556
|
+
for (let attrName of Object.keys(attributes)) {
|
|
557
|
+
if (attrName in AccessibilityAttributes && !(attrName === "role" && (attributes[attrName] === "none" || attributes[attrName] === "presentation"))) {
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return false;
|
|
562
|
+
}
|
|
563
|
+
function getAttributes(element) {
|
|
564
|
+
const names = element.getAttributeNames();
|
|
565
|
+
const attributes = {};
|
|
566
|
+
for (let name of names) {
|
|
567
|
+
attributes[name] = element.getAttribute(name) || "";
|
|
568
|
+
}
|
|
569
|
+
return attributes;
|
|
570
|
+
}
|
|
571
|
+
function matchesSelector(element, selector) {
|
|
572
|
+
const matches = element.matches || element.matchesSelector || element.msMatchesSelector || element.webkitMatchesSelector;
|
|
573
|
+
return matches && matches.call(element, selector);
|
|
574
|
+
}
|
|
575
|
+
function isDisplayNone(element) {
|
|
576
|
+
var _a, _b;
|
|
577
|
+
const elementDocument = element.ownerDocument;
|
|
578
|
+
const computedStyle = (_a = elementDocument.defaultView) == null ? void 0 : _a.getComputedStyle(element);
|
|
579
|
+
if (element.offsetParent === null && elementDocument.body !== element && (computedStyle == null ? void 0 : computedStyle.position) !== "fixed") {
|
|
580
|
+
return true;
|
|
581
|
+
}
|
|
582
|
+
if ((computedStyle == null ? void 0 : computedStyle.visibility) === "hidden") {
|
|
583
|
+
return true;
|
|
584
|
+
}
|
|
585
|
+
if ((computedStyle == null ? void 0 : computedStyle.position) === "fixed") {
|
|
586
|
+
if (computedStyle.display === "none") {
|
|
587
|
+
return true;
|
|
588
|
+
}
|
|
589
|
+
if (((_b = element.parentElement) == null ? void 0 : _b.offsetParent) === null && elementDocument.body !== element.parentElement) {
|
|
590
|
+
return true;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
function isElementVisible(element) {
|
|
596
|
+
if (!element.ownerDocument || element.nodeType !== Node.ELEMENT_NODE) {
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
if (isDisplayNone(element)) {
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
const rect = element.ownerDocument.body.getBoundingClientRect();
|
|
603
|
+
if (rect.width === 0 && rect.height === 0) {
|
|
604
|
+
return false;
|
|
605
|
+
}
|
|
606
|
+
return true;
|
|
607
|
+
}
|
|
608
|
+
function getStackTrace() {
|
|
609
|
+
var _a;
|
|
610
|
+
const oldStackTraceLimit = Error.stackTraceLimit;
|
|
611
|
+
try {
|
|
612
|
+
Error.stackTraceLimit = 1e3;
|
|
613
|
+
throw new Error();
|
|
614
|
+
} catch (e) {
|
|
615
|
+
Error.stackTraceLimit = oldStackTraceLimit;
|
|
616
|
+
return ((_a = e.stack) == null ? void 0 : _a.split("\n").slice(1).map((line) => line.trim()).filter((line) => line.startsWith("at "))) || [];
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
// src/core.ts
|
|
621
|
+
var AbleDOM = class {
|
|
622
|
+
constructor(win) {
|
|
623
|
+
__publicField(this, "_win");
|
|
624
|
+
__publicField(this, "_observer");
|
|
625
|
+
__publicField(this, "_clearValidationTimeout");
|
|
626
|
+
__publicField(this, "_elementsWithNotifications", /* @__PURE__ */ new Set());
|
|
627
|
+
__publicField(this, "_changedElementIds", /* @__PURE__ */ new Set());
|
|
628
|
+
__publicField(this, "_elementsDependingOnId", /* @__PURE__ */ new Map());
|
|
629
|
+
__publicField(this, "_dependantIdsByElement", /* @__PURE__ */ new Map());
|
|
630
|
+
__publicField(this, "_idByElement", /* @__PURE__ */ new Map());
|
|
631
|
+
__publicField(this, "_rules", []);
|
|
632
|
+
__publicField(this, "_startFunc");
|
|
633
|
+
__publicField(this, "_isStarted", false);
|
|
634
|
+
__publicField(this, "_onFocusIn", (event) => {
|
|
635
|
+
var _a;
|
|
636
|
+
const target = event.target;
|
|
637
|
+
if (target && isAbleDOMUIElement(target)) {
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
for (const rule of this._rules) {
|
|
641
|
+
const focusNotification = (_a = rule.focused) == null ? void 0 : _a.call(rule, event);
|
|
642
|
+
if (focusNotification) {
|
|
643
|
+
this._addNotification(rule, focusNotification);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
__publicField(this, "_onFocusOut", (event) => {
|
|
648
|
+
var _a;
|
|
649
|
+
const target = event.target;
|
|
650
|
+
if (target && isAbleDOMUIElement(target)) {
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
for (const rule of this._rules) {
|
|
654
|
+
const blurNotification = (_a = rule.blurred) == null ? void 0 : _a.call(rule, event);
|
|
655
|
+
if (blurNotification) {
|
|
656
|
+
this._addNotification(rule, blurNotification);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
__publicField(this, "_notifyAsync", (rule, notification) => {
|
|
661
|
+
this._addNotification(rule, notification);
|
|
662
|
+
});
|
|
663
|
+
this._win = win;
|
|
664
|
+
const _elementsToValidate = /* @__PURE__ */ new Set();
|
|
665
|
+
const _elementsToRemove = /* @__PURE__ */ new Set();
|
|
666
|
+
win.document.addEventListener("focusin", this._onFocusIn, true);
|
|
667
|
+
win.document.addEventListener("focusout", this._onFocusOut, true);
|
|
668
|
+
this._observer = new MutationObserver((mutations) => {
|
|
669
|
+
var _a;
|
|
670
|
+
for (let mutation of mutations) {
|
|
671
|
+
if (mutation.target.__abledomui) {
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
const added = mutation.addedNodes;
|
|
675
|
+
const removed = mutation.removedNodes;
|
|
676
|
+
const attributeName = mutation.attributeName;
|
|
677
|
+
if (attributeName === "id") {
|
|
678
|
+
this._onElementId(mutation.target, false);
|
|
679
|
+
continue;
|
|
680
|
+
}
|
|
681
|
+
lookUp(mutation.target);
|
|
682
|
+
for (let i = 0; i < added.length; i++) {
|
|
683
|
+
findTargets(added[i], false);
|
|
684
|
+
}
|
|
685
|
+
for (let i = 0; i < removed.length; i++) {
|
|
686
|
+
findTargets(removed[i], true);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
(_a = this._clearValidationTimeout) == null ? void 0 : _a.call(this);
|
|
690
|
+
const _validationTimeout = win.setTimeout(() => {
|
|
691
|
+
delete this._clearValidationTimeout;
|
|
692
|
+
this._remove(_elementsToRemove);
|
|
693
|
+
this._validate(_elementsToValidate);
|
|
694
|
+
_elementsToRemove.clear();
|
|
695
|
+
_elementsToValidate.clear();
|
|
696
|
+
this._changedElementIds.clear();
|
|
697
|
+
}, 200);
|
|
698
|
+
this._clearValidationTimeout = () => {
|
|
699
|
+
win.clearTimeout(_validationTimeout);
|
|
700
|
+
delete this._clearValidationTimeout;
|
|
701
|
+
};
|
|
702
|
+
});
|
|
703
|
+
this._startFunc = () => {
|
|
704
|
+
delete this._startFunc;
|
|
705
|
+
this._observer.observe(win.document, {
|
|
706
|
+
childList: true,
|
|
707
|
+
subtree: true,
|
|
708
|
+
attributes: true
|
|
709
|
+
});
|
|
710
|
+
findTargets(win.document.body, false);
|
|
711
|
+
this._validate(_elementsToValidate);
|
|
712
|
+
_elementsToValidate.clear();
|
|
713
|
+
};
|
|
714
|
+
const addTarget = (node, removed) => {
|
|
715
|
+
if (node.nodeType !== Node.ELEMENT_NODE) {
|
|
716
|
+
return;
|
|
717
|
+
}
|
|
718
|
+
const id = node.id;
|
|
719
|
+
if (id) {
|
|
720
|
+
this._onElementId(node, removed);
|
|
721
|
+
}
|
|
722
|
+
if (removed) {
|
|
723
|
+
_elementsToRemove.add(node);
|
|
724
|
+
_elementsToValidate.delete(node);
|
|
725
|
+
} else {
|
|
726
|
+
_elementsToValidate.add(node);
|
|
727
|
+
_elementsToRemove.delete(node);
|
|
728
|
+
}
|
|
729
|
+
};
|
|
730
|
+
function lookUp(node) {
|
|
731
|
+
for (let n = node; n; n = n.parentNode) {
|
|
732
|
+
addTarget(n, _elementsToRemove.has(node));
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
function findTargets(node, removed) {
|
|
736
|
+
if (node.nodeType !== Node.ELEMENT_NODE) {
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
addTarget(node, removed);
|
|
740
|
+
const walker = win.document.createTreeWalker(
|
|
741
|
+
node,
|
|
742
|
+
NodeFilter.SHOW_ELEMENT,
|
|
743
|
+
(node2) => {
|
|
744
|
+
addTarget(node2, removed);
|
|
745
|
+
return NodeFilter.FILTER_SKIP;
|
|
746
|
+
}
|
|
747
|
+
);
|
|
748
|
+
if (walker) {
|
|
749
|
+
while (walker.nextNode()) {
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
_onElementId(element, removed) {
|
|
755
|
+
const elementId = element.getAttribute("id");
|
|
756
|
+
const oldElementId = this._idByElement.get(element);
|
|
757
|
+
if (oldElementId) {
|
|
758
|
+
this._changedElementIds.add(oldElementId);
|
|
759
|
+
const elements = this._elementsDependingOnId.get(oldElementId);
|
|
760
|
+
if (elements) {
|
|
761
|
+
elements.delete(element);
|
|
762
|
+
if (elements.size === 0) {
|
|
763
|
+
this._elementsDependingOnId.delete(oldElementId);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
if (elementId) {
|
|
768
|
+
this._changedElementIds.add(elementId);
|
|
769
|
+
let elements = this._elementsDependingOnId.get(elementId);
|
|
770
|
+
if (removed) {
|
|
771
|
+
this._idByElement.delete(element);
|
|
772
|
+
if (elements) {
|
|
773
|
+
elements.delete(element);
|
|
774
|
+
if (elements.size === 0) {
|
|
775
|
+
this._elementsDependingOnId.delete(elementId);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
} else {
|
|
779
|
+
this._idByElement.set(element, elementId);
|
|
780
|
+
if (!elements) {
|
|
781
|
+
elements = /* @__PURE__ */ new Set();
|
|
782
|
+
this._elementsDependingOnId.set(elementId, elements);
|
|
783
|
+
}
|
|
784
|
+
elements.add(element);
|
|
785
|
+
}
|
|
786
|
+
} else {
|
|
787
|
+
this._idByElement.delete(element);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
_addNotification(rule, notification) {
|
|
791
|
+
const element = notification == null ? void 0 : notification.element;
|
|
792
|
+
if (!notification) {
|
|
793
|
+
this._removeNotification(element || this._win.document.body, rule);
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
let notificationUI;
|
|
797
|
+
if (rule.anchored && element) {
|
|
798
|
+
let abledomOnElement = element.__abledom;
|
|
799
|
+
if (!abledomOnElement) {
|
|
800
|
+
abledomOnElement = element.__abledom = {};
|
|
801
|
+
}
|
|
802
|
+
let notifications = abledomOnElement.notifications;
|
|
803
|
+
if (!notifications) {
|
|
804
|
+
notifications = abledomOnElement.notifications = /* @__PURE__ */ new Map();
|
|
805
|
+
}
|
|
806
|
+
notificationUI = notifications.get(rule);
|
|
807
|
+
if (!notificationUI) {
|
|
808
|
+
notificationUI = new NotificationUI(this._win, rule);
|
|
809
|
+
notifications.set(rule, notificationUI);
|
|
810
|
+
}
|
|
811
|
+
this._elementsWithNotifications.add(element);
|
|
812
|
+
} else {
|
|
813
|
+
notificationUI = new NotificationUI(this._win, rule);
|
|
814
|
+
}
|
|
815
|
+
notificationUI.update(notification);
|
|
816
|
+
}
|
|
817
|
+
_removeNotification(element, rule) {
|
|
818
|
+
var _a;
|
|
819
|
+
if (!rule.anchored) {
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
const notifications = (_a = element.__abledom) == null ? void 0 : _a.notifications;
|
|
823
|
+
if (!notifications) {
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
const notification = notifications.get(rule);
|
|
827
|
+
if (notification) {
|
|
828
|
+
notification.dispose();
|
|
829
|
+
notifications.delete(rule);
|
|
830
|
+
}
|
|
831
|
+
if (notifications.size === 0) {
|
|
832
|
+
this._elementsWithNotifications.delete(element);
|
|
833
|
+
delete element.__abledom;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
_validate(elements) {
|
|
837
|
+
for (const id of this._changedElementIds) {
|
|
838
|
+
const dependingOnId = this._elementsDependingOnId.get(id);
|
|
839
|
+
if (dependingOnId) {
|
|
840
|
+
for (const element of dependingOnId) {
|
|
841
|
+
elements.add(element);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
elements.forEach((element) => {
|
|
846
|
+
var _a, _b, _c, _d, _e;
|
|
847
|
+
if (isAccessibilityAffectingElement(element) || ((_a = element.__abledom) == null ? void 0 : _a.notifications)) {
|
|
848
|
+
const dependsOnIds = /* @__PURE__ */ new Set();
|
|
849
|
+
for (const rule of this._rules) {
|
|
850
|
+
if (!rule.validate || ((_b = rule.accept) == null ? void 0 : _b.call(rule, element)) === false) {
|
|
851
|
+
continue;
|
|
852
|
+
}
|
|
853
|
+
if (ValidationRule.checkExceptions(rule, element)) {
|
|
854
|
+
continue;
|
|
855
|
+
}
|
|
856
|
+
const validationResult = (_c = rule.validate) == null ? void 0 : _c.call(rule, element);
|
|
857
|
+
if (validationResult == null ? void 0 : validationResult.notification) {
|
|
858
|
+
this._addNotification(rule, validationResult.notification);
|
|
859
|
+
const ids = validationResult.dependsOnIds;
|
|
860
|
+
if (ids) {
|
|
861
|
+
for (const id of ids) {
|
|
862
|
+
dependsOnIds.add(id);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
} else if ((_e = (_d = element.__abledom) == null ? void 0 : _d.notifications) == null ? void 0 : _e.has(rule)) {
|
|
866
|
+
this._removeNotification(element, rule);
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
this._processElementDependingOnIds(
|
|
870
|
+
element,
|
|
871
|
+
dependsOnIds.size === 0 ? null : dependsOnIds
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
}
|
|
876
|
+
_processElementDependingOnIds(element, ids) {
|
|
877
|
+
let dependsOnIds = this._dependantIdsByElement.get(element);
|
|
878
|
+
if (!ids && !dependsOnIds) {
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
if (!dependsOnIds) {
|
|
882
|
+
dependsOnIds = /* @__PURE__ */ new Set();
|
|
883
|
+
}
|
|
884
|
+
if (!ids) {
|
|
885
|
+
ids = /* @__PURE__ */ new Set();
|
|
886
|
+
}
|
|
887
|
+
for (const id of dependsOnIds) {
|
|
888
|
+
if (!ids.has(id)) {
|
|
889
|
+
const elements = this._elementsDependingOnId.get(id);
|
|
890
|
+
if (elements) {
|
|
891
|
+
elements.delete(element);
|
|
892
|
+
if (elements.size === 0) {
|
|
893
|
+
this._elementsDependingOnId.delete(id);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
for (const id of ids) {
|
|
899
|
+
if (!dependsOnIds.has(id)) {
|
|
900
|
+
dependsOnIds.add(id);
|
|
901
|
+
let elements = this._elementsDependingOnId.get(id);
|
|
902
|
+
if (!elements) {
|
|
903
|
+
elements = /* @__PURE__ */ new Set();
|
|
904
|
+
this._elementsDependingOnId.set(id, elements);
|
|
905
|
+
}
|
|
906
|
+
elements.add(element);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
if (dependsOnIds.size === 0) {
|
|
910
|
+
this._dependantIdsByElement.delete(element);
|
|
911
|
+
} else {
|
|
912
|
+
this._dependantIdsByElement.set(element, dependsOnIds);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
_remove(elements) {
|
|
916
|
+
elements.forEach((element) => {
|
|
917
|
+
var _a, _b;
|
|
918
|
+
const rules = [...((_b = (_a = element.__abledom) == null ? void 0 : _a.notifications) == null ? void 0 : _b.keys()) || []];
|
|
919
|
+
rules.forEach((rule) => this._removeNotification(element, rule));
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
addRule(rule) {
|
|
923
|
+
this._rules.push(rule);
|
|
924
|
+
}
|
|
925
|
+
removeRule(rule) {
|
|
926
|
+
var _a;
|
|
927
|
+
const index = this._rules.indexOf(rule);
|
|
928
|
+
if (index >= 0) {
|
|
929
|
+
const rule2 = this._rules[index];
|
|
930
|
+
this._rules.splice(index, 1);
|
|
931
|
+
(_a = rule2.stop) == null ? void 0 : _a.call(rule2);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
start() {
|
|
935
|
+
var _a, _b;
|
|
936
|
+
if (this._isStarted) {
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
this._isStarted = true;
|
|
940
|
+
for (const rule of this._rules) {
|
|
941
|
+
ValidationRule.init(rule, this._win, this._notifyAsync);
|
|
942
|
+
(_a = rule.start) == null ? void 0 : _a.call(rule);
|
|
943
|
+
}
|
|
944
|
+
(_b = this._startFunc) == null ? void 0 : _b.call(this);
|
|
945
|
+
}
|
|
946
|
+
dispose() {
|
|
947
|
+
var _a, _b;
|
|
948
|
+
this._win.document.addEventListener("focusin", this._onFocusIn, true);
|
|
949
|
+
this._win.document.addEventListener("focusout", this._onFocusOut, true);
|
|
950
|
+
this._remove(this._elementsWithNotifications);
|
|
951
|
+
this._elementsWithNotifications.clear();
|
|
952
|
+
this._dependantIdsByElement.clear();
|
|
953
|
+
this._elementsDependingOnId.clear();
|
|
954
|
+
this._idByElement.clear();
|
|
955
|
+
(_a = this._clearValidationTimeout) == null ? void 0 : _a.call(this);
|
|
956
|
+
for (const rule of this._rules) {
|
|
957
|
+
(_b = rule.stop) == null ? void 0 : _b.call(rule);
|
|
958
|
+
ValidationRule.dispose(rule);
|
|
959
|
+
}
|
|
960
|
+
this._rules = [];
|
|
961
|
+
if (this._startFunc) {
|
|
962
|
+
delete this._startFunc;
|
|
963
|
+
} else {
|
|
964
|
+
this._observer.disconnect();
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
};
|
|
968
|
+
|
|
969
|
+
// src/rules/atomic.ts
|
|
970
|
+
var AtomicRule = class extends ValidationRule {
|
|
971
|
+
constructor() {
|
|
972
|
+
super(...arguments);
|
|
973
|
+
__publicField(this, "type", 1 /* Error */);
|
|
974
|
+
__publicField(this, "name", "atomic");
|
|
975
|
+
__publicField(this, "anchored", true);
|
|
976
|
+
}
|
|
977
|
+
accept(element) {
|
|
978
|
+
return matchesSelector(element, focusableElementSelector);
|
|
979
|
+
}
|
|
980
|
+
validate(element) {
|
|
981
|
+
const parentAtomic = document.evaluate(
|
|
982
|
+
`ancestor::*[
|
|
983
|
+
@role = 'button' or
|
|
984
|
+
@role = 'checkbox' or
|
|
985
|
+
@role = 'link' or
|
|
986
|
+
@role = 'menuitem' or
|
|
987
|
+
@role = 'menuitemcheckbox' or
|
|
988
|
+
@role = 'menuitemradio' or
|
|
989
|
+
@role = 'option' or
|
|
990
|
+
@role = 'radio' or
|
|
991
|
+
@role = 'switch' or
|
|
992
|
+
@role = 'tab' or
|
|
993
|
+
@role = 'treeitem' or
|
|
994
|
+
self::a or
|
|
995
|
+
self::button or
|
|
996
|
+
self::input or
|
|
997
|
+
self::option or
|
|
998
|
+
self::textarea
|
|
999
|
+
][1]`,
|
|
1000
|
+
element,
|
|
1001
|
+
null,
|
|
1002
|
+
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
|
|
1003
|
+
null
|
|
1004
|
+
).snapshotItem(0);
|
|
1005
|
+
if (parentAtomic) {
|
|
1006
|
+
return {
|
|
1007
|
+
notification: {
|
|
1008
|
+
id: "focusable-in-atomic",
|
|
1009
|
+
message: "Focusable element inside atomic focusable.",
|
|
1010
|
+
element,
|
|
1011
|
+
rel: parentAtomic
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
return null;
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
|
|
1019
|
+
// src/rules/label.ts
|
|
1020
|
+
var _keyboardEditableInputTypes = /* @__PURE__ */ new Set([
|
|
1021
|
+
"text",
|
|
1022
|
+
"password",
|
|
1023
|
+
"email",
|
|
1024
|
+
"search",
|
|
1025
|
+
"tel",
|
|
1026
|
+
"url",
|
|
1027
|
+
"number",
|
|
1028
|
+
"date",
|
|
1029
|
+
"month",
|
|
1030
|
+
"week",
|
|
1031
|
+
"time",
|
|
1032
|
+
"datetime-local"
|
|
1033
|
+
]);
|
|
1034
|
+
var FocusableElementLabelRule = class extends ValidationRule {
|
|
1035
|
+
constructor() {
|
|
1036
|
+
super(...arguments);
|
|
1037
|
+
__publicField(this, "type", 1 /* Error */);
|
|
1038
|
+
__publicField(this, "name", "FocusableElementLabelRule");
|
|
1039
|
+
__publicField(this, "anchored", true);
|
|
1040
|
+
}
|
|
1041
|
+
_isAriaHidden(element) {
|
|
1042
|
+
return document.evaluate(
|
|
1043
|
+
`ancestor-or-self::*[@aria-hidden = 'true' or @hidden]`,
|
|
1044
|
+
element,
|
|
1045
|
+
null,
|
|
1046
|
+
XPathResult.BOOLEAN_TYPE,
|
|
1047
|
+
null
|
|
1048
|
+
).booleanValue;
|
|
1049
|
+
}
|
|
1050
|
+
_hasLabel(element) {
|
|
1051
|
+
var _a, _b;
|
|
1052
|
+
const labels = element.labels;
|
|
1053
|
+
if (labels && labels.length > 0) {
|
|
1054
|
+
for (let i = 0; i < labels.length; i++) {
|
|
1055
|
+
const label = labels[i];
|
|
1056
|
+
if (label.innerText.trim()) {
|
|
1057
|
+
return true;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
if (element.tagName === "IMG") {
|
|
1062
|
+
if (element.alt.trim()) {
|
|
1063
|
+
return true;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
const labelNodes = document.evaluate(
|
|
1067
|
+
`(
|
|
1068
|
+
.//@aria-label |
|
|
1069
|
+
.//text() |
|
|
1070
|
+
.//@title |
|
|
1071
|
+
.//img/@alt |
|
|
1072
|
+
.//input[@type = 'image']/@alt |
|
|
1073
|
+
.//input[@type != 'hidden'][@type = 'submit' or @type = 'reset' or @type = 'button']/@value
|
|
1074
|
+
)[not(ancestor-or-self::*[@aria-hidden = 'true' or @hidden])]`,
|
|
1075
|
+
element,
|
|
1076
|
+
null,
|
|
1077
|
+
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
|
|
1078
|
+
null
|
|
1079
|
+
);
|
|
1080
|
+
for (let i = 0; i < labelNodes.snapshotLength; i++) {
|
|
1081
|
+
const val = (_b = (_a = labelNodes.snapshotItem(i)) == null ? void 0 : _a.nodeValue) == null ? void 0 : _b.trim();
|
|
1082
|
+
if (val) {
|
|
1083
|
+
return true;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
return false;
|
|
1087
|
+
}
|
|
1088
|
+
accept(element) {
|
|
1089
|
+
return matchesSelector(element, focusableElementSelector);
|
|
1090
|
+
}
|
|
1091
|
+
validate(element) {
|
|
1092
|
+
var _a, _b;
|
|
1093
|
+
if (element.tagName === "INPUT") {
|
|
1094
|
+
const type = element.type;
|
|
1095
|
+
if (type === "hidden") {
|
|
1096
|
+
return null;
|
|
1097
|
+
}
|
|
1098
|
+
if (_keyboardEditableInputTypes.has(type)) {
|
|
1099
|
+
return null;
|
|
1100
|
+
}
|
|
1101
|
+
if (type === "image") {
|
|
1102
|
+
if (element.alt.trim()) {
|
|
1103
|
+
return null;
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
if (type === "submit" || type === "reset" || type === "button") {
|
|
1107
|
+
if (element.value.trim()) {
|
|
1108
|
+
return null;
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
if (this._isAriaHidden(element)) {
|
|
1113
|
+
return null;
|
|
1114
|
+
}
|
|
1115
|
+
if (this._hasLabel(element)) {
|
|
1116
|
+
return null;
|
|
1117
|
+
}
|
|
1118
|
+
const labelledByNodes = document.evaluate(
|
|
1119
|
+
`.//@aria-labelledby[not(ancestor-or-self::*[@aria-hidden = 'true' or @hidden])]`,
|
|
1120
|
+
element,
|
|
1121
|
+
null,
|
|
1122
|
+
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
|
|
1123
|
+
null
|
|
1124
|
+
);
|
|
1125
|
+
const labelledByValues = [];
|
|
1126
|
+
for (let i = 0; i < labelledByNodes.snapshotLength; i++) {
|
|
1127
|
+
const val = (_b = (_a = labelledByNodes.snapshotItem(i)) == null ? void 0 : _a.value) == null ? void 0 : _b.trim().split(" ");
|
|
1128
|
+
if (val == null ? void 0 : val.length) {
|
|
1129
|
+
labelledByValues.push(...val);
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
for (const id of labelledByValues) {
|
|
1133
|
+
const labelElement = document.getElementById(id);
|
|
1134
|
+
if (labelElement && this._hasLabel(labelElement)) {
|
|
1135
|
+
return {
|
|
1136
|
+
dependsOnIds: new Set(labelledByValues)
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
return {
|
|
1141
|
+
notification: isElementVisible(element) ? {
|
|
1142
|
+
id: "focusable-element-label",
|
|
1143
|
+
message: "Focusable element must have a non-empty text label.",
|
|
1144
|
+
element
|
|
1145
|
+
} : void 0,
|
|
1146
|
+
dependsOnIds: new Set(labelledByValues)
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
|
|
1151
|
+
// src/rules/existingid.ts
|
|
1152
|
+
var ExistingIdRule = class extends ValidationRule {
|
|
1153
|
+
constructor() {
|
|
1154
|
+
super(...arguments);
|
|
1155
|
+
__publicField(this, "type", 1 /* Error */);
|
|
1156
|
+
__publicField(this, "name", "existing-id");
|
|
1157
|
+
__publicField(this, "anchored", true);
|
|
1158
|
+
}
|
|
1159
|
+
accept(element) {
|
|
1160
|
+
return element.hasAttribute("aria-labelledby") || element.hasAttribute("aria-describedby") || element.tagName === "LABEL" && !!element.htmlFor;
|
|
1161
|
+
}
|
|
1162
|
+
validate(element) {
|
|
1163
|
+
var _a, _b;
|
|
1164
|
+
const ids = [
|
|
1165
|
+
...((_a = element.getAttribute("aria-labelledby")) == null ? void 0 : _a.split(" ")) || [],
|
|
1166
|
+
...((_b = element.getAttribute("aria-describedby")) == null ? void 0 : _b.split(" ")) || [],
|
|
1167
|
+
...element.tagName === "LABEL" ? [element.htmlFor] : []
|
|
1168
|
+
].filter((id) => !!id);
|
|
1169
|
+
if (ids.length === 0) {
|
|
1170
|
+
return null;
|
|
1171
|
+
}
|
|
1172
|
+
for (const id of ids) {
|
|
1173
|
+
if (document.getElementById(id)) {
|
|
1174
|
+
return {
|
|
1175
|
+
dependsOnIds: new Set(ids)
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
return {
|
|
1180
|
+
notification: {
|
|
1181
|
+
id: "missing-id",
|
|
1182
|
+
message: `Elements with referenced ids do not extist.`,
|
|
1183
|
+
element
|
|
1184
|
+
},
|
|
1185
|
+
dependsOnIds: new Set(ids)
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
};
|
|
1189
|
+
|
|
1190
|
+
// src/rules/focuslost.ts
|
|
1191
|
+
var FocusLostRule = class extends ValidationRule {
|
|
1192
|
+
constructor() {
|
|
1193
|
+
super(...arguments);
|
|
1194
|
+
__publicField(this, "type", 1 /* Error */);
|
|
1195
|
+
__publicField(this, "name", "focus-lost");
|
|
1196
|
+
__publicField(this, "anchored", false);
|
|
1197
|
+
__publicField(this, "_focusLostTimeout", 2e3);
|
|
1198
|
+
// For now reporting lost focus after 2 seconds of it being lost.
|
|
1199
|
+
__publicField(this, "_clearScheduledFocusLost");
|
|
1200
|
+
__publicField(this, "_focusedElement");
|
|
1201
|
+
__publicField(this, "_focusedElementPosition");
|
|
1202
|
+
__publicField(this, "_lastFocusStack");
|
|
1203
|
+
__publicField(this, "_lastBlurStack");
|
|
1204
|
+
__publicField(this, "_mouseEventTimer");
|
|
1205
|
+
__publicField(this, "_releaseMouseEvent");
|
|
1206
|
+
}
|
|
1207
|
+
_serializeElementPosition(element) {
|
|
1208
|
+
const position = [];
|
|
1209
|
+
const parentElement = element.parentElement;
|
|
1210
|
+
if (!parentElement) {
|
|
1211
|
+
return position;
|
|
1212
|
+
}
|
|
1213
|
+
for (let el = parentElement; el; el = el.parentElement) {
|
|
1214
|
+
const tagName = el.tagName.toLowerCase();
|
|
1215
|
+
position.push(tagName);
|
|
1216
|
+
}
|
|
1217
|
+
return position;
|
|
1218
|
+
}
|
|
1219
|
+
focused(event) {
|
|
1220
|
+
var _a;
|
|
1221
|
+
const target = event.target;
|
|
1222
|
+
(_a = this._clearScheduledFocusLost) == null ? void 0 : _a.call(this);
|
|
1223
|
+
if (target) {
|
|
1224
|
+
this._lastFocusStack = getStackTrace();
|
|
1225
|
+
this._focusedElement = target;
|
|
1226
|
+
this._focusedElementPosition = this._serializeElementPosition(target);
|
|
1227
|
+
}
|
|
1228
|
+
return null;
|
|
1229
|
+
}
|
|
1230
|
+
blurred(event) {
|
|
1231
|
+
var _a;
|
|
1232
|
+
const target = event.target;
|
|
1233
|
+
const win = this.window;
|
|
1234
|
+
(_a = this._clearScheduledFocusLost) == null ? void 0 : _a.call(this);
|
|
1235
|
+
if (!target || !win || event.relatedTarget || this._mouseEventTimer) {
|
|
1236
|
+
return null;
|
|
1237
|
+
}
|
|
1238
|
+
const targetPosition = this._focusedElement === target ? this._focusedElementPosition : void 0;
|
|
1239
|
+
this._lastBlurStack = getStackTrace();
|
|
1240
|
+
this._focusedElement = void 0;
|
|
1241
|
+
this._focusedElementPosition = void 0;
|
|
1242
|
+
const focusLostTimer = win.setTimeout(() => {
|
|
1243
|
+
delete this._clearScheduledFocusLost;
|
|
1244
|
+
if (win.document.body && (!win.document.activeElement || win.document.activeElement === win.document.body) && (!win.document.body.contains(target) || !isElementVisible(target))) {
|
|
1245
|
+
this.notify({
|
|
1246
|
+
element: target,
|
|
1247
|
+
id: "focus-lost",
|
|
1248
|
+
message: "Focus lost.",
|
|
1249
|
+
stack: this._lastBlurStack,
|
|
1250
|
+
relStack: this._lastFocusStack,
|
|
1251
|
+
position: targetPosition || []
|
|
1252
|
+
});
|
|
1253
|
+
}
|
|
1254
|
+
}, this._focusLostTimeout);
|
|
1255
|
+
this._clearScheduledFocusLost = () => {
|
|
1256
|
+
delete this._clearScheduledFocusLost;
|
|
1257
|
+
win.clearTimeout(focusLostTimer);
|
|
1258
|
+
};
|
|
1259
|
+
return null;
|
|
1260
|
+
}
|
|
1261
|
+
start() {
|
|
1262
|
+
const win = this.window;
|
|
1263
|
+
if (!win) {
|
|
1264
|
+
return;
|
|
1265
|
+
}
|
|
1266
|
+
const onMouseEvent = () => {
|
|
1267
|
+
if (!this._mouseEventTimer) {
|
|
1268
|
+
this._mouseEventTimer = win.setTimeout(() => {
|
|
1269
|
+
this._mouseEventTimer = void 0;
|
|
1270
|
+
}, 0);
|
|
1271
|
+
}
|
|
1272
|
+
};
|
|
1273
|
+
win.addEventListener("mousedown", onMouseEvent, true);
|
|
1274
|
+
win.addEventListener("mouseup", onMouseEvent, true);
|
|
1275
|
+
win.addEventListener("mousemove", onMouseEvent, true);
|
|
1276
|
+
this._releaseMouseEvent = () => {
|
|
1277
|
+
delete this._releaseMouseEvent;
|
|
1278
|
+
if (this._mouseEventTimer) {
|
|
1279
|
+
win.clearTimeout(this._mouseEventTimer);
|
|
1280
|
+
delete this._mouseEventTimer;
|
|
1281
|
+
}
|
|
1282
|
+
win.removeEventListener("mousedown", onMouseEvent, true);
|
|
1283
|
+
win.removeEventListener("mouseup", onMouseEvent, true);
|
|
1284
|
+
win.removeEventListener("mousemove", onMouseEvent, true);
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
stop() {
|
|
1288
|
+
var _a, _b;
|
|
1289
|
+
(_a = this._releaseMouseEvent) == null ? void 0 : _a.call(this);
|
|
1290
|
+
(_b = this._clearScheduledFocusLost) == null ? void 0 : _b.call(this);
|
|
1291
|
+
this._focusedElement = void 0;
|
|
1292
|
+
this._focusedElementPosition = void 0;
|
|
1293
|
+
this._lastFocusStack = void 0;
|
|
1294
|
+
this._lastBlurStack = void 0;
|
|
1295
|
+
}
|
|
1296
|
+
};
|
|
1297
|
+
|
|
1298
|
+
// src/rules/badfocus.ts
|
|
1299
|
+
var BadFocusRule = class extends ValidationRule {
|
|
1300
|
+
constructor() {
|
|
1301
|
+
super(...arguments);
|
|
1302
|
+
__publicField(this, "type", 1 /* Error */);
|
|
1303
|
+
__publicField(this, "name", "bad-focus");
|
|
1304
|
+
__publicField(this, "anchored", false);
|
|
1305
|
+
__publicField(this, "_lastFocusStack");
|
|
1306
|
+
__publicField(this, "_lastBlurStack");
|
|
1307
|
+
__publicField(this, "_clearCheckTimer");
|
|
1308
|
+
}
|
|
1309
|
+
focused() {
|
|
1310
|
+
this._lastFocusStack = getStackTrace();
|
|
1311
|
+
return null;
|
|
1312
|
+
}
|
|
1313
|
+
blurred() {
|
|
1314
|
+
var _a;
|
|
1315
|
+
const win = this.window;
|
|
1316
|
+
if (!win) {
|
|
1317
|
+
return null;
|
|
1318
|
+
}
|
|
1319
|
+
this._lastBlurStack = getStackTrace();
|
|
1320
|
+
(_a = this._clearCheckTimer) == null ? void 0 : _a.call(this);
|
|
1321
|
+
const checkTimer = win.setTimeout(() => {
|
|
1322
|
+
delete this._clearCheckTimer;
|
|
1323
|
+
if (document.activeElement && !isElementVisible(document.activeElement)) {
|
|
1324
|
+
this.notify({
|
|
1325
|
+
id: "bad-focus",
|
|
1326
|
+
message: "Focused stolen by invisible element.",
|
|
1327
|
+
element: document.activeElement,
|
|
1328
|
+
stack: this._lastBlurStack,
|
|
1329
|
+
relStack: this._lastFocusStack
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
}, 100);
|
|
1333
|
+
this._clearCheckTimer = () => {
|
|
1334
|
+
delete this._clearCheckTimer;
|
|
1335
|
+
win.clearTimeout(checkTimer);
|
|
1336
|
+
};
|
|
1337
|
+
return null;
|
|
1338
|
+
}
|
|
1339
|
+
stop() {
|
|
1340
|
+
var _a;
|
|
1341
|
+
(_a = this._clearCheckTimer) == null ? void 0 : _a.call(this);
|
|
1342
|
+
this._clearCheckTimer = void 0;
|
|
1343
|
+
this._lastFocusStack = void 0;
|
|
1344
|
+
this._lastBlurStack = void 0;
|
|
1345
|
+
}
|
|
1346
|
+
};
|
|
1347
|
+
|
|
1348
|
+
// src/rules/find.ts
|
|
1349
|
+
var FindElementRule = class extends ValidationRule {
|
|
1350
|
+
constructor() {
|
|
1351
|
+
super(...arguments);
|
|
1352
|
+
__publicField(this, "type", 2 /* Warning */);
|
|
1353
|
+
__publicField(this, "name", "find-element");
|
|
1354
|
+
__publicField(this, "anchored", true);
|
|
1355
|
+
__publicField(this, "_conditions", {});
|
|
1356
|
+
}
|
|
1357
|
+
addCondition(name, condition) {
|
|
1358
|
+
this._conditions[name] = condition;
|
|
1359
|
+
}
|
|
1360
|
+
removeCondition(name) {
|
|
1361
|
+
delete this._conditions[name];
|
|
1362
|
+
}
|
|
1363
|
+
validate(element) {
|
|
1364
|
+
for (const name of Object.keys(this._conditions)) {
|
|
1365
|
+
if (this._conditions[name](element)) {
|
|
1366
|
+
return {
|
|
1367
|
+
notification: {
|
|
1368
|
+
id: "find-element",
|
|
1369
|
+
message: `Element found: ${name}.`,
|
|
1370
|
+
element
|
|
1371
|
+
}
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1375
|
+
return null;
|
|
1376
|
+
}
|
|
1377
|
+
};
|
|
1378
|
+
|
|
1379
|
+
// src/rules/notify.ts
|
|
1380
|
+
var CustomNotifyRule = class extends ValidationRule {
|
|
1381
|
+
constructor() {
|
|
1382
|
+
super(...arguments);
|
|
1383
|
+
__publicField(this, "type", 3 /* Info */);
|
|
1384
|
+
__publicField(this, "name", "custom-notify");
|
|
1385
|
+
__publicField(this, "anchored", false);
|
|
1386
|
+
}
|
|
1387
|
+
customNotify(message, element) {
|
|
1388
|
+
this.notify({
|
|
1389
|
+
id: "custom-notify",
|
|
1390
|
+
message,
|
|
1391
|
+
element
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
export {
|
|
1396
|
+
AbleDOM,
|
|
1397
|
+
AtomicRule,
|
|
1398
|
+
BadFocusRule,
|
|
1399
|
+
CustomNotifyRule,
|
|
1400
|
+
ExistingIdRule,
|
|
1401
|
+
FindElementRule,
|
|
1402
|
+
FocusLostRule,
|
|
1403
|
+
FocusableElementLabelRule,
|
|
1404
|
+
ValidationRule,
|
|
1405
|
+
ValidationRuleType,
|
|
1406
|
+
hasAccessibilityAttribute,
|
|
1407
|
+
isAccessibilityAffectingElement,
|
|
1408
|
+
isDisplayNone,
|
|
1409
|
+
isElementVisible,
|
|
1410
|
+
matchesSelector
|
|
1411
|
+
};
|
|
1412
|
+
/*!
|
|
1413
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
1414
|
+
* Licensed under the MIT License.
|
|
1415
|
+
*/
|
|
1416
|
+
//# sourceMappingURL=index.js.map
|