@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.
|
|
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 {
|
|
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 (
|
|
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 ===
|
|
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(
|
|
52
|
-
window.addEventListener(
|
|
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 =
|
|
101
|
-
|
|
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 !==
|
|
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 =
|
|
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(
|
|
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
|
|
150
|
+
return "fullscreen";
|
|
137
151
|
case "dropdown":
|
|
138
152
|
case undefined:
|
|
139
153
|
case null:
|
|
140
154
|
if (breakpoint) {
|
|
141
|
-
const smallerThanBreakpoint = window.matchMedia(
|
|
155
|
+
const smallerThanBreakpoint = window.matchMedia(
|
|
156
|
+
`(max-width: ${breakpoint})`,
|
|
157
|
+
).matches;
|
|
142
158
|
if (smallerThanBreakpoint) {
|
|
143
|
-
return
|
|
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 ===
|
|
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 ||
|
|
192
|
+
strategy: this.element.floaterConfig?.strategy || "fixed",
|
|
177
193
|
placement: this.element.floaterConfig?.placement,
|
|
178
|
-
middleware: middleware || []
|
|
179
|
-
}).then(({ x, y }) => {
|
|
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 ===
|
|
202
|
+
} else if (strategy === "cover") {
|
|
186
203
|
// Compute the position of the bib
|
|
187
204
|
computePosition(this.element.parentNode, this.element.bib, {
|
|
188
|
-
placement:
|
|
189
|
-
}).then(({ x, y }) => {
|
|
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 =
|
|
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 ===
|
|
244
|
+
if (value === "fullscreen") {
|
|
227
245
|
this.element.isBibFullscreen = true;
|
|
228
246
|
// reset the prev position
|
|
229
|
-
this.element.bib.setAttribute(
|
|
230
|
-
this.element.bib.style.position =
|
|
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 =
|
|
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(
|
|
276
|
+
this.element.bib.style.position = "";
|
|
277
|
+
this.element.bib.removeAttribute("isfullscreen");
|
|
259
278
|
this.element.isBibFullscreen = false;
|
|
260
|
-
this.element.style.contain =
|
|
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(
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
|
|
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 (
|
|
304
|
-
this.element.
|
|
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 (
|
|
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(
|
|
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
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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
|
-
|
|
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 ===
|
|
346
|
-
const existedVisibleFloatingUI =
|
|
347
|
-
|
|
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 !==
|
|
404
|
+
if (this.behavior !== "drawer" && this.behavior !== "dialog") {
|
|
356
405
|
// Add event listeners using the stored references
|
|
357
|
-
document.addEventListener(
|
|
406
|
+
document.addEventListener("focusin", this.focusHandler);
|
|
358
407
|
}
|
|
359
408
|
|
|
360
|
-
document.addEventListener(
|
|
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(
|
|
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(
|
|
422
|
+
document.removeEventListener("focusin", this.focusHandler);
|
|
374
423
|
this.focusHandler = null;
|
|
375
424
|
}
|
|
376
425
|
|
|
377
426
|
if (this.clickHandler) {
|
|
378
|
-
window.removeEventListener(
|
|
427
|
+
window.removeEventListener("click", this.clickHandler);
|
|
379
428
|
this.clickHandler = null;
|
|
380
429
|
}
|
|
381
430
|
|
|
382
431
|
if (this.keyDownHandler) {
|
|
383
|
-
document.removeEventListener(
|
|
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(
|
|
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 =
|
|
397
|
-
|
|
445
|
+
const existedVisibleFloatingUI =
|
|
446
|
+
document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
|
|
447
|
+
if (
|
|
448
|
+
existedVisibleFloatingUI &&
|
|
449
|
+
existedVisibleFloatingUI !== this &&
|
|
398
450
|
existedVisibleFloatingUI.element.isPopoverVisible &&
|
|
399
|
-
|
|
400
|
-
|
|
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(
|
|
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(
|
|
424
|
-
this.
|
|
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(
|
|
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(
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
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
|
-
|
|
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(
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
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
|
|
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 (
|
|
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
|
-
|
|
563
|
+
}
|
|
564
|
+
case "mouseenter":
|
|
499
565
|
if (this.element.hoverToggle) {
|
|
500
566
|
this.showBib();
|
|
501
567
|
}
|
|
502
568
|
break;
|
|
503
|
-
case
|
|
569
|
+
case "mouseleave":
|
|
504
570
|
if (this.element.hoverToggle) {
|
|
505
571
|
this.hideBib("mouseleave");
|
|
506
572
|
}
|
|
507
573
|
break;
|
|
508
|
-
case
|
|
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
|
|
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
|
|
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
|
-
|
|
544
|
-
|
|
608
|
+
"a",
|
|
609
|
+
"button",
|
|
545
610
|
'input:not([type="hidden"])',
|
|
546
|
-
|
|
547
|
-
|
|
611
|
+
"select",
|
|
612
|
+
"textarea",
|
|
548
613
|
'[tabindex]:not([tabindex="-1"])',
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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(
|
|
644
|
+
this.id = this.element.getAttribute("id");
|
|
580
645
|
if (!this.id) {
|
|
581
646
|
this.id = window.crypto.randomUUID();
|
|
582
|
-
this.element.setAttribute(
|
|
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 =
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
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(
|
|
619
|
-
this.element.trigger.addEventListener(
|
|
620
|
-
this.element.trigger.addEventListener(
|
|
621
|
-
this.element.trigger.addEventListener(
|
|
622
|
-
this.element.trigger.addEventListener(
|
|
623
|
-
this.element.trigger.addEventListener(
|
|
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(
|
|
639
|
-
this.element.trigger.removeEventListener(
|
|
640
|
-
this.element.trigger.removeEventListener(
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
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
|
}
|