@aurodesignsystem/auro-library 5.11.0 → 5.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/package.json +1 -1
- package/scripts/runtime/floatingUI.mjs +220 -132
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Semantic Release Automated Changelog
|
|
2
2
|
|
|
3
|
+
## [5.11.2](https://github.com/AlaskaAirlines/auro-library/compare/v5.11.1...v5.11.2) (2026-03-17)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* prevent dropdown from closing on click for noToggle elements AB[#1494298](https://github.com/AlaskaAirlines/auro-library/issues/1494298) ([4d23b40](https://github.com/AlaskaAirlines/auro-library/commit/4d23b4082c8e22d9a865ba51b702f70185cfd455))
|
|
9
|
+
* return comment ([d2b315c](https://github.com/AlaskaAirlines/auro-library/commit/d2b315c0ca08d724ac6239d0e25b6127173f990e))
|
|
10
|
+
* simplify hideBib logic with early returns for readability ([bd4038d](https://github.com/AlaskaAirlines/auro-library/commit/bd4038dce05969e18e87910a234344f95c729ac2))
|
|
11
|
+
|
|
12
|
+
## [5.11.1](https://github.com/AlaskaAirlines/auro-library/compare/v5.11.0...v5.11.1) (2026-03-04)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* prevent TypeError in updateCurrentExpandedDropdown when expandedAuroFloater is undefined ([8fb98bc](https://github.com/AlaskaAirlines/auro-library/commit/8fb98bc1ea1ce5d1643cdb406cb5cbd239ca4476))
|
|
18
|
+
* 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)
|
|
19
|
+
|
|
3
20
|
# [5.11.0](https://github.com/AlaskaAirlines/auro-library/compare/v5.10.0...v5.11.0) (2026-02-20)
|
|
4
21
|
|
|
5
22
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aurodesignsystem/auro-library",
|
|
3
|
-
"version": "5.11.
|
|
3
|
+
"version": "5.11.2",
|
|
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",
|
|
@@ -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
|
|
|
@@ -431,19 +488,32 @@ export default class AuroFloatingUI {
|
|
|
431
488
|
* @param {String} eventType - The event type that triggered the hiding action.
|
|
432
489
|
*/
|
|
433
490
|
hideBib(eventType = "unknown") {
|
|
434
|
-
if (
|
|
435
|
-
|
|
436
|
-
|
|
491
|
+
if (this.element.disabled) {
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
437
494
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
495
|
+
// noToggle dropdowns should not close when the trigger is clicked (the
|
|
496
|
+
// "toggle" behavior), but they CAN still close via other interactions like
|
|
497
|
+
// Escape key or focus loss.
|
|
498
|
+
if (this.element.noToggle && eventType === "click") {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
this.lockScroll(false);
|
|
503
|
+
this.element.triggerChevron?.removeAttribute("data-expanded");
|
|
504
|
+
|
|
505
|
+
if (this.element.isPopoverVisible) {
|
|
506
|
+
this.element.isPopoverVisible = false;
|
|
446
507
|
}
|
|
508
|
+
if (this.showing) {
|
|
509
|
+
this.cleanupHideHandlers();
|
|
510
|
+
this.showing = false;
|
|
511
|
+
this.dispatchEventDropdownToggle(eventType);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Only clear the global reference if the bib was actually hidden.
|
|
515
|
+
// Clearing it when hideBib is blocked (e.g. noToggle + click) corrupts
|
|
516
|
+
// the singleton state so other dropdowns can't detect this one is still open.
|
|
447
517
|
document.expandedAuroFloater = null;
|
|
448
518
|
}
|
|
449
519
|
|
|
@@ -453,13 +523,16 @@ export default class AuroFloatingUI {
|
|
|
453
523
|
* @param {String} eventType - The event type that triggered the toggle action.
|
|
454
524
|
*/
|
|
455
525
|
dispatchEventDropdownToggle(eventType) {
|
|
456
|
-
const event = new CustomEvent(
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
526
|
+
const event = new CustomEvent(
|
|
527
|
+
this.eventPrefix ? `${this.eventPrefix}-toggled` : "toggled",
|
|
528
|
+
{
|
|
529
|
+
detail: {
|
|
530
|
+
expanded: this.showing,
|
|
531
|
+
eventType: eventType || "unknown",
|
|
532
|
+
},
|
|
533
|
+
composed: true,
|
|
460
534
|
},
|
|
461
|
-
|
|
462
|
-
});
|
|
535
|
+
);
|
|
463
536
|
|
|
464
537
|
this.element.dispatchEvent(event);
|
|
465
538
|
}
|
|
@@ -471,12 +544,15 @@ export default class AuroFloatingUI {
|
|
|
471
544
|
this.showBib();
|
|
472
545
|
}
|
|
473
546
|
|
|
474
|
-
const event = new CustomEvent(
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
547
|
+
const event = new CustomEvent(
|
|
548
|
+
this.eventPrefix ? `${this.eventPrefix}-triggerClick` : "triggerClick",
|
|
549
|
+
{
|
|
550
|
+
composed: true,
|
|
551
|
+
detail: {
|
|
552
|
+
expanded: this.element.isPopoverVisible,
|
|
553
|
+
},
|
|
554
|
+
},
|
|
555
|
+
);
|
|
480
556
|
|
|
481
557
|
this.element.dispatchEvent(event);
|
|
482
558
|
}
|
|
@@ -484,30 +560,32 @@ export default class AuroFloatingUI {
|
|
|
484
560
|
handleEvent(event) {
|
|
485
561
|
if (!this.element.disableEventShow) {
|
|
486
562
|
switch (event.type) {
|
|
487
|
-
case
|
|
563
|
+
case "keydown": {
|
|
488
564
|
// Support both Enter and Space keys for accessibility
|
|
489
565
|
// Space is included as it's expected behavior for interactive elements
|
|
490
566
|
|
|
491
567
|
const origin = event.composedPath()[0];
|
|
492
|
-
if (
|
|
493
|
-
|
|
568
|
+
if (
|
|
569
|
+
event.key === "Enter" ||
|
|
570
|
+
(event.key === " " && (!origin || origin.tagName !== "INPUT"))
|
|
571
|
+
) {
|
|
494
572
|
event.preventDefault();
|
|
495
573
|
this.handleClick();
|
|
496
574
|
}
|
|
497
575
|
break;
|
|
498
|
-
|
|
576
|
+
}
|
|
577
|
+
case "mouseenter":
|
|
499
578
|
if (this.element.hoverToggle) {
|
|
500
579
|
this.showBib();
|
|
501
580
|
}
|
|
502
581
|
break;
|
|
503
|
-
case
|
|
582
|
+
case "mouseleave":
|
|
504
583
|
if (this.element.hoverToggle) {
|
|
505
584
|
this.hideBib("mouseleave");
|
|
506
585
|
}
|
|
507
586
|
break;
|
|
508
|
-
case
|
|
587
|
+
case "focus":
|
|
509
588
|
if (this.element.focusShow) {
|
|
510
|
-
|
|
511
589
|
/*
|
|
512
590
|
This needs to better handle clicking that gives focus -
|
|
513
591
|
currently it shows and then immediately hides the bib
|
|
@@ -515,12 +593,12 @@ export default class AuroFloatingUI {
|
|
|
515
593
|
this.showBib();
|
|
516
594
|
}
|
|
517
595
|
break;
|
|
518
|
-
case
|
|
596
|
+
case "blur":
|
|
519
597
|
// send this task 100ms later queue to
|
|
520
598
|
// wait a frame in case focus moves within the floating element/bib
|
|
521
599
|
setTimeout(() => this.handleFocusLoss(), 0);
|
|
522
600
|
break;
|
|
523
|
-
case
|
|
601
|
+
case "click":
|
|
524
602
|
if (document.activeElement === document.body) {
|
|
525
603
|
event.currentTarget.focus();
|
|
526
604
|
}
|
|
@@ -540,15 +618,15 @@ export default class AuroFloatingUI {
|
|
|
540
618
|
*/
|
|
541
619
|
handleTriggerTabIndex() {
|
|
542
620
|
const focusableElementSelectors = [
|
|
543
|
-
|
|
544
|
-
|
|
621
|
+
"a",
|
|
622
|
+
"button",
|
|
545
623
|
'input:not([type="hidden"])',
|
|
546
|
-
|
|
547
|
-
|
|
624
|
+
"select",
|
|
625
|
+
"textarea",
|
|
548
626
|
'[tabindex]:not([tabindex="-1"])',
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
627
|
+
"auro-button",
|
|
628
|
+
"auro-input",
|
|
629
|
+
"auro-hyperlink",
|
|
552
630
|
];
|
|
553
631
|
|
|
554
632
|
const triggerNode = this.element.querySelectorAll('[slot="trigger"]')[0];
|
|
@@ -576,10 +654,10 @@ export default class AuroFloatingUI {
|
|
|
576
654
|
* @param {*} eventPrefix
|
|
577
655
|
*/
|
|
578
656
|
regenerateBibId() {
|
|
579
|
-
this.id = this.element.getAttribute(
|
|
657
|
+
this.id = this.element.getAttribute("id");
|
|
580
658
|
if (!this.id) {
|
|
581
659
|
this.id = window.crypto.randomUUID();
|
|
582
|
-
this.element.setAttribute(
|
|
660
|
+
this.element.setAttribute("id", this.id);
|
|
583
661
|
}
|
|
584
662
|
|
|
585
663
|
this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
|
|
@@ -600,11 +678,15 @@ export default class AuroFloatingUI {
|
|
|
600
678
|
if (this.element.trigger) {
|
|
601
679
|
this.disconnect();
|
|
602
680
|
}
|
|
603
|
-
this.element.trigger =
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
681
|
+
this.element.trigger =
|
|
682
|
+
this.element.triggerElement ||
|
|
683
|
+
this.element.shadowRoot.querySelector("#trigger") ||
|
|
684
|
+
this.element.trigger;
|
|
685
|
+
this.element.bib =
|
|
686
|
+
this.element.shadowRoot.querySelector("#bib") || this.element.bib;
|
|
687
|
+
this.element.bibSizer = this.element.shadowRoot.querySelector("#bibSizer");
|
|
688
|
+
this.element.triggerChevron =
|
|
689
|
+
this.element.shadowRoot.querySelector("#showStateIcon");
|
|
608
690
|
|
|
609
691
|
if (this.element.floaterConfig) {
|
|
610
692
|
this.element.hoverToggle = this.element.floaterConfig.hoverToggle;
|
|
@@ -615,12 +697,12 @@ export default class AuroFloatingUI {
|
|
|
615
697
|
|
|
616
698
|
this.handleEvent = this.handleEvent.bind(this);
|
|
617
699
|
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(
|
|
700
|
+
this.element.trigger.addEventListener("keydown", this.handleEvent);
|
|
701
|
+
this.element.trigger.addEventListener("click", this.handleEvent);
|
|
702
|
+
this.element.trigger.addEventListener("mouseenter", this.handleEvent);
|
|
703
|
+
this.element.trigger.addEventListener("mouseleave", this.handleEvent);
|
|
704
|
+
this.element.trigger.addEventListener("focus", this.handleEvent);
|
|
705
|
+
this.element.trigger.addEventListener("blur", this.handleEvent);
|
|
624
706
|
}
|
|
625
707
|
}
|
|
626
708
|
|
|
@@ -635,12 +717,18 @@ export default class AuroFloatingUI {
|
|
|
635
717
|
|
|
636
718
|
// Remove event & keyboard listeners
|
|
637
719
|
if (this.element?.trigger) {
|
|
638
|
-
this.element.trigger.removeEventListener(
|
|
639
|
-
this.element.trigger.removeEventListener(
|
|
640
|
-
this.element.trigger.removeEventListener(
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
720
|
+
this.element.trigger.removeEventListener("keydown", this.handleEvent);
|
|
721
|
+
this.element.trigger.removeEventListener("click", this.handleEvent);
|
|
722
|
+
this.element.trigger.removeEventListener(
|
|
723
|
+
"mouseenter",
|
|
724
|
+
this.handleEvent,
|
|
725
|
+
);
|
|
726
|
+
this.element.trigger.removeEventListener(
|
|
727
|
+
"mouseleave",
|
|
728
|
+
this.handleEvent,
|
|
729
|
+
);
|
|
730
|
+
this.element.trigger.removeEventListener("focus", this.handleEvent);
|
|
731
|
+
this.element.trigger.removeEventListener("blur", this.handleEvent);
|
|
644
732
|
}
|
|
645
733
|
}
|
|
646
734
|
}
|