abledom 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -58,7 +58,7 @@ var ValidationRule = class {
58
58
  };
59
59
 
60
60
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/ui.css
61
- var ui_default = "#abledom-report {\n bottom: 20px;\n display: flex;\n flex-direction: column;\n left: 10px;\n max-height: 80%;\n max-width: 60%;\n padding: 4px 8px;\n position: 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";
61
+ var ui_default = "#abledom-report {\n bottom: 20px;\n display: flex;\n flex-direction: column;\n left: 10px;\n max-height: 80%;\n max-width: 60%;\n padding: 4px 8px;\n position: fixed;\n z-index: 100500;\n}\n\n#abledom-report :focus-visible {\n outline: 3px solid red;\n mix-blend-mode: difference;\n}\n\n#abledom-report.abledom-align-left {\n left: 10px;\n right: auto;\n}\n\n#abledom-report.abledom-align-right {\n left: auto;\n right: 10px;\n}\n\n#abledom-report.abledom-align-bottom {\n bottom: 20px;\n top: auto;\n}\n\n#abledom-report.abledom-align-top {\n /* flex-direction: column-reverse; */\n bottom: auto;\n top: 10px;\n}\n\n.abledom-menu-container {\n backdrop-filter: blur(3px);\n border-radius: 8px;\n box-shadow: 0px 0px 4px rgba(127, 127, 127, 0.5);\n display: inline-block;\n margin: 2px auto 2px 0;\n}\n\n#abledom-report.abledom-align-right .abledom-menu-container {\n margin: 2px 0 2px auto;\n}\n\n.abledom-menu {\n background-color: rgba(140, 10, 121, 0.7);\n border-radius: 8px;\n color: white;\n display: inline flex;\n font-family: Arial, Helvetica, sans-serif;\n font-size: 16px;\n line-height: 26px;\n padding: 4px;\n}\n\n.abledom-menu .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 box-sizing: border-box;\n display: none;\n opacity: 0.6;\n position: fixed;\n z-index: 100499;\n}\n\n.abledom-highlight-border1 {\n border-top: 2px solid red;\n border-bottom: 2px solid red;\n box-sizing: border-box;\n position: absolute;\n top: -2px;\n width: calc(100% + 20px);\n height: calc(100% + 4px);\n margin: 0 -10px;\n}\n\n.abledom-highlight-border2 {\n border-left: 2px solid red;\n border-right: 2px solid red;\n box-sizing: border-box;\n position: absolute;\n width: calc(100% + 4px);\n left: -2px;\n height: calc(100% + 20px);\n margin: -10px 0;\n}\n";
62
62
 
63
63
  // src/ui/domBuilder.ts
64
64
  var DOMBuilder = class {
@@ -73,6 +73,7 @@ var DOMBuilder = class {
73
73
  const parent = this._stack[0];
74
74
  const element = namespace ? (_a = this._doc) == null ? void 0 : _a.createElementNS(namespace, tagName) : (_b = this._doc) == null ? void 0 : _b.createElement(tagName);
75
75
  if (parent && element) {
76
+ element.__abledomui = true;
76
77
  if (attributes) {
77
78
  for (const [key, value] of Object.entries(attributes)) {
78
79
  if (key === "class") {
@@ -100,8 +101,12 @@ var DOMBuilder = class {
100
101
  return this;
101
102
  }
102
103
  text(text) {
103
- var _a;
104
- (_a = this._stack[0]) == null ? void 0 : _a.appendChild(document.createTextNode(text));
104
+ var _a, _b;
105
+ const textNode = (_a = this._doc) == null ? void 0 : _a.createTextNode(text);
106
+ if (textNode) {
107
+ textNode.__abledomui = true;
108
+ (_b = this._stack[0]) == null ? void 0 : _b.appendChild(textNode);
109
+ }
105
110
  return this;
106
111
  }
107
112
  element(callback) {
@@ -168,8 +173,36 @@ var reveal_default = function buildSVG4(parent) {
168
173
  return parent.firstElementChild;
169
174
  };
170
175
 
176
+ // inline-file:/Users/marata/Documents/Work/abledom/src/ui/bug.svg
177
+ var bug_default = function buildSVG5(parent) {
178
+ const builder = new DOMBuilder(parent);
179
+ builder.openTag("svg", { "width": "20", "height": "20", "viewBox": "0 0 20 20", "fill": "none", "stroke": "currentColor" }, void 0, "http://www.w3.org/2000/svg");
180
+ builder.openTag("ellipse", { "cx": "10", "cy": "12", "rx": "4", "ry": "5", "stroke-width": "1.5" }, void 0, "http://www.w3.org/2000/svg");
181
+ builder.closeTag();
182
+ builder.openTag("circle", { "cx": "10", "cy": "5.5", "r": "2", "stroke-width": "1.5" }, void 0, "http://www.w3.org/2000/svg");
183
+ builder.closeTag();
184
+ builder.openTag("line", { "x1": "6.5", "y1": "10", "x2": "3.5", "y2": "7", "stroke-width": "1.2" }, void 0, "http://www.w3.org/2000/svg");
185
+ builder.closeTag();
186
+ builder.openTag("line", { "x1": "13.5", "y1": "10", "x2": "16.5", "y2": "7", "stroke-width": "1.2" }, void 0, "http://www.w3.org/2000/svg");
187
+ builder.closeTag();
188
+ builder.openTag("line", { "x1": "6", "y1": "13", "x2": "3.5", "y2": "13", "stroke-width": "1.2" }, void 0, "http://www.w3.org/2000/svg");
189
+ builder.closeTag();
190
+ builder.openTag("line", { "x1": "14", "y1": "13", "x2": "16.5", "y2": "13", "stroke-width": "1.2" }, void 0, "http://www.w3.org/2000/svg");
191
+ builder.closeTag();
192
+ builder.openTag("line", { "x1": "6.5", "y1": "16", "x2": "3.5", "y2": "19", "stroke-width": "1.2" }, void 0, "http://www.w3.org/2000/svg");
193
+ builder.closeTag();
194
+ builder.openTag("line", { "x1": "13.5", "y1": "16", "x2": "16.5", "y2": "19", "stroke-width": "1.2" }, void 0, "http://www.w3.org/2000/svg");
195
+ builder.closeTag();
196
+ builder.openTag("line", { "x1": "9", "y1": "3.5", "x2": "7.5", "y2": "2", "stroke-width": "1.2" }, void 0, "http://www.w3.org/2000/svg");
197
+ builder.closeTag();
198
+ builder.openTag("line", { "x1": "11", "y1": "3.5", "x2": "12.5", "y2": "2", "stroke-width": "1.2" }, void 0, "http://www.w3.org/2000/svg");
199
+ builder.closeTag();
200
+ builder.closeTag();
201
+ return parent.firstElementChild;
202
+ };
203
+
171
204
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/hideall.svg
172
- var hideall_default = function buildSVG5(parent) {
205
+ var hideall_default = function buildSVG6(parent) {
173
206
  const builder = new DOMBuilder(parent);
174
207
  builder.openTag("svg", { "width": "20", "height": "20", "viewBox": "0 0 20 20", "fill": "none", "stroke": "currentColor" }, void 0, "http://www.w3.org/2000/svg");
175
208
  builder.openTag("path", { "d": "M11.44 17.5a1.67 1.67 0 0 1-2.89 0", "stroke-width": "1.5" }, void 0, "http://www.w3.org/2000/svg");
@@ -183,7 +216,7 @@ var hideall_default = function buildSVG5(parent) {
183
216
  };
184
217
 
185
218
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/muteall.svg
186
- var muteall_default = function buildSVG6(parent) {
219
+ var muteall_default = function buildSVG7(parent) {
187
220
  const builder = new DOMBuilder(parent);
188
221
  builder.openTag("svg", { "width": "20", "height": "20", "viewBox": "0 0 20 20", "fill": "none", "stroke": "currentColor" }, void 0, "http://www.w3.org/2000/svg");
189
222
  builder.openTag("path", { "d": "M11.44 17.5a1.67 1.67 0 0 1-2.89 0", "stroke-width": "1.5" }, void 0, "http://www.w3.org/2000/svg");
@@ -199,7 +232,7 @@ var muteall_default = function buildSVG6(parent) {
199
232
  };
200
233
 
201
234
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/showall.svg
202
- var showall_default = function buildSVG7(parent) {
235
+ var showall_default = function buildSVG8(parent) {
203
236
  const builder = new DOMBuilder(parent);
204
237
  builder.openTag("svg", { "width": "20", "height": "20", "viewBox": "0 0 20 20", "fill": "none", "stroke": "currentColor" }, void 0, "http://www.w3.org/2000/svg");
205
238
  builder.openTag("path", { "d": "M11.44 17.5a1.67 1.67 0 0 1-2.89 0", "stroke-width": "1.5" }, void 0, "http://www.w3.org/2000/svg");
@@ -211,7 +244,7 @@ var showall_default = function buildSVG7(parent) {
211
244
  };
212
245
 
213
246
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/aligntopleft.svg
214
- var aligntopleft_default = function buildSVG8(parent) {
247
+ var aligntopleft_default = function buildSVG9(parent) {
215
248
  const builder = new DOMBuilder(parent);
216
249
  builder.openTag("svg", { "width": "20", "height": "20", "viewBox": "0 0 20 20", "fill": "none", "stroke": "currentColor" }, void 0, "http://www.w3.org/2000/svg");
217
250
  builder.openTag("rect", { "x": "3", "y": "3", "width": "6", "height": "6", "stroke-width": "2" }, void 0, "http://www.w3.org/2000/svg");
@@ -221,7 +254,7 @@ var aligntopleft_default = function buildSVG8(parent) {
221
254
  };
222
255
 
223
256
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/aligntopright.svg
224
- var aligntopright_default = function buildSVG9(parent) {
257
+ var aligntopright_default = function buildSVG10(parent) {
225
258
  const builder = new DOMBuilder(parent);
226
259
  builder.openTag("svg", { "width": "20", "height": "20", "viewBox": "0 0 20 20", "fill": "none", "stroke": "currentColor" }, void 0, "http://www.w3.org/2000/svg");
227
260
  builder.openTag("rect", { "x": "11", "y": "3", "width": "6", "height": "6", "stroke-width": "2" }, void 0, "http://www.w3.org/2000/svg");
@@ -231,7 +264,7 @@ var aligntopright_default = function buildSVG9(parent) {
231
264
  };
232
265
 
233
266
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/alignbottomright.svg
234
- var alignbottomright_default = function buildSVG10(parent) {
267
+ var alignbottomright_default = function buildSVG11(parent) {
235
268
  const builder = new DOMBuilder(parent);
236
269
  builder.openTag("svg", { "width": "20", "height": "20", "viewBox": "0 0 20 20", "fill": "none", "stroke": "currentColor" }, void 0, "http://www.w3.org/2000/svg");
237
270
  builder.openTag("rect", { "x": "11", "y": "11", "width": "6", "height": "6", "stroke-width": "2" }, void 0, "http://www.w3.org/2000/svg");
@@ -241,7 +274,7 @@ var alignbottomright_default = function buildSVG10(parent) {
241
274
  };
242
275
 
243
276
  // inline-file:/Users/marata/Documents/Work/abledom/src/ui/alignbottomleft.svg
244
- var alignbottomleft_default = function buildSVG11(parent) {
277
+ var alignbottomleft_default = function buildSVG12(parent) {
245
278
  const builder = new DOMBuilder(parent);
246
279
  builder.openTag("svg", { "width": "20", "height": "20", "viewBox": "0 0 20 20", "fill": "none", "stroke": "currentColor" }, void 0, "http://www.w3.org/2000/svg");
247
280
  builder.openTag("rect", { "x": "3", "y": "11", "width": "6", "height": "6", "stroke-width": "2" }, void 0, "http://www.w3.org/2000/svg");
@@ -252,25 +285,21 @@ var alignbottomleft_default = function buildSVG11(parent) {
252
285
 
253
286
  // src/ui/ui.ts
254
287
  var pressedClass = "pressed";
255
- var _NotificationUI = class _NotificationUI {
256
- constructor(win, rule) {
257
- __publicField(this, "_win");
288
+ var NotificationUI = class {
289
+ constructor(win, core, rule, notificationsUI) {
290
+ __publicField(this, "_core");
291
+ __publicField(this, "_notificationsUI");
258
292
  __publicField(this, "_wrapper");
259
293
  __publicField(this, "_rule");
260
294
  __publicField(this, "_onToggle");
261
295
  __publicField(this, "isHidden", false);
262
- this._win = win;
296
+ this._core = core;
263
297
  this._rule = rule;
264
- if (!_NotificationUI._notificationsUI) {
265
- _NotificationUI._notificationsUI = new NotificationsUI(this._win);
266
- }
298
+ this._notificationsUI = notificationsUI;
267
299
  this._wrapper = win.document.createElement(
268
300
  "div"
269
301
  );
270
- if (!_NotificationUI._highlight) {
271
- _NotificationUI._highlight = new ElementHighlighter(win);
272
- }
273
- _NotificationUI._notificationsUI.addNotification(this);
302
+ notificationsUI.addNotification(this);
274
303
  }
275
304
  static setOnToggle(instance, onToggle) {
276
305
  instance._onToggle = onToggle;
@@ -279,7 +308,6 @@ var _NotificationUI = class _NotificationUI {
279
308
  return instance._wrapper;
280
309
  }
281
310
  update(notification) {
282
- const win = this._win;
283
311
  const rule = this._rule;
284
312
  const wrapper = this._wrapper;
285
313
  const element = notification.element;
@@ -291,11 +319,11 @@ var _NotificationUI = class _NotificationUI {
291
319
  (container) => {
292
320
  container.onmouseover = () => {
293
321
  var _a;
294
- element && ((_a = _NotificationUI._highlight) == null ? void 0 : _a.highlight(element));
322
+ element && ((_a = this._notificationsUI) == null ? void 0 : _a.highlight(element));
295
323
  };
296
324
  container.onmouseout = () => {
297
325
  var _a;
298
- (_a = _NotificationUI._highlight) == null ? void 0 : _a.hide();
326
+ (_a = this._notificationsUI) == null ? void 0 : _a.highlight(null);
299
327
  };
300
328
  }
301
329
  ).openTag("div", {
@@ -308,15 +336,18 @@ var _NotificationUI = class _NotificationUI {
308
336
  },
309
337
  (logButton) => {
310
338
  logButton.onclick = () => {
311
- console.error(
339
+ const { id, message, element: element2, rel, help, ...extra } = notification;
340
+ this._core.log(
312
341
  "AbleDOM: ",
342
+ "\nid:",
343
+ id,
313
344
  "\nmessage:",
314
- notification.message,
345
+ message,
315
346
  "\nelement:",
316
- element,
317
- ...notification.rel ? ["\nrelative:", notification.rel] : [],
318
- "\nnotification:",
319
- notification
347
+ element2,
348
+ ...rel ? ["\nrelative:", rel] : [],
349
+ ...help ? ["\nhelp:", help] : [],
350
+ ...Object.keys(extra).length > 0 ? ["\nextra:", extra] : []
320
351
  );
321
352
  };
322
353
  }
@@ -324,27 +355,43 @@ var _NotificationUI = class _NotificationUI {
324
355
  "button",
325
356
  {
326
357
  class: "button",
327
- title: "Reveal in Elements panel"
358
+ // title: "Reveal in Elements panel",
359
+ title: "Scroll element into view"
328
360
  },
329
361
  (revealButton) => {
330
- var _a;
331
- const hasDevTools = !!((_a = win.__ableDOMDevtools) == null ? void 0 : _a.revealElement) && false;
332
- if (hasDevTools && element && win.document.body.contains(element)) {
362
+ const element2 = notification.element;
363
+ if (element2) {
333
364
  revealButton.onclick = () => {
334
- var _a2;
335
- const revealElement = (_a2 = win.__ableDOMDevtools) == null ? void 0 : _a2.revealElement;
336
- if (revealElement && win.document.body.contains(element)) {
337
- revealElement(element).then((revealed) => {
338
- if (!revealed) {
339
- }
340
- });
341
- }
365
+ var _a;
366
+ element2.scrollIntoView();
367
+ (_a = this._notificationsUI) == null ? void 0 : _a.highlight(element2);
342
368
  };
343
369
  } else {
344
370
  revealButton.style.display = "none";
345
371
  }
346
372
  }
347
- ).element(reveal_default).closeTag().text(notification.message).openTag(
373
+ ).element(reveal_default).closeTag().openTag(
374
+ "button",
375
+ {
376
+ class: "button",
377
+ title: "Report bug"
378
+ },
379
+ (bugReportButton) => {
380
+ var _a, _b;
381
+ const bugReport = (_a = this._notificationsUI) == null ? void 0 : _a.bugReport;
382
+ if (bugReport == null ? void 0 : bugReport.isVisible(notification)) {
383
+ const title = (_b = bugReport.getTitle) == null ? void 0 : _b.call(bugReport, notification);
384
+ if (title) {
385
+ bugReportButton.title = title;
386
+ }
387
+ bugReportButton.onclick = () => {
388
+ bugReport.onClick(notification);
389
+ };
390
+ } else {
391
+ bugReportButton.style.display = "none";
392
+ }
393
+ }
394
+ ).element(bug_default).closeTag().text(notification.message).openTag(
348
395
  "a",
349
396
  {
350
397
  class: "button close",
@@ -367,7 +414,7 @@ var _NotificationUI = class _NotificationUI {
367
414
  closeButton.onclick = () => {
368
415
  var _a;
369
416
  this.toggle(false);
370
- (_a = _NotificationUI._highlight) == null ? void 0 : _a.hide();
417
+ (_a = this._notificationsUI) == null ? void 0 : _a.highlight(null);
371
418
  };
372
419
  }
373
420
  ).element(close_default).closeTag().closeTag().closeTag();
@@ -386,14 +433,12 @@ var _NotificationUI = class _NotificationUI {
386
433
  dispose() {
387
434
  var _a;
388
435
  this._wrapper.remove();
389
- (_a = _NotificationUI._notificationsUI) == null ? void 0 : _a.removeNotification(this);
436
+ (_a = this._notificationsUI) == null ? void 0 : _a.removeNotification(this);
437
+ delete this._notificationsUI;
390
438
  }
391
439
  };
392
- __publicField(_NotificationUI, "_notificationsUI");
393
- __publicField(_NotificationUI, "_highlight");
394
- var NotificationUI = _NotificationUI;
395
440
  var NotificationsUI = class {
396
- constructor(win) {
441
+ constructor(win, props) {
397
442
  __publicField(this, "_container");
398
443
  __publicField(this, "_notificationsContainer");
399
444
  __publicField(this, "_menuElement");
@@ -406,17 +451,23 @@ var NotificationsUI = class {
406
451
  __publicField(this, "_alignBottomRightButton");
407
452
  __publicField(this, "_isMuted", false);
408
453
  __publicField(this, "_notifications", /* @__PURE__ */ new Set());
409
- const container = this._container = win.document.createElement("div");
454
+ __publicField(this, "_highlighter");
455
+ __publicField(this, "bugReport");
456
+ this.bugReport = props.bugReport;
457
+ const doc = win.document;
458
+ const container = this._container = doc.createElement("div");
410
459
  container.__abledomui = true;
411
460
  container.id = "abledom-report";
412
- const style = document.createElement("style");
461
+ const style = doc.createElement("style");
413
462
  style.type = "text/css";
414
- style.appendChild(document.createTextNode(ui_default));
463
+ style.appendChild(doc.createTextNode(ui_default));
415
464
  container.appendChild(style);
416
- const notificationsContainer = this._notificationsContainer = win.document.createElement("div");
465
+ const notificationsContainer = this._notificationsContainer = doc.createElement("div");
466
+ notificationsContainer.__abledomui = true;
417
467
  notificationsContainer.className = "abledom-notifications-container";
418
468
  container.appendChild(notificationsContainer);
419
- const menuElement = this._menuElement = win.document.createElement("div");
469
+ const menuElement = this._menuElement = doc.createElement("div");
470
+ menuElement.__abledomui = true;
420
471
  menuElement.className = "abledom-menu-container";
421
472
  container.appendChild(menuElement);
422
473
  new DOMBuilder(menuElement).openTag("div", { class: "abledom-menu" }).openTag(
@@ -523,10 +574,14 @@ var NotificationsUI = class {
523
574
  };
524
575
  }
525
576
  ).element(alignbottomright_default).closeTag().closeTag();
526
- win.document.body.appendChild(container);
577
+ doc.body.appendChild(container);
578
+ this._highlighter = new ElementHighlighter(win);
527
579
  }
528
580
  setUIAlignment(alignment) {
529
581
  var _a, _b, _c, _d, _e, _f, _g, _h;
582
+ if (!this._container || !this._notificationsContainer || !this._menuElement) {
583
+ return;
584
+ }
530
585
  (_a = this._alignBottomLeftButton) == null ? void 0 : _a.classList.remove(pressedClass);
531
586
  (_b = this._alignBottomRightButton) == null ? void 0 : _b.classList.remove(pressedClass);
532
587
  (_c = this._alignTopLeftButton) == null ? void 0 : _c.classList.remove(pressedClass);
@@ -566,6 +621,9 @@ var NotificationsUI = class {
566
621
  );
567
622
  }
568
623
  _setNotificationsCount(count) {
624
+ if (!this._menuElement) {
625
+ return;
626
+ }
569
627
  const countElement = this._notificationCountElement;
570
628
  if (countElement && count > 0) {
571
629
  countElement.textContent = "";
@@ -597,6 +655,9 @@ var NotificationsUI = class {
597
655
  showAllButton.style.display = allVisible ? "none" : "block";
598
656
  }
599
657
  addNotification(notification) {
658
+ if (!this._notificationsContainer) {
659
+ throw new Error("NotificationsUI is not initialized");
660
+ }
600
661
  if (this._notifications.has(notification)) {
601
662
  return;
602
663
  }
@@ -620,6 +681,7 @@ var NotificationsUI = class {
620
681
  this._notifications.delete(notification);
621
682
  this._setNotificationsCount(this._notifications.size);
622
683
  this._setShowHideButtonsVisibility();
684
+ this.highlight(null);
623
685
  }
624
686
  hideAll() {
625
687
  this._notifications.forEach((notification) => {
@@ -633,35 +695,104 @@ var NotificationsUI = class {
633
695
  });
634
696
  this._setShowHideButtonsVisibility();
635
697
  }
698
+ highlight(element) {
699
+ var _a;
700
+ (_a = this._highlighter) == null ? void 0 : _a.highlight(element);
701
+ }
702
+ dispose() {
703
+ var _a, _b;
704
+ (_a = this._highlighter) == null ? void 0 : _a.dispose();
705
+ (_b = this._container) == null ? void 0 : _b.remove();
706
+ delete this._highlighter;
707
+ delete this._container;
708
+ delete this._notificationsContainer;
709
+ delete this._menuElement;
710
+ delete this._notificationCountElement;
711
+ delete this._showAllButton;
712
+ delete this._hideAllButton;
713
+ delete this._alignBottomLeftButton;
714
+ delete this._alignTopLeftButton;
715
+ delete this._alignTopRightButton;
716
+ delete this._alignBottomRightButton;
717
+ }
636
718
  };
637
719
  var ElementHighlighter = class {
638
720
  constructor(win) {
639
721
  __publicField(this, "_window");
640
722
  __publicField(this, "_container");
723
+ __publicField(this, "_element");
724
+ __publicField(this, "_cancelScrollTimer");
725
+ __publicField(this, "_intersectionObserver");
726
+ __publicField(this, "_onScroll", () => {
727
+ var _a;
728
+ (_a = this._cancelScrollTimer) == null ? void 0 : _a.call(this);
729
+ this._hide();
730
+ const win = this._window;
731
+ if (win) {
732
+ const scrollTimer = win.setTimeout(() => {
733
+ delete this._cancelScrollTimer;
734
+ this.highlight(this._element || null);
735
+ }, 100);
736
+ this._cancelScrollTimer = () => {
737
+ delete this._cancelScrollTimer;
738
+ win.clearTimeout(scrollTimer);
739
+ };
740
+ }
741
+ });
641
742
  this._window = win;
642
743
  const container = this._container = win.document.createElement("div");
643
744
  container.__abledomui = true;
644
745
  container.className = "abledom-highlight";
746
+ new DOMBuilder(container).openTag("div", { class: "abledom-highlight-border1" }).closeTag().openTag("div", { class: "abledom-highlight-border2" }).closeTag();
747
+ win.addEventListener("scroll", this._onScroll, true);
645
748
  }
646
749
  highlight(element) {
647
- const rect = element.getBoundingClientRect();
648
- if (rect.width === 0 || rect.height === 0) {
750
+ if (!element) {
751
+ delete this._element;
752
+ this._unobserve();
753
+ this._hide();
649
754
  return;
650
755
  }
651
756
  const win = this._window;
652
757
  const container = this._container;
653
- const style = container.style;
654
- if (container.parentElement !== win.document.body) {
655
- win.document.body.appendChild(container);
758
+ if (!win || !container) {
759
+ return;
656
760
  }
657
- style.width = `${rect.width}px`;
658
- style.height = `${rect.height}px`;
659
- style.top = `${rect.top}px`;
660
- style.left = `${rect.left}px`;
661
- container.style.display = "block";
761
+ this._element = element;
762
+ this._intersectionObserver = new IntersectionObserver(([entry]) => {
763
+ if (entry) {
764
+ const rect = entry.boundingClientRect;
765
+ const body = win.document.body;
766
+ const style = container.style;
767
+ if (container.parentElement !== body) {
768
+ body.appendChild(container);
769
+ }
770
+ style.width = `${rect.width}px`;
771
+ style.height = `${rect.height}px`;
772
+ style.top = `${rect.top}px`;
773
+ style.left = `${rect.left}px`;
774
+ container.style.display = "block";
775
+ }
776
+ });
777
+ this._intersectionObserver.observe(element);
662
778
  }
663
- hide() {
664
- this._container.style.display = "none";
779
+ dispose() {
780
+ var _a, _b, _c;
781
+ this._unobserve();
782
+ (_a = this._cancelScrollTimer) == null ? void 0 : _a.call(this);
783
+ (_b = this._window) == null ? void 0 : _b.removeEventListener("scroll", this._onScroll, true);
784
+ (_c = this._container) == null ? void 0 : _c.remove();
785
+ delete this._element;
786
+ delete this._container;
787
+ delete this._window;
788
+ }
789
+ _hide() {
790
+ this._container && (this._container.style.display = "none");
791
+ }
792
+ _unobserve() {
793
+ var _a;
794
+ (_a = this._intersectionObserver) == null ? void 0 : _a.disconnect();
795
+ delete this._intersectionObserver;
665
796
  }
666
797
  };
667
798
  function isAbleDOMUIElement(element) {
@@ -856,8 +987,9 @@ function getStackTrace() {
856
987
 
857
988
  // src/core.ts
858
989
  var AbleDOM = class {
859
- constructor(win) {
990
+ constructor(win, props = {}) {
860
991
  __publicField(this, "_win");
992
+ __publicField(this, "_props");
861
993
  __publicField(this, "_observer");
862
994
  __publicField(this, "_clearValidationTimeout");
863
995
  __publicField(this, "_elementsWithNotifications", /* @__PURE__ */ new Set());
@@ -868,6 +1000,7 @@ var AbleDOM = class {
868
1000
  __publicField(this, "_rules", []);
869
1001
  __publicField(this, "_startFunc");
870
1002
  __publicField(this, "_isStarted", false);
1003
+ __publicField(this, "_notificationsUI");
871
1004
  __publicField(this, "_onFocusIn", (event) => {
872
1005
  var _a;
873
1006
  const target = event.target;
@@ -897,11 +1030,18 @@ var AbleDOM = class {
897
1030
  __publicField(this, "_notifyAsync", (rule, notification) => {
898
1031
  this._addNotification(rule, notification);
899
1032
  });
1033
+ __publicField(this, "log", (...args) => {
1034
+ var _a, _b, _c, _d;
1035
+ return (_d = ((_a = this._props) == null ? void 0 : _a.log) || // In a multi-window application, just `console.error` could belong to a different window.
1036
+ ((_c = (_b = this._win) == null ? void 0 : _b.console) == null ? void 0 : _c.error)) == null ? void 0 : _d.apply(null, args);
1037
+ });
900
1038
  this._win = win;
1039
+ this._props = props;
901
1040
  const _elementsToValidate = /* @__PURE__ */ new Set();
902
1041
  const _elementsToRemove = /* @__PURE__ */ new Set();
903
- win.document.addEventListener("focusin", this._onFocusIn, true);
904
- win.document.addEventListener("focusout", this._onFocusOut, true);
1042
+ const doc = win.document;
1043
+ doc.addEventListener("focusin", this._onFocusIn, true);
1044
+ doc.addEventListener("focusout", this._onFocusOut, true);
905
1045
  this._observer = new MutationObserver((mutations) => {
906
1046
  var _a;
907
1047
  for (let mutation of mutations) {
@@ -939,12 +1079,13 @@ var AbleDOM = class {
939
1079
  });
940
1080
  this._startFunc = () => {
941
1081
  delete this._startFunc;
942
- this._observer.observe(win.document, {
1082
+ this._observer.observe(doc, {
943
1083
  childList: true,
944
1084
  subtree: true,
945
- attributes: true
1085
+ attributes: true,
1086
+ characterData: true
946
1087
  });
947
- findTargets(win.document.body, false);
1088
+ findTargets(doc.body, false);
948
1089
  this._validate(_elementsToValidate);
949
1090
  _elementsToValidate.clear();
950
1091
  };
@@ -974,7 +1115,7 @@ var AbleDOM = class {
974
1115
  return;
975
1116
  }
976
1117
  addTarget(node, removed);
977
- const walker = win.document.createTreeWalker(
1118
+ const walker = doc.createTreeWalker(
978
1119
  node,
979
1120
  NodeFilter.SHOW_ELEMENT,
980
1121
  (node2) => {
@@ -1025,6 +1166,12 @@ var AbleDOM = class {
1025
1166
  }
1026
1167
  }
1027
1168
  _addNotification(rule, notification) {
1169
+ var _a;
1170
+ if (!this._notificationsUI) {
1171
+ this._notificationsUI = new NotificationsUI(this._win, {
1172
+ bugReport: (_a = this._props) == null ? void 0 : _a.bugReport
1173
+ });
1174
+ }
1028
1175
  const element = notification == null ? void 0 : notification.element;
1029
1176
  if (!notification) {
1030
1177
  this._removeNotification(element || this._win.document.body, rule);
@@ -1042,12 +1189,22 @@ var AbleDOM = class {
1042
1189
  }
1043
1190
  notificationUI = notifications.get(rule);
1044
1191
  if (!notificationUI) {
1045
- notificationUI = new NotificationUI(this._win, rule);
1192
+ notificationUI = new NotificationUI(
1193
+ this._win,
1194
+ this,
1195
+ rule,
1196
+ this._notificationsUI
1197
+ );
1046
1198
  notifications.set(rule, notificationUI);
1047
1199
  }
1048
1200
  this._elementsWithNotifications.add(element);
1049
1201
  } else {
1050
- notificationUI = new NotificationUI(this._win, rule);
1202
+ notificationUI = new NotificationUI(
1203
+ this._win,
1204
+ this,
1205
+ rule,
1206
+ this._notificationsUI
1207
+ );
1051
1208
  }
1052
1209
  notificationUI.update(notification);
1053
1210
  }
@@ -1181,17 +1338,20 @@ var AbleDOM = class {
1181
1338
  (_b = this._startFunc) == null ? void 0 : _b.call(this);
1182
1339
  }
1183
1340
  dispose() {
1184
- var _a, _b;
1185
- this._win.document.addEventListener("focusin", this._onFocusIn, true);
1186
- this._win.document.addEventListener("focusout", this._onFocusOut, true);
1341
+ var _a, _b, _c;
1342
+ const doc = this._win.document;
1343
+ doc.addEventListener("focusin", this._onFocusIn, true);
1344
+ doc.addEventListener("focusout", this._onFocusOut, true);
1187
1345
  this._remove(this._elementsWithNotifications);
1188
1346
  this._elementsWithNotifications.clear();
1189
1347
  this._dependantIdsByElement.clear();
1190
1348
  this._elementsDependingOnId.clear();
1191
1349
  this._idByElement.clear();
1192
- (_a = this._clearValidationTimeout) == null ? void 0 : _a.call(this);
1350
+ (_a = this._notificationsUI) == null ? void 0 : _a.dispose();
1351
+ delete this._notificationsUI;
1352
+ (_b = this._clearValidationTimeout) == null ? void 0 : _b.call(this);
1193
1353
  for (const rule of this._rules) {
1194
- (_b = rule.stop) == null ? void 0 : _b.call(rule);
1354
+ (_c = rule.stop) == null ? void 0 : _c.call(rule);
1195
1355
  ValidationRule.dispose(rule);
1196
1356
  }
1197
1357
  this._rules = [];
@@ -1215,7 +1375,7 @@ var AtomicRule = class extends ValidationRule {
1215
1375
  return matchesSelector(element, focusableElementSelector);
1216
1376
  }
1217
1377
  validate(element) {
1218
- const parentAtomic = document.evaluate(
1378
+ const parentAtomic = element.ownerDocument.evaluate(
1219
1379
  `ancestor::*[
1220
1380
  @role = 'button' or
1221
1381
  @role = 'checkbox' or
@@ -1276,7 +1436,7 @@ var FocusableElementLabelRule = class extends ValidationRule {
1276
1436
  __publicField(this, "anchored", true);
1277
1437
  }
1278
1438
  _isAriaHidden(element) {
1279
- return document.evaluate(
1439
+ return element.ownerDocument.evaluate(
1280
1440
  `ancestor-or-self::*[@aria-hidden = 'true' or @hidden]`,
1281
1441
  element,
1282
1442
  null,
@@ -1303,7 +1463,7 @@ var FocusableElementLabelRule = class extends ValidationRule {
1303
1463
  if ((_a = element.textContent) == null ? void 0 : _a.trim()) {
1304
1464
  return true;
1305
1465
  }
1306
- const labelNodes = document.evaluate(
1466
+ const labelNodes = element.ownerDocument.evaluate(
1307
1467
  `(
1308
1468
  .//@aria-label |
1309
1469
  .//text() |
@@ -1330,6 +1490,7 @@ var FocusableElementLabelRule = class extends ValidationRule {
1330
1490
  }
1331
1491
  validate(element) {
1332
1492
  var _a, _b;
1493
+ const doc = element.ownerDocument;
1333
1494
  if (element.tagName === "INPUT") {
1334
1495
  const type = element.type;
1335
1496
  if (type === "hidden") {
@@ -1355,7 +1516,7 @@ var FocusableElementLabelRule = class extends ValidationRule {
1355
1516
  if (this._hasLabel(element)) {
1356
1517
  return null;
1357
1518
  }
1358
- const labelledByNodes = document.evaluate(
1519
+ const labelledByNodes = doc.evaluate(
1359
1520
  `.//@aria-labelledby[not(ancestor-or-self::*[@aria-hidden = 'true' or @hidden])]`,
1360
1521
  element,
1361
1522
  null,
@@ -1370,7 +1531,7 @@ var FocusableElementLabelRule = class extends ValidationRule {
1370
1531
  }
1371
1532
  }
1372
1533
  for (const id of labelledByValues) {
1373
- const labelElement = document.getElementById(id);
1534
+ const labelElement = doc.getElementById(id);
1374
1535
  if (labelElement && this._hasLabel(labelElement)) {
1375
1536
  return {
1376
1537
  dependsOnIds: new Set(labelledByValues)
@@ -1411,7 +1572,7 @@ var ExistingIdRule = class extends ValidationRule {
1411
1572
  return null;
1412
1573
  }
1413
1574
  for (const id of ids) {
1414
- if (document.getElementById(id)) {
1575
+ if (element.ownerDocument.getElementById(id)) {
1415
1576
  return {
1416
1577
  dependsOnIds: new Set(ids)
1417
1578
  };
@@ -1476,13 +1637,14 @@ var FocusLostRule = class extends ValidationRule {
1476
1637
  if (!target || !win || event.relatedTarget || this._mouseEventTimer) {
1477
1638
  return null;
1478
1639
  }
1640
+ const doc = win.document;
1479
1641
  const targetPosition = this._focusedElement === target ? this._focusedElementPosition : void 0;
1480
1642
  this._lastBlurStack = getStackTrace();
1481
1643
  this._focusedElement = void 0;
1482
1644
  this._focusedElementPosition = void 0;
1483
1645
  const focusLostTimer = win.setTimeout(() => {
1484
1646
  delete this._clearScheduledFocusLost;
1485
- if (win.document.body && (!win.document.activeElement || win.document.activeElement === win.document.body) && (!win.document.body.contains(target) || !isElementVisible(target))) {
1647
+ if (doc.body && (!doc.activeElement || doc.activeElement === doc.body) && (!doc.body.contains(target) || !isElementVisible(target))) {
1486
1648
  this.notify({
1487
1649
  element: target,
1488
1650
  id: "focus-lost",
@@ -1557,15 +1719,16 @@ var BadFocusRule = class extends ValidationRule {
1557
1719
  if (!win) {
1558
1720
  return null;
1559
1721
  }
1722
+ const doc = win.document;
1560
1723
  this._lastBlurStack = getStackTrace();
1561
1724
  (_a = this._clearCheckTimer) == null ? void 0 : _a.call(this);
1562
1725
  const checkTimer = win.setTimeout(() => {
1563
1726
  delete this._clearCheckTimer;
1564
- if (document.activeElement && !isElementVisible(document.activeElement)) {
1727
+ if (doc.activeElement && !isElementVisible(doc.activeElement)) {
1565
1728
  this.notify({
1566
1729
  id: "bad-focus",
1567
1730
  message: "Focused stolen by invisible element.",
1568
- element: document.activeElement,
1731
+ element: doc.activeElement,
1569
1732
  stack: this._lastBlurStack,
1570
1733
  relStack: this._lastFocusStack
1571
1734
  });