abledom 0.0.1 → 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/dist/esm/index.js CHANGED
@@ -2,8 +2,63 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
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
+
5
60
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/ui.css
6
- 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-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\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";
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";
7
62
 
8
63
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/close.svg
9
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';
@@ -17,27 +72,67 @@ var log_default = '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" s
17
72
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/reveal.svg
18
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>';
19
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
+
20
96
  // src/ui/ui.ts
97
+ var pressedClass = "pressed";
21
98
  var _NotificationUI = class _NotificationUI {
22
- constructor(element, error) {
99
+ constructor(win, rule) {
100
+ __publicField(this, "_win");
23
101
  __publicField(this, "_wrapper");
24
- var _a;
25
- const wrapper = this._wrapper = document.createElement(
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(
26
111
  "div"
27
112
  );
28
- const win = element.ownerDocument.defaultView;
29
- if (!win) {
30
- return;
31
- }
32
113
  if (!_NotificationUI._highlight) {
33
114
  _NotificationUI._highlight = new ElementHighlighter(win);
34
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;
35
130
  wrapper.__abledomui = true;
36
131
  wrapper.innerHTML = `
37
- <div class="abledom-notification-container"><div class="abledom-notification">
132
+ <div class="abledom-notification-container"><div class="abledom-notification${rule.type === 2 /* Warning */ ? " abledom-notification_warning" : rule.type === 3 /* Info */ ? " abledom-notification_info" : ""}">
38
133
  <button class="button" title="Log to Console">${log_default}</button>
39
134
  <button class="button" title="Reveal in Elements panel">${reveal_default}</button>
40
- ${error.message}
135
+ ${notification.message}
41
136
  <a href class="button close" href="/" title="Open help" target="_blank">${help_default}</a>
42
137
  <button class="button close" class="close" title="Hide">${close_default}</button>
43
138
  </div></div>`;
@@ -48,16 +143,18 @@ var _NotificationUI = class _NotificationUI {
48
143
  const closeButton = buttons[2];
49
144
  logButton.onclick = () => {
50
145
  console.error(
51
- "AbleDOM violation: ",
52
- "\nerror:",
53
- error.message,
146
+ "AbleDOM: ",
147
+ "\nmessage:",
148
+ notification.message,
54
149
  "\nelement:",
55
150
  element,
56
- ...error.rel ? ["\nrelative:", error.rel] : []
151
+ ...notification.rel ? ["\nrelative:", notification.rel] : [],
152
+ "\nnotification:",
153
+ notification
57
154
  );
58
155
  };
59
- const hasDevTools = !!((_a = win.__ableDOMDevtools) == null ? void 0 : _a.revealElement);
60
- if (hasDevTools && win.document.body.contains(element)) {
156
+ const hasDevTools = !!((_a = win.__ableDOMDevtools) == null ? void 0 : _a.revealElement) && false;
157
+ if (hasDevTools && element && win.document.body.contains(element)) {
61
158
  revealButton.onclick = () => {
62
159
  var _a2;
63
160
  const revealElement = (_a2 = win.__ableDOMDevtools) == null ? void 0 : _a2.revealElement;
@@ -73,51 +170,231 @@ var _NotificationUI = class _NotificationUI {
73
170
  }
74
171
  closeButton.onclick = () => {
75
172
  var _a2;
76
- wrapper.style.display = "none";
173
+ this.toggle(false);
77
174
  (_a2 = _NotificationUI._highlight) == null ? void 0 : _a2.hide();
78
175
  };
79
176
  container.onmouseover = () => {
80
177
  var _a2;
81
- (_a2 = _NotificationUI._highlight) == null ? void 0 : _a2.highlight(element);
178
+ element && ((_a2 = _NotificationUI._highlight) == null ? void 0 : _a2.highlight(element));
82
179
  };
83
180
  container.onmouseout = () => {
84
181
  var _a2;
85
182
  (_a2 = _NotificationUI._highlight) == null ? void 0 : _a2.hide();
86
183
  };
87
184
  }
88
- static getElement(instance) {
89
- return instance._wrapper;
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";
90
195
  }
91
196
  dispose() {
197
+ var _a;
92
198
  this._wrapper.remove();
199
+ (_a = _NotificationUI._notificationsUI) == null ? void 0 : _a.removeNotification(this);
93
200
  }
94
201
  };
202
+ __publicField(_NotificationUI, "_notificationsUI");
95
203
  __publicField(_NotificationUI, "_highlight");
96
204
  var NotificationUI = _NotificationUI;
97
205
  var NotificationsUI = class {
98
206
  constructor(win) {
99
- // private _window: Window;
100
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);
101
218
  __publicField(this, "_notifications", /* @__PURE__ */ new Set());
102
- const container = this._container = document.createElement("div");
219
+ var _a;
220
+ const container = this._container = win.document.createElement("div");
103
221
  container.__abledomui = true;
104
222
  container.id = "abledom-report";
105
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
+ }
106
290
  win.document.body.appendChild(container);
107
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
+ }
108
362
  addNotification(notification) {
109
363
  if (this._notifications.has(notification)) {
110
364
  return;
111
365
  }
366
+ if (this._isMuted) {
367
+ notification.toggle(false, true);
368
+ }
112
369
  this._notifications.add(notification);
113
- this._container.appendChild(NotificationUI.getElement(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();
114
378
  }
115
379
  removeNotification(notification) {
116
380
  if (!this._notifications.has(notification)) {
117
381
  return;
118
382
  }
119
383
  this._notifications.delete(notification);
120
- this._container.removeChild(NotificationUI.getElement(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();
121
398
  }
122
399
  };
123
400
  var ElementHighlighter = class {
@@ -340,91 +617,13 @@ function getStackTrace() {
340
617
  }
341
618
  }
342
619
 
343
- // src/rules/base.ts
344
- var ValidationRule = class {
345
- constructor() {
346
- __publicField(this, "_window");
347
- __publicField(this, "_exceptions", []);
348
- }
349
- static setWindow(instance, window2) {
350
- instance._window = window2;
351
- }
352
- static checkExceptions(instance, element) {
353
- for (const exception of instance._exceptions) {
354
- if (exception(element)) {
355
- return true;
356
- }
357
- }
358
- return false;
359
- }
360
- addException(checkException) {
361
- var _a;
362
- (_a = this._exceptions) == null ? void 0 : _a.push(checkException);
363
- }
364
- removeException(checkException) {
365
- const index = this._exceptions.indexOf(checkException);
366
- if (index >= 0) {
367
- this._exceptions.splice(index, 1);
368
- }
369
- }
370
- /**
371
- * Window is set when the rule is added to the AbleDOM instance.
372
- */
373
- get window() {
374
- return this._window;
375
- }
376
- };
377
-
378
620
  // src/core.ts
379
- var _ValidationErrorReport = class _ValidationErrorReport {
380
- constructor(element, error, onHide) {
381
- this.element = element;
382
- this.error = error;
383
- __publicField(this, "_notification");
384
- __publicField(this, "_onHide");
385
- this._onHide = onHide;
386
- this.report();
387
- }
388
- update(error) {
389
- this.error = error;
390
- this.report();
391
- }
392
- report() {
393
- if (!_ValidationErrorReport._notificationsUI) {
394
- _ValidationErrorReport._notificationsUI = new NotificationsUI(window);
395
- }
396
- let notification = this._notification;
397
- if (notification) {
398
- } else {
399
- notification = this._notification = new NotificationUI(
400
- this.element,
401
- this.error
402
- );
403
- }
404
- _ValidationErrorReport._notificationsUI.addNotification(notification);
405
- }
406
- hide() {
407
- var _a;
408
- (_a = this._onHide) == null ? void 0 : _a.call(this);
409
- }
410
- remove() {
411
- var _a;
412
- if (this._notification) {
413
- (_a = _ValidationErrorReport._notificationsUI) == null ? void 0 : _a.removeNotification(
414
- this._notification
415
- );
416
- delete this._notification;
417
- }
418
- }
419
- };
420
- __publicField(_ValidationErrorReport, "_notificationsUI");
421
- var ValidationErrorReport = _ValidationErrorReport;
422
621
  var AbleDOM = class {
423
622
  constructor(win) {
424
- __publicField(this, "_window");
623
+ __publicField(this, "_win");
425
624
  __publicField(this, "_observer");
426
625
  __publicField(this, "_clearValidationTimeout");
427
- __publicField(this, "_elementsWithErrors", /* @__PURE__ */ new Set());
626
+ __publicField(this, "_elementsWithNotifications", /* @__PURE__ */ new Set());
428
627
  __publicField(this, "_changedElementIds", /* @__PURE__ */ new Set());
429
628
  __publicField(this, "_elementsDependingOnId", /* @__PURE__ */ new Map());
430
629
  __publicField(this, "_dependantIdsByElement", /* @__PURE__ */ new Map());
@@ -439,19 +638,10 @@ var AbleDOM = class {
439
638
  return;
440
639
  }
441
640
  for (const rule of this._rules) {
442
- (_a = rule.focused) == null ? void 0 : _a.call(rule, event).then(
443
- (focusError) => {
444
- if (focusError) {
445
- this._addValidationError(
446
- focusError.element,
447
- rule,
448
- focusError.error
449
- );
450
- }
451
- },
452
- () => {
453
- }
454
- );
641
+ const focusNotification = (_a = rule.focused) == null ? void 0 : _a.call(rule, event);
642
+ if (focusNotification) {
643
+ this._addNotification(rule, focusNotification);
644
+ }
455
645
  }
456
646
  });
457
647
  __publicField(this, "_onFocusOut", (event) => {
@@ -461,22 +651,16 @@ var AbleDOM = class {
461
651
  return;
462
652
  }
463
653
  for (const rule of this._rules) {
464
- (_a = rule.blurred) == null ? void 0 : _a.call(rule, event).then(
465
- (focusError) => {
466
- if (focusError) {
467
- this._addValidationError(
468
- focusError.element,
469
- rule,
470
- focusError.error
471
- );
472
- }
473
- },
474
- () => {
475
- }
476
- );
654
+ const blurNotification = (_a = rule.blurred) == null ? void 0 : _a.call(rule, event);
655
+ if (blurNotification) {
656
+ this._addNotification(rule, blurNotification);
657
+ }
477
658
  }
478
659
  });
479
- this._window = win;
660
+ __publicField(this, "_notifyAsync", (rule, notification) => {
661
+ this._addNotification(rule, notification);
662
+ });
663
+ this._win = win;
480
664
  const _elementsToValidate = /* @__PURE__ */ new Set();
481
665
  const _elementsToRemove = /* @__PURE__ */ new Set();
482
666
  win.document.addEventListener("focusin", this._onFocusIn, true);
@@ -545,7 +729,7 @@ var AbleDOM = class {
545
729
  };
546
730
  function lookUp(node) {
547
731
  for (let n = node; n; n = n.parentNode) {
548
- addTarget(n, false);
732
+ addTarget(n, _elementsToRemove.has(node));
549
733
  }
550
734
  }
551
735
  function findTargets(node, removed) {
@@ -603,49 +787,49 @@ var AbleDOM = class {
603
787
  this._idByElement.delete(element);
604
788
  }
605
789
  }
606
- _addValidationError(element, rule, error) {
607
- if (!error) {
608
- this._removeElementError(element, rule);
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);
609
794
  return;
610
795
  }
611
- if (rule.anchored) {
796
+ let notificationUI;
797
+ if (rule.anchored && element) {
612
798
  let abledomOnElement = element.__abledom;
613
799
  if (!abledomOnElement) {
614
800
  abledomOnElement = element.__abledom = {};
615
801
  }
616
- let errors = abledomOnElement.errors;
617
- if (!errors) {
618
- errors = abledomOnElement.errors = /* @__PURE__ */ new Map();
802
+ let notifications = abledomOnElement.notifications;
803
+ if (!notifications) {
804
+ notifications = abledomOnElement.notifications = /* @__PURE__ */ new Map();
619
805
  }
620
- const report = errors.get(rule);
621
- if (report) {
622
- report.update(error);
623
- } else {
624
- errors.set(rule, new ValidationErrorReport(element, error));
806
+ notificationUI = notifications.get(rule);
807
+ if (!notificationUI) {
808
+ notificationUI = new NotificationUI(this._win, rule);
809
+ notifications.set(rule, notificationUI);
625
810
  }
626
- this._elementsWithErrors.add(element);
811
+ this._elementsWithNotifications.add(element);
627
812
  } else {
628
- const report = new ValidationErrorReport(element, error, () => {
629
- report.remove();
630
- });
813
+ notificationUI = new NotificationUI(this._win, rule);
631
814
  }
815
+ notificationUI.update(notification);
632
816
  }
633
- _removeElementError(element, rule) {
817
+ _removeNotification(element, rule) {
634
818
  var _a;
635
819
  if (!rule.anchored) {
636
820
  return;
637
821
  }
638
- const errors = (_a = element.__abledom) == null ? void 0 : _a.errors;
639
- if (!errors) {
822
+ const notifications = (_a = element.__abledom) == null ? void 0 : _a.notifications;
823
+ if (!notifications) {
640
824
  return;
641
825
  }
642
- const report = errors.get(rule);
643
- if (report) {
644
- report.remove();
645
- errors.delete(rule);
826
+ const notification = notifications.get(rule);
827
+ if (notification) {
828
+ notification.dispose();
829
+ notifications.delete(rule);
646
830
  }
647
- if (errors.size === 0) {
648
- this._elementsWithErrors.delete(element);
831
+ if (notifications.size === 0) {
832
+ this._elementsWithNotifications.delete(element);
649
833
  delete element.__abledom;
650
834
  }
651
835
  }
@@ -660,26 +844,26 @@ var AbleDOM = class {
660
844
  }
661
845
  elements.forEach((element) => {
662
846
  var _a, _b, _c, _d, _e;
663
- if (isAccessibilityAffectingElement(element) || ((_a = element.__abledom) == null ? void 0 : _a.errors)) {
847
+ if (isAccessibilityAffectingElement(element) || ((_a = element.__abledom) == null ? void 0 : _a.notifications)) {
664
848
  const dependsOnIds = /* @__PURE__ */ new Set();
665
849
  for (const rule of this._rules) {
666
- if (((_b = rule.accept) == null ? void 0 : _b.call(rule, element)) === false) {
850
+ if (!rule.validate || ((_b = rule.accept) == null ? void 0 : _b.call(rule, element)) === false) {
667
851
  continue;
668
852
  }
669
853
  if (ValidationRule.checkExceptions(rule, element)) {
670
854
  continue;
671
855
  }
672
856
  const validationResult = (_c = rule.validate) == null ? void 0 : _c.call(rule, element);
673
- if (validationResult) {
674
- this._addValidationError(element, rule, validationResult.error);
857
+ if (validationResult == null ? void 0 : validationResult.notification) {
858
+ this._addNotification(rule, validationResult.notification);
675
859
  const ids = validationResult.dependsOnIds;
676
860
  if (ids) {
677
861
  for (const id of ids) {
678
862
  dependsOnIds.add(id);
679
863
  }
680
864
  }
681
- } else if ((_e = (_d = element.__abledom) == null ? void 0 : _d.errors) == null ? void 0 : _e.has(rule)) {
682
- this._removeElementError(element, rule);
865
+ } else if ((_e = (_d = element.__abledom) == null ? void 0 : _d.notifications) == null ? void 0 : _e.has(rule)) {
866
+ this._removeNotification(element, rule);
683
867
  }
684
868
  }
685
869
  this._processElementDependingOnIds(
@@ -731,8 +915,8 @@ var AbleDOM = class {
731
915
  _remove(elements) {
732
916
  elements.forEach((element) => {
733
917
  var _a, _b;
734
- const rules = [...((_b = (_a = element.__abledom) == null ? void 0 : _a.errors) == null ? void 0 : _b.keys()) || []];
735
- rules.forEach((rule) => this._removeElementError(element, rule));
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));
736
920
  });
737
921
  }
738
922
  addRule(rule) {
@@ -754,23 +938,24 @@ var AbleDOM = class {
754
938
  }
755
939
  this._isStarted = true;
756
940
  for (const rule of this._rules) {
757
- ValidationRule.setWindow(rule, this._window);
941
+ ValidationRule.init(rule, this._win, this._notifyAsync);
758
942
  (_a = rule.start) == null ? void 0 : _a.call(rule);
759
943
  }
760
944
  (_b = this._startFunc) == null ? void 0 : _b.call(this);
761
945
  }
762
946
  dispose() {
763
947
  var _a, _b;
764
- this._window.document.addEventListener("focusin", this._onFocusIn, true);
765
- this._window.document.addEventListener("focusout", this._onFocusOut, true);
766
- this._remove(this._elementsWithErrors);
767
- this._elementsWithErrors.clear();
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();
768
952
  this._dependantIdsByElement.clear();
769
953
  this._elementsDependingOnId.clear();
770
954
  this._idByElement.clear();
771
955
  (_a = this._clearValidationTimeout) == null ? void 0 : _a.call(this);
772
956
  for (const rule of this._rules) {
773
957
  (_b = rule.stop) == null ? void 0 : _b.call(rule);
958
+ ValidationRule.dispose(rule);
774
959
  }
775
960
  this._rules = [];
776
961
  if (this._startFunc) {
@@ -785,6 +970,7 @@ var AbleDOM = class {
785
970
  var AtomicRule = class extends ValidationRule {
786
971
  constructor() {
787
972
  super(...arguments);
973
+ __publicField(this, "type", 1 /* Error */);
788
974
  __publicField(this, "name", "atomic");
789
975
  __publicField(this, "anchored", true);
790
976
  }
@@ -818,9 +1004,10 @@ var AtomicRule = class extends ValidationRule {
818
1004
  ).snapshotItem(0);
819
1005
  if (parentAtomic) {
820
1006
  return {
821
- error: {
1007
+ notification: {
822
1008
  id: "focusable-in-atomic",
823
1009
  message: "Focusable element inside atomic focusable.",
1010
+ element,
824
1011
  rel: parentAtomic
825
1012
  }
826
1013
  };
@@ -847,6 +1034,7 @@ var _keyboardEditableInputTypes = /* @__PURE__ */ new Set([
847
1034
  var FocusableElementLabelRule = class extends ValidationRule {
848
1035
  constructor() {
849
1036
  super(...arguments);
1037
+ __publicField(this, "type", 1 /* Error */);
850
1038
  __publicField(this, "name", "FocusableElementLabelRule");
851
1039
  __publicField(this, "anchored", true);
852
1040
  }
@@ -950,9 +1138,10 @@ var FocusableElementLabelRule = class extends ValidationRule {
950
1138
  }
951
1139
  }
952
1140
  return {
953
- error: isElementVisible(element) ? {
1141
+ notification: isElementVisible(element) ? {
954
1142
  id: "focusable-element-label",
955
- message: "Focusable element must have a non-empty text label."
1143
+ message: "Focusable element must have a non-empty text label.",
1144
+ element
956
1145
  } : void 0,
957
1146
  dependsOnIds: new Set(labelledByValues)
958
1147
  };
@@ -963,6 +1152,7 @@ var FocusableElementLabelRule = class extends ValidationRule {
963
1152
  var ExistingIdRule = class extends ValidationRule {
964
1153
  constructor() {
965
1154
  super(...arguments);
1155
+ __publicField(this, "type", 1 /* Error */);
966
1156
  __publicField(this, "name", "existing-id");
967
1157
  __publicField(this, "anchored", true);
968
1158
  }
@@ -987,9 +1177,10 @@ var ExistingIdRule = class extends ValidationRule {
987
1177
  }
988
1178
  }
989
1179
  return {
990
- error: {
1180
+ notification: {
991
1181
  id: "missing-id",
992
- message: `Elements with referenced ids do not extist.`
1182
+ message: `Elements with referenced ids do not extist.`,
1183
+ element
993
1184
  },
994
1185
  dependsOnIds: new Set(ids)
995
1186
  };
@@ -1000,6 +1191,7 @@ var ExistingIdRule = class extends ValidationRule {
1000
1191
  var FocusLostRule = class extends ValidationRule {
1001
1192
  constructor() {
1002
1193
  super(...arguments);
1194
+ __publicField(this, "type", 1 /* Error */);
1003
1195
  __publicField(this, "name", "focus-lost");
1004
1196
  __publicField(this, "anchored", false);
1005
1197
  __publicField(this, "_focusLostTimeout", 2e3);
@@ -1009,6 +1201,8 @@ var FocusLostRule = class extends ValidationRule {
1009
1201
  __publicField(this, "_focusedElementPosition");
1010
1202
  __publicField(this, "_lastFocusStack");
1011
1203
  __publicField(this, "_lastBlurStack");
1204
+ __publicField(this, "_mouseEventTimer");
1205
+ __publicField(this, "_releaseMouseEvent");
1012
1206
  }
1013
1207
  _serializeElementPosition(element) {
1014
1208
  const position = [];
@@ -1022,7 +1216,7 @@ var FocusLostRule = class extends ValidationRule {
1022
1216
  }
1023
1217
  return position;
1024
1218
  }
1025
- async focused(event) {
1219
+ focused(event) {
1026
1220
  var _a;
1027
1221
  const target = event.target;
1028
1222
  (_a = this._clearScheduledFocusLost) == null ? void 0 : _a.call(this);
@@ -1033,53 +1227,71 @@ var FocusLostRule = class extends ValidationRule {
1033
1227
  }
1034
1228
  return null;
1035
1229
  }
1036
- async blurred(event) {
1230
+ blurred(event) {
1037
1231
  var _a;
1038
1232
  const target = event.target;
1039
1233
  const win = this.window;
1040
1234
  (_a = this._clearScheduledFocusLost) == null ? void 0 : _a.call(this);
1041
- if (!target || !win || event.relatedTarget) {
1235
+ if (!target || !win || event.relatedTarget || this._mouseEventTimer) {
1042
1236
  return null;
1043
1237
  }
1044
- let focusLostTimer;
1045
- let rejectPromise;
1046
1238
  const targetPosition = this._focusedElement === target ? this._focusedElementPosition : void 0;
1047
1239
  this._lastBlurStack = getStackTrace();
1048
1240
  this._focusedElement = void 0;
1049
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);
1050
1255
  this._clearScheduledFocusLost = () => {
1051
1256
  delete this._clearScheduledFocusLost;
1052
- rejectPromise == null ? void 0 : rejectPromise();
1053
- if (focusLostTimer) {
1054
- win.clearTimeout(focusLostTimer);
1055
- focusLostTimer = void 0;
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);
1056
1271
  }
1057
1272
  };
1058
- return new Promise((resolve, reject) => {
1059
- rejectPromise = () => {
1060
- rejectPromise = void 0;
1061
- reject();
1062
- };
1063
- focusLostTimer = win.setTimeout(() => {
1064
- focusLostTimer = void 0;
1065
- rejectPromise = void 0;
1066
- delete this._clearScheduledFocusLost;
1067
- if (win.document.body && (!win.document.activeElement || win.document.activeElement === win.document.body) && (!win.document.body.contains(target) || !isElementVisible(target))) {
1068
- resolve({
1069
- element: target,
1070
- position: targetPosition || [],
1071
- error: {
1072
- id: "focus-lost",
1073
- message: "Focus lost.",
1074
- stack: this._lastBlurStack,
1075
- relStack: this._lastFocusStack
1076
- }
1077
- });
1078
- } else {
1079
- resolve(null);
1080
- }
1081
- }, this._focusLostTimeout);
1082
- });
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;
1083
1295
  }
1084
1296
  };
1085
1297
 
@@ -1087,53 +1299,96 @@ var FocusLostRule = class extends ValidationRule {
1087
1299
  var BadFocusRule = class extends ValidationRule {
1088
1300
  constructor() {
1089
1301
  super(...arguments);
1302
+ __publicField(this, "type", 1 /* Error */);
1090
1303
  __publicField(this, "name", "bad-focus");
1091
1304
  __publicField(this, "anchored", false);
1092
1305
  __publicField(this, "_lastFocusStack");
1093
1306
  __publicField(this, "_lastBlurStack");
1094
- __publicField(this, "_reject");
1307
+ __publicField(this, "_clearCheckTimer");
1095
1308
  }
1096
- async focused() {
1097
- var _a;
1309
+ focused() {
1098
1310
  this._lastFocusStack = getStackTrace();
1099
- (_a = this._reject) == null ? void 0 : _a.call(this);
1100
1311
  return null;
1101
1312
  }
1102
- async blurred() {
1313
+ blurred() {
1103
1314
  var _a;
1104
- (_a = this._reject) == null ? void 0 : _a.call(this);
1105
1315
  const win = this.window;
1106
1316
  if (!win) {
1107
1317
  return null;
1108
1318
  }
1109
1319
  this._lastBlurStack = getStackTrace();
1110
- return new Promise((resolve, reject) => {
1111
- let checkTimer;
1112
- this._reject = () => {
1113
- if (checkTimer) {
1114
- win.clearTimeout(checkTimer);
1115
- checkTimer = void 0;
1116
- }
1117
- this._reject = void 0;
1118
- reject();
1119
- };
1120
- checkTimer = win.setTimeout(() => {
1121
- checkTimer = void 0;
1122
- this._reject = void 0;
1123
- if (document.activeElement && !isElementVisible(document.activeElement)) {
1124
- resolve({
1125
- element: document.activeElement,
1126
- error: {
1127
- id: "bad-focus",
1128
- message: "Focused stolen by invisible element.",
1129
- stack: this._lastBlurStack,
1130
- relStack: this._lastFocusStack
1131
- }
1132
- });
1133
- } else {
1134
- resolve(null);
1135
- }
1136
- }, 100);
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
1137
1392
  });
1138
1393
  }
1139
1394
  };
@@ -1141,10 +1396,18 @@ export {
1141
1396
  AbleDOM,
1142
1397
  AtomicRule,
1143
1398
  BadFocusRule,
1399
+ CustomNotifyRule,
1144
1400
  ExistingIdRule,
1401
+ FindElementRule,
1145
1402
  FocusLostRule,
1146
1403
  FocusableElementLabelRule,
1147
- ValidationRule
1404
+ ValidationRule,
1405
+ ValidationRuleType,
1406
+ hasAccessibilityAttribute,
1407
+ isAccessibilityAffectingElement,
1408
+ isDisplayNone,
1409
+ isElementVisible,
1410
+ matchesSelector
1148
1411
  };
1149
1412
  /*!
1150
1413
  * Copyright (c) Microsoft Corporation. All rights reserved.