@aurodesignsystem/auro-library 5.10.0 → 5.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Semantic Release Automated Changelog
2
2
 
3
+ ## [5.11.1](https://github.com/AlaskaAirlines/auro-library/compare/v5.11.0...v5.11.1) (2026-03-04)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * prevent TypeError in updateCurrentExpandedDropdown when expandedAuroFloater is undefined ([8fb98bc](https://github.com/AlaskaAirlines/auro-library/commit/8fb98bc1ea1ce5d1643cdb406cb5cbd239ca4476))
9
+ * skip outside-click handler when bib is fullscreen for VoiceOver compatibility #AB1503186 ([d958258](https://github.com/AlaskaAirlines/auro-library/commit/d958258e4d0557345e46290d21298b581ed88dd2)), closes [#AB1503186](https://github.com/AlaskaAirlines/auro-library/issues/AB1503186)
10
+
11
+ # [5.11.0](https://github.com/AlaskaAirlines/auro-library/compare/v5.10.0...v5.11.0) (2026-02-20)
12
+
13
+
14
+ ### Features
15
+
16
+ * add function for finding closest elem with defined attr [#222](https://github.com/AlaskaAirlines/auro-library/issues/222) ([e0a311d](https://github.com/AlaskaAirlines/auro-library/commit/e0a311db4b2d112d2bcfcce437e75553b16efe3e))
17
+ * new function to get nearest defined locale [#223](https://github.com/AlaskaAirlines/auro-library/issues/223) ([7562865](https://github.com/AlaskaAirlines/auro-library/commit/756286553b301bc679648f2764d23b4682304a40))
18
+
3
19
  # [5.10.0](https://github.com/AlaskaAirlines/auro-library/compare/v5.9.0...v5.10.0) (2026-02-17)
4
20
 
5
21
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurodesignsystem/auro-library",
3
- "version": "5.10.0",
3
+ "version": "5.11.1",
4
4
  "description": "This repository holds shared scripts, utilities, and workflows utilized across repositories along the Auro Design System.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Class for interaction with the DOM.
3
+ */
4
+ export class DomHandler {
5
+ /**
6
+ * Walk up the DOM (including Shadow DOM boundaries) to find
7
+ * the closest ancestor with a given attribute.
8
+ *
9
+ * @param {Node} startNode - The node to start from
10
+ * @param {string} attrName - Attribute name to match
11
+ * @returns {Element|null}
12
+ */
13
+ closestWithAttribute(startNode, attrName) {
14
+ let node = startNode;
15
+
16
+ while (node) {
17
+ // Only check Elements
18
+ if (node.nodeType === Node.ELEMENT_NODE && node.hasAttribute(attrName)) {
19
+ return node;
20
+ }
21
+
22
+ // Normal DOM parent
23
+ if (node.parentNode) {
24
+ node = node.parentNode;
25
+ continue;
26
+ }
27
+
28
+ // Cross Shadow DOM boundary
29
+ if (node instanceof ShadowRoot) {
30
+ node = node.host;
31
+ continue;
32
+ }
33
+
34
+ // If we're inside a shadow tree and parentNode is null
35
+ if (node.getRootNode) {
36
+ const root = node.getRootNode();
37
+ if (root instanceof ShadowRoot) {
38
+ node = root.host;
39
+ continue;
40
+ }
41
+ }
42
+
43
+ // Nothing left to traverse
44
+ node = null;
45
+ }
46
+
47
+ return null;
48
+ }
49
+
50
+ /**
51
+ * If the locale wasn't set via attribute on `elem`,
52
+ * then use the closest `data-locale` attribute crawling up the DOM tree.
53
+ * If none is found, default to 'en-US'.
54
+ */
55
+ getLocale(elem) {
56
+ let locale = "en-US";
57
+
58
+ try {
59
+ if (elem.hasAttribute("locale")) {
60
+ locale = elem.getAttribute("locale");
61
+ } else {
62
+ const closestLocaleElement = this.closestWithAttribute(
63
+ elem,
64
+ "data-locale",
65
+ );
66
+
67
+ if (closestLocaleElement) {
68
+ locale = closestLocaleElement.getAttribute("data-locale");
69
+ }
70
+ }
71
+ } catch (error) {
72
+ if (!elem) {
73
+ console.debug(
74
+ "Auro getLocale: No element provided, defaulting to 'en-US'",
75
+ );
76
+ } else {
77
+ console.debug(
78
+ "Auro getLocale: Error accessing attributes, defaulting to 'en-US'",
79
+ );
80
+ }
81
+ }
82
+
83
+ return locale;
84
+ }
85
+ }
@@ -0,0 +1 @@
1
+ export * from "./domHandler.mjs";
@@ -1,12 +1,17 @@
1
1
  /* eslint-disable line-comment-position, no-inline-comments */
2
2
 
3
- import { autoUpdate, computePosition, offset, autoPlacement, flip, shift } from '@floating-ui/dom';
4
-
3
+ import {
4
+ autoPlacement,
5
+ autoUpdate,
6
+ computePosition,
7
+ flip,
8
+ offset,
9
+ shift,
10
+ } from "@floating-ui/dom";
5
11
 
6
12
  const MAX_CONFIGURATION_COUNT = 10;
7
13
 
8
14
  export default class AuroFloatingUI {
9
-
10
15
  /**
11
16
  * @private
12
17
  */
@@ -21,7 +26,11 @@ export default class AuroFloatingUI {
21
26
  * @private
22
27
  */
23
28
  static setupMousePressChecker() {
24
- if (!AuroFloatingUI.isMousePressHandlerInitialized && window && window.addEventListener) {
29
+ if (
30
+ !AuroFloatingUI.isMousePressHandlerInitialized &&
31
+ window &&
32
+ window.addEventListener
33
+ ) {
25
34
  AuroFloatingUI.isMousePressHandlerInitialized = true;
26
35
 
27
36
  // Track timeout for isMousePressed reset to avoid race conditions
@@ -29,7 +38,7 @@ export default class AuroFloatingUI {
29
38
  AuroFloatingUI._mousePressedTimeout = null;
30
39
  }
31
40
  const mouseEventGlobalHandler = (event) => {
32
- const isPressed = event.type === 'mousedown';
41
+ const isPressed = event.type === "mousedown";
33
42
  if (isPressed) {
34
43
  // Clear any pending timeout to prevent race condition
35
44
  if (AuroFloatingUI._mousePressedTimeout !== null) {
@@ -48,8 +57,8 @@ export default class AuroFloatingUI {
48
57
  }
49
58
  };
50
59
 
51
- window.addEventListener('mousedown', mouseEventGlobalHandler);
52
- window.addEventListener('mouseup', mouseEventGlobalHandler);
60
+ window.addEventListener("mousedown", mouseEventGlobalHandler);
61
+ window.addEventListener("mouseup", mouseEventGlobalHandler);
53
62
  }
54
63
  }
55
64
 
@@ -97,11 +106,12 @@ export default class AuroFloatingUI {
97
106
  // mirror the boxsize from bibSizer
98
107
  if (this.element.bibSizer && this.element.matchWidth) {
99
108
  const sizerStyle = window.getComputedStyle(this.element.bibSizer);
100
- const bibContent = this.element.bib.shadowRoot.querySelector(".container");
101
- if (sizerStyle.width !== '0px') {
109
+ const bibContent =
110
+ this.element.bib.shadowRoot.querySelector(".container");
111
+ if (sizerStyle.width !== "0px") {
102
112
  bibContent.style.width = sizerStyle.width;
103
113
  }
104
- if (sizerStyle.height !== '0px') {
114
+ if (sizerStyle.height !== "0px") {
105
115
  bibContent.style.height = sizerStyle.height;
106
116
  }
107
117
  bibContent.style.maxWidth = sizerStyle.maxWidth;
@@ -119,28 +129,34 @@ export default class AuroFloatingUI {
119
129
  * @returns {String} The positioning strategy, one of 'fullscreen', 'floating', 'cover'.
120
130
  */
121
131
  getPositioningStrategy() {
122
- const breakpoint = this.element.bib.mobileFullscreenBreakpoint || this.element.floaterConfig?.fullscreenBreakpoint;
132
+ const breakpoint =
133
+ this.element.bib.mobileFullscreenBreakpoint ||
134
+ this.element.floaterConfig?.fullscreenBreakpoint;
123
135
  switch (this.behavior) {
124
136
  case "tooltip":
125
137
  return "floating";
126
138
  case "dialog":
127
139
  case "drawer":
128
140
  if (breakpoint) {
129
- const smallerThanBreakpoint = window.matchMedia(`(max-width: ${breakpoint})`).matches;
141
+ const smallerThanBreakpoint = window.matchMedia(
142
+ `(max-width: ${breakpoint})`,
143
+ ).matches;
130
144
 
131
145
  this.element.expanded = smallerThanBreakpoint;
132
146
  }
133
147
  if (this.element.nested) {
134
148
  return "cover";
135
149
  }
136
- return 'fullscreen';
150
+ return "fullscreen";
137
151
  case "dropdown":
138
152
  case undefined:
139
153
  case null:
140
154
  if (breakpoint) {
141
- const smallerThanBreakpoint = window.matchMedia(`(max-width: ${breakpoint})`).matches;
155
+ const smallerThanBreakpoint = window.matchMedia(
156
+ `(max-width: ${breakpoint})`,
157
+ ).matches;
142
158
  if (smallerThanBreakpoint) {
143
- return 'fullscreen';
159
+ return "fullscreen";
144
160
  }
145
161
  }
146
162
  return "floating";
@@ -161,37 +177,39 @@ export default class AuroFloatingUI {
161
177
  const strategy = this.getPositioningStrategy();
162
178
  this.configureBibStrategy(strategy);
163
179
 
164
- if (strategy === 'floating') {
180
+ if (strategy === "floating") {
165
181
  this.mirrorSize();
166
182
  // Define the middlware for the floater configuration
167
183
  const middleware = [
168
184
  offset(this.element.floaterConfig?.offset || 0),
169
- ...this.element.floaterConfig?.shift ? [shift()] : [], // Add shift middleware if shift is enabled.
170
- ...this.element.floaterConfig?.flip ? [flip()] : [], // Add flip middleware if flip is enabled.
171
- ...this.element.floaterConfig?.autoPlacement ? [autoPlacement()] : [], // Add autoPlacement middleware if autoPlacement is enabled.
185
+ ...(this.element.floaterConfig?.shift ? [shift()] : []), // Add shift middleware if shift is enabled.
186
+ ...(this.element.floaterConfig?.flip ? [flip()] : []), // Add flip middleware if flip is enabled.
187
+ ...(this.element.floaterConfig?.autoPlacement ? [autoPlacement()] : []), // Add autoPlacement middleware if autoPlacement is enabled.
172
188
  ];
173
189
 
174
190
  // Compute the position of the bib
175
191
  computePosition(this.element.trigger, this.element.bib, {
176
- strategy: this.element.floaterConfig?.strategy || 'fixed',
192
+ strategy: this.element.floaterConfig?.strategy || "fixed",
177
193
  placement: this.element.floaterConfig?.placement,
178
- middleware: middleware || []
179
- }).then(({ x, y }) => { // eslint-disable-line id-length
194
+ middleware: middleware || [],
195
+ }).then(({ x, y }) => {
196
+ // eslint-disable-line id-length
180
197
  Object.assign(this.element.bib.style, {
181
198
  left: `${x}px`,
182
199
  top: `${y}px`,
183
200
  });
184
201
  });
185
- } else if (strategy === 'cover') {
202
+ } else if (strategy === "cover") {
186
203
  // Compute the position of the bib
187
204
  computePosition(this.element.parentNode, this.element.bib, {
188
- placement: 'bottom-start'
189
- }).then(({ x, y }) => { // eslint-disable-line id-length
205
+ placement: "bottom-start",
206
+ }).then(({ x, y }) => {
207
+ // eslint-disable-line id-length
190
208
  Object.assign(this.element.bib.style, {
191
209
  left: `${x}px`,
192
210
  top: `${y - this.element.parentNode.offsetHeight}px`,
193
211
  width: `${this.element.parentNode.offsetWidth}px`,
194
- height: `${this.element.parentNode.offsetHeight}px`
212
+ height: `${this.element.parentNode.offsetHeight}px`,
195
213
  });
196
214
  });
197
215
  }
@@ -204,12 +222,12 @@ export default class AuroFloatingUI {
204
222
  */
205
223
  lockScroll(lock = true) {
206
224
  if (lock) {
207
- document.body.style.overflow = 'hidden'; // hide body's scrollbar
225
+ document.body.style.overflow = "hidden"; // hide body's scrollbar
208
226
 
209
227
  // Move `bib` by the amount the viewport is shifted to stay aligned in fullscreen.
210
228
  this.element.bib.style.transform = `translateY(${window?.visualViewport?.offsetTop}px)`;
211
229
  } else {
212
- document.body.style.overflow = '';
230
+ document.body.style.overflow = "";
213
231
  }
214
232
  }
215
233
 
@@ -223,23 +241,24 @@ export default class AuroFloatingUI {
223
241
  * @param {string} strategy - The positioning strategy ('fullscreen' or 'floating').
224
242
  */
225
243
  configureBibStrategy(value) {
226
- if (value === 'fullscreen') {
244
+ if (value === "fullscreen") {
227
245
  this.element.isBibFullscreen = true;
228
246
  // reset the prev position
229
- this.element.bib.setAttribute('isfullscreen', "");
230
- this.element.bib.style.position = 'fixed';
247
+ this.element.bib.setAttribute("isfullscreen", "");
248
+ this.element.bib.style.position = "fixed";
231
249
  this.element.bib.style.top = "0px";
232
250
  this.element.bib.style.left = "0px";
233
- this.element.bib.style.width = '';
234
- this.element.bib.style.height = '';
235
- this.element.style.contain = '';
251
+ this.element.bib.style.width = "";
252
+ this.element.bib.style.height = "";
253
+ this.element.style.contain = "";
236
254
 
237
255
  // reset the size that was mirroring `size` css-part
238
- const bibContent = this.element.bib.shadowRoot.querySelector(".container");
256
+ const bibContent =
257
+ this.element.bib.shadowRoot.querySelector(".container");
239
258
  if (bibContent) {
240
- bibContent.style.width = '';
241
- bibContent.style.height = '';
242
- bibContent.style.maxWidth = '';
259
+ bibContent.style.width = "";
260
+ bibContent.style.height = "";
261
+ bibContent.style.maxWidth = "";
243
262
  bibContent.style.maxHeight = `${window?.visualViewport?.height}px`;
244
263
  this.configureTrial = 0;
245
264
  } else if (this.configureTrial < MAX_CONFIGURATION_COUNT) {
@@ -254,21 +273,26 @@ export default class AuroFloatingUI {
254
273
  this.lockScroll(true);
255
274
  }
256
275
  } else {
257
- this.element.bib.style.position = '';
258
- this.element.bib.removeAttribute('isfullscreen');
276
+ this.element.bib.style.position = "";
277
+ this.element.bib.removeAttribute("isfullscreen");
259
278
  this.element.isBibFullscreen = false;
260
- this.element.style.contain = 'layout';
279
+ this.element.style.contain = "layout";
261
280
  }
262
281
 
263
282
  const isChanged = this.strategy && this.strategy !== value;
264
283
  this.strategy = value;
265
284
  if (isChanged) {
266
- const event = new CustomEvent(this.eventPrefix ? `${this.eventPrefix}-strategy-change` : 'strategy-change', {
267
- detail: {
268
- value,
285
+ const event = new CustomEvent(
286
+ this.eventPrefix
287
+ ? `${this.eventPrefix}-strategy-change`
288
+ : "strategy-change",
289
+ {
290
+ detail: {
291
+ value,
292
+ },
293
+ composed: true,
269
294
  },
270
- composed: true
271
- });
295
+ );
272
296
 
273
297
  this.element.dispatchEvent(event);
274
298
  }
@@ -300,19 +324,24 @@ export default class AuroFloatingUI {
300
324
  return;
301
325
  }
302
326
 
303
- if (this.element.noHideOnThisFocusLoss ||
304
- this.element.hasAttribute('noHideOnThisFocusLoss')) {
327
+ if (
328
+ this.element.noHideOnThisFocusLoss ||
329
+ this.element.hasAttribute("noHideOnThisFocusLoss")
330
+ ) {
305
331
  return;
306
332
  }
307
333
 
308
334
  const { activeElement } = document;
309
335
  // if focus is still inside of trigger or bib, do not close
310
- if (this.element.contains(activeElement) || this.element.bib?.contains(activeElement)) {
336
+ if (
337
+ this.element.contains(activeElement) ||
338
+ this.element.bib?.contains(activeElement)
339
+ ) {
311
340
  return;
312
341
  }
313
342
 
314
343
  // if fullscreen bib is in fullscreen mode, do not close
315
- if (this.element.bib.hasAttribute('isfullscreen')) {
344
+ if (this.element.bib.hasAttribute("isfullscreen")) {
316
345
  return;
317
346
  }
318
347
 
@@ -324,12 +353,27 @@ export default class AuroFloatingUI {
324
353
  this.focusHandler = () => this.handleFocusLoss();
325
354
 
326
355
  this.clickHandler = (evt) => {
327
- if ((!evt.composedPath().includes(this.element.trigger) &&
328
- !evt.composedPath().includes(this.element.bib)) ||
329
- (this.element.bib.backdrop && evt.composedPath().includes(this.element.bib.backdrop))) {
330
- const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
356
+ // When the bib is fullscreen (modal dialog), don't close on outside
357
+ // clicks. VoiceOver's synthetic click events inside a top-layer modal
358
+ // <dialog> may not include the bib in composedPath(), causing false
359
+ // positives. This mirrors the fullscreen guard in handleFocusLoss().
360
+ if (this.element.bib && this.element.bib.hasAttribute("isfullscreen")) {
361
+ return;
362
+ }
331
363
 
332
- if (existedVisibleFloatingUI && existedVisibleFloatingUI.element.isPopoverVisible) {
364
+ if (
365
+ (!evt.composedPath().includes(this.element.trigger) &&
366
+ !evt.composedPath().includes(this.element.bib)) ||
367
+ (this.element.bib.backdrop &&
368
+ evt.composedPath().includes(this.element.bib.backdrop))
369
+ ) {
370
+ const existedVisibleFloatingUI =
371
+ document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
372
+
373
+ if (
374
+ existedVisibleFloatingUI &&
375
+ existedVisibleFloatingUI.element.isPopoverVisible
376
+ ) {
333
377
  // if something else is open, close that
334
378
  existedVisibleFloatingUI.hideBib();
335
379
  document.expandedAuroFormkitDropdown = null;
@@ -342,9 +386,14 @@ export default class AuroFloatingUI {
342
386
 
343
387
  // ESC key handler
344
388
  this.keyDownHandler = (evt) => {
345
- if (evt.key === 'Escape' && this.element.isPopoverVisible) {
346
- const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
347
- if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this && existedVisibleFloatingUI.element.isPopoverVisible) {
389
+ if (evt.key === "Escape" && this.element.isPopoverVisible) {
390
+ const existedVisibleFloatingUI =
391
+ document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
392
+ if (
393
+ existedVisibleFloatingUI &&
394
+ existedVisibleFloatingUI !== this &&
395
+ existedVisibleFloatingUI.element.isPopoverVisible
396
+ ) {
348
397
  // if something else is open, let it handle itself
349
398
  return;
350
399
  }
@@ -352,17 +401,17 @@ export default class AuroFloatingUI {
352
401
  }
353
402
  };
354
403
 
355
- if (this.behavior !== 'drawer' && this.behavior !== 'dialog') {
404
+ if (this.behavior !== "drawer" && this.behavior !== "dialog") {
356
405
  // Add event listeners using the stored references
357
- document.addEventListener('focusin', this.focusHandler);
406
+ document.addEventListener("focusin", this.focusHandler);
358
407
  }
359
408
 
360
- document.addEventListener('keydown', this.keyDownHandler);
409
+ document.addEventListener("keydown", this.keyDownHandler);
361
410
 
362
411
  // send this task to the end of queue to prevent conflicting
363
412
  // it conflicts if showBib gets call from a button that's not this.element.trigger
364
413
  setTimeout(() => {
365
- window.addEventListener('click', this.clickHandler);
414
+ window.addEventListener("click", this.clickHandler);
366
415
  }, 0);
367
416
  }
368
417
 
@@ -370,34 +419,38 @@ export default class AuroFloatingUI {
370
419
  // Remove event listeners if they exist
371
420
 
372
421
  if (this.focusHandler) {
373
- document.removeEventListener('focusin', this.focusHandler);
422
+ document.removeEventListener("focusin", this.focusHandler);
374
423
  this.focusHandler = null;
375
424
  }
376
425
 
377
426
  if (this.clickHandler) {
378
- window.removeEventListener('click', this.clickHandler);
427
+ window.removeEventListener("click", this.clickHandler);
379
428
  this.clickHandler = null;
380
429
  }
381
430
 
382
431
  if (this.keyDownHandler) {
383
- document.removeEventListener('keydown', this.keyDownHandler);
432
+ document.removeEventListener("keydown", this.keyDownHandler);
384
433
  this.keyDownHandler = null;
385
434
  }
386
435
  }
387
436
 
388
437
  handleUpdate(changedProperties) {
389
- if (changedProperties.has('isPopoverVisible')) {
438
+ if (changedProperties.has("isPopoverVisible")) {
390
439
  this.updateState();
391
440
  }
392
441
  }
393
442
 
394
443
  updateCurrentExpandedDropdown() {
395
444
  // Close any other dropdown that is already open
396
- const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
397
- if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this &&
445
+ const existedVisibleFloatingUI =
446
+ document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
447
+ if (
448
+ existedVisibleFloatingUI &&
449
+ existedVisibleFloatingUI !== this &&
398
450
  existedVisibleFloatingUI.element.isPopoverVisible &&
399
- document.expandedAuroFloater.eventPrefix === this.eventPrefix) {
400
- document.expandedAuroFloater.hideBib();
451
+ existedVisibleFloatingUI.eventPrefix === this.eventPrefix
452
+ ) {
453
+ existedVisibleFloatingUI.hideBib();
401
454
  }
402
455
 
403
456
  document.expandedAuroFloater = this;
@@ -406,7 +459,7 @@ export default class AuroFloatingUI {
406
459
  showBib() {
407
460
  if (!this.element.disabled && !this.showing) {
408
461
  this.updateCurrentExpandedDropdown();
409
- this.element.triggerChevron?.setAttribute('data-expanded', true);
462
+ this.element.triggerChevron?.setAttribute("data-expanded", true);
410
463
 
411
464
  // prevent double showing: isPopovervisible gets first and showBib gets called later
412
465
  if (!this.showing) {
@@ -420,9 +473,13 @@ export default class AuroFloatingUI {
420
473
  }
421
474
 
422
475
  // Setup auto update to handle resize and scroll
423
- this.element.cleanup = autoUpdate(this.element.trigger || this.element.parentNode, this.element.bib, () => {
424
- this.position();
425
- });
476
+ this.element.cleanup = autoUpdate(
477
+ this.element.trigger || this.element.parentNode,
478
+ this.element.bib,
479
+ () => {
480
+ this.position();
481
+ },
482
+ );
426
483
  }
427
484
  }
428
485
 
@@ -433,7 +490,7 @@ export default class AuroFloatingUI {
433
490
  hideBib(eventType = "unknown") {
434
491
  if (!this.element.disabled && !this.element.noToggle) {
435
492
  this.lockScroll(false);
436
- this.element.triggerChevron?.removeAttribute('data-expanded');
493
+ this.element.triggerChevron?.removeAttribute("data-expanded");
437
494
 
438
495
  if (this.element.isPopoverVisible) {
439
496
  this.element.isPopoverVisible = false;
@@ -453,13 +510,16 @@ export default class AuroFloatingUI {
453
510
  * @param {String} eventType - The event type that triggered the toggle action.
454
511
  */
455
512
  dispatchEventDropdownToggle(eventType) {
456
- const event = new CustomEvent(this.eventPrefix ? `${this.eventPrefix}-toggled` : 'toggled', {
457
- detail: {
458
- expanded: this.showing,
459
- eventType: eventType || "unknown",
513
+ const event = new CustomEvent(
514
+ this.eventPrefix ? `${this.eventPrefix}-toggled` : "toggled",
515
+ {
516
+ detail: {
517
+ expanded: this.showing,
518
+ eventType: eventType || "unknown",
519
+ },
520
+ composed: true,
460
521
  },
461
- composed: true
462
- });
522
+ );
463
523
 
464
524
  this.element.dispatchEvent(event);
465
525
  }
@@ -471,12 +531,15 @@ export default class AuroFloatingUI {
471
531
  this.showBib();
472
532
  }
473
533
 
474
- const event = new CustomEvent(this.eventPrefix ? `${this.eventPrefix}-triggerClick` : "triggerClick", {
475
- composed: true,
476
- detail: {
477
- expanded: this.element.isPopoverVisible
478
- }
479
- });
534
+ const event = new CustomEvent(
535
+ this.eventPrefix ? `${this.eventPrefix}-triggerClick` : "triggerClick",
536
+ {
537
+ composed: true,
538
+ detail: {
539
+ expanded: this.element.isPopoverVisible,
540
+ },
541
+ },
542
+ );
480
543
 
481
544
  this.element.dispatchEvent(event);
482
545
  }
@@ -484,30 +547,32 @@ export default class AuroFloatingUI {
484
547
  handleEvent(event) {
485
548
  if (!this.element.disableEventShow) {
486
549
  switch (event.type) {
487
- case 'keydown':
550
+ case "keydown": {
488
551
  // Support both Enter and Space keys for accessibility
489
552
  // Space is included as it's expected behavior for interactive elements
490
553
 
491
554
  const origin = event.composedPath()[0];
492
- if (event.key === 'Enter' || event.key === ' ' && (!origin || origin.tagName !== "INPUT")) {
493
-
555
+ if (
556
+ event.key === "Enter" ||
557
+ (event.key === " " && (!origin || origin.tagName !== "INPUT"))
558
+ ) {
494
559
  event.preventDefault();
495
560
  this.handleClick();
496
561
  }
497
562
  break;
498
- case 'mouseenter':
563
+ }
564
+ case "mouseenter":
499
565
  if (this.element.hoverToggle) {
500
566
  this.showBib();
501
567
  }
502
568
  break;
503
- case 'mouseleave':
569
+ case "mouseleave":
504
570
  if (this.element.hoverToggle) {
505
571
  this.hideBib("mouseleave");
506
572
  }
507
573
  break;
508
- case 'focus':
574
+ case "focus":
509
575
  if (this.element.focusShow) {
510
-
511
576
  /*
512
577
  This needs to better handle clicking that gives focus -
513
578
  currently it shows and then immediately hides the bib
@@ -515,12 +580,12 @@ export default class AuroFloatingUI {
515
580
  this.showBib();
516
581
  }
517
582
  break;
518
- case 'blur':
583
+ case "blur":
519
584
  // send this task 100ms later queue to
520
585
  // wait a frame in case focus moves within the floating element/bib
521
586
  setTimeout(() => this.handleFocusLoss(), 0);
522
587
  break;
523
- case 'click':
588
+ case "click":
524
589
  if (document.activeElement === document.body) {
525
590
  event.currentTarget.focus();
526
591
  }
@@ -540,15 +605,15 @@ export default class AuroFloatingUI {
540
605
  */
541
606
  handleTriggerTabIndex() {
542
607
  const focusableElementSelectors = [
543
- 'a',
544
- 'button',
608
+ "a",
609
+ "button",
545
610
  'input:not([type="hidden"])',
546
- 'select',
547
- 'textarea',
611
+ "select",
612
+ "textarea",
548
613
  '[tabindex]:not([tabindex="-1"])',
549
- 'auro-button',
550
- 'auro-input',
551
- 'auro-hyperlink'
614
+ "auro-button",
615
+ "auro-input",
616
+ "auro-hyperlink",
552
617
  ];
553
618
 
554
619
  const triggerNode = this.element.querySelectorAll('[slot="trigger"]')[0];
@@ -576,10 +641,10 @@ export default class AuroFloatingUI {
576
641
  * @param {*} eventPrefix
577
642
  */
578
643
  regenerateBibId() {
579
- this.id = this.element.getAttribute('id');
644
+ this.id = this.element.getAttribute("id");
580
645
  if (!this.id) {
581
646
  this.id = window.crypto.randomUUID();
582
- this.element.setAttribute('id', this.id);
647
+ this.element.setAttribute("id", this.id);
583
648
  }
584
649
 
585
650
  this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
@@ -600,11 +665,15 @@ export default class AuroFloatingUI {
600
665
  if (this.element.trigger) {
601
666
  this.disconnect();
602
667
  }
603
- this.element.trigger = this.element.triggerElement || this.element.shadowRoot.querySelector('#trigger') || this.element.trigger;
604
- this.element.bib = this.element.shadowRoot.querySelector('#bib') || this.element.bib;
605
- this.element.bibSizer = this.element.shadowRoot.querySelector('#bibSizer');
606
- this.element.triggerChevron = this.element.shadowRoot.querySelector('#showStateIcon');
607
-
668
+ this.element.trigger =
669
+ this.element.triggerElement ||
670
+ this.element.shadowRoot.querySelector("#trigger") ||
671
+ this.element.trigger;
672
+ this.element.bib =
673
+ this.element.shadowRoot.querySelector("#bib") || this.element.bib;
674
+ this.element.bibSizer = this.element.shadowRoot.querySelector("#bibSizer");
675
+ this.element.triggerChevron =
676
+ this.element.shadowRoot.querySelector("#showStateIcon");
608
677
 
609
678
  if (this.element.floaterConfig) {
610
679
  this.element.hoverToggle = this.element.floaterConfig.hoverToggle;
@@ -615,12 +684,12 @@ export default class AuroFloatingUI {
615
684
 
616
685
  this.handleEvent = this.handleEvent.bind(this);
617
686
  if (this.element.trigger) {
618
- this.element.trigger.addEventListener('keydown', this.handleEvent);
619
- this.element.trigger.addEventListener('click', this.handleEvent);
620
- this.element.trigger.addEventListener('mouseenter', this.handleEvent);
621
- this.element.trigger.addEventListener('mouseleave', this.handleEvent);
622
- this.element.trigger.addEventListener('focus', this.handleEvent);
623
- this.element.trigger.addEventListener('blur', this.handleEvent);
687
+ this.element.trigger.addEventListener("keydown", this.handleEvent);
688
+ this.element.trigger.addEventListener("click", this.handleEvent);
689
+ this.element.trigger.addEventListener("mouseenter", this.handleEvent);
690
+ this.element.trigger.addEventListener("mouseleave", this.handleEvent);
691
+ this.element.trigger.addEventListener("focus", this.handleEvent);
692
+ this.element.trigger.addEventListener("blur", this.handleEvent);
624
693
  }
625
694
  }
626
695
 
@@ -635,12 +704,18 @@ export default class AuroFloatingUI {
635
704
 
636
705
  // Remove event & keyboard listeners
637
706
  if (this.element?.trigger) {
638
- this.element.trigger.removeEventListener('keydown', this.handleEvent);
639
- this.element.trigger.removeEventListener('click', this.handleEvent);
640
- this.element.trigger.removeEventListener('mouseenter', this.handleEvent);
641
- this.element.trigger.removeEventListener('mouseleave', this.handleEvent);
642
- this.element.trigger.removeEventListener('focus', this.handleEvent);
643
- this.element.trigger.removeEventListener('blur', this.handleEvent);
707
+ this.element.trigger.removeEventListener("keydown", this.handleEvent);
708
+ this.element.trigger.removeEventListener("click", this.handleEvent);
709
+ this.element.trigger.removeEventListener(
710
+ "mouseenter",
711
+ this.handleEvent,
712
+ );
713
+ this.element.trigger.removeEventListener(
714
+ "mouseleave",
715
+ this.handleEvent,
716
+ );
717
+ this.element.trigger.removeEventListener("focus", this.handleEvent);
718
+ this.element.trigger.removeEventListener("blur", this.handleEvent);
644
719
  }
645
720
  }
646
721
  }