@aurodesignsystem/auro-library 5.13.2 → 5.13.3

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,12 @@
1
1
  # Semantic Release Automated Changelog
2
2
 
3
+ ## [5.13.3](https://github.com/AlaskaAirlines/auro-library/compare/v5.13.2...v5.13.3) (2026-08-07)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **floatingUI:** suppress Escape keydown for modal dialogs to prevent CloseWatcher force-close AB[#1613688](https://github.com/AlaskaAirlines/auro-library/issues/1613688) ([efd81c5](https://github.com/AlaskaAirlines/auro-library/commit/efd81c5fd96f4d02253e4ce76b4e7a2ddb8d25c7))
9
+
3
10
  ## [5.13.2](https://github.com/AlaskaAirlines/auro-library/compare/v5.13.1...v5.13.2) (2026-07-28)
4
11
 
5
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurodesignsystem/auro-library",
3
- "version": "5.13.2",
3
+ "version": "5.13.3",
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",
@@ -778,6 +778,24 @@ export default class AuroFloatingUI {
778
778
  if (!this.showing) {
779
779
  if (!element.modal) {
780
780
  this.setupHideHandlers();
781
+ } else {
782
+ if (this.keyDownHandler) {
783
+ document.removeEventListener("keydown", this.keyDownHandler);
784
+ }
785
+ this.keyDownHandler = (evt) => {
786
+ if (evt.key === "Escape" && element.isPopoverVisible) {
787
+ // Intercept at keydown so CloseWatcher never sees the keystroke.
788
+ // Canceling `cancel` alone is insufficient — a second Esc with no
789
+ // intervening user activation triggers the anti-trap and fires `close`
790
+ // directly, bypassing any `cancel` preventDefault (AB#1613688).
791
+ // stopImmediatePropagation is intentional: it prevents other document
792
+ // keydown handlers (e.g. consumer code, auro-dialog) from also acting
793
+ // on Escape while the modal owns the key.
794
+ evt.preventDefault();
795
+ evt.stopImmediatePropagation();
796
+ }
797
+ };
798
+ document.addEventListener("keydown", this.keyDownHandler);
781
799
  }
782
800
  this.showing = true;
783
801
  element.isPopoverVisible = true;
@@ -295,6 +295,85 @@ describe("AuroFloatingUI", () => {
295
295
  });
296
296
  });
297
297
 
298
+ describe("AuroFloatingUI modal Escape suppression (AB#1613688)", () => {
299
+ let host;
300
+ let bib;
301
+ let floatingUI;
302
+ let hideBibSpy;
303
+
304
+ beforeEach(() => {
305
+ host = document.createElement("div");
306
+ bib = document.createElement("div");
307
+ host.bib = bib;
308
+ host.modal = true;
309
+ host.isPopoverVisible = false;
310
+ host.triggerChevron = document.createElement("span");
311
+ document.body.append(host, bib);
312
+
313
+ AuroFloatingUI.openingQueue = [];
314
+ document.expandedAuroFloater = null;
315
+
316
+ floatingUI = new AuroFloatingUI(host, "dialog");
317
+ hideBibSpy = sinon.spy(floatingUI, "hideBib");
318
+ });
319
+
320
+ afterEach(() => {
321
+ floatingUI.cleanupHideHandlers();
322
+ sinon.restore();
323
+ AuroFloatingUI.isMousePressed = false;
324
+ AuroFloatingUI.openingQueue = [];
325
+ document.expandedAuroFloater = null;
326
+ host?.remove();
327
+ bib?.remove();
328
+ });
329
+
330
+ it("registers a keydown handler and skips setupHideHandlers when modal=true", () => {
331
+ const setupHideHandlersSpy = sinon.spy(floatingUI, "setupHideHandlers");
332
+
333
+ floatingUI.showBib();
334
+
335
+ expect(setupHideHandlersSpy.called).to.be.false;
336
+ expect(floatingUI.keyDownHandler).to.be.a("function");
337
+ expect(floatingUI.showing).to.be.true;
338
+ });
339
+
340
+ it("does not call hideBib when Escape is pressed while modal dialog is open", () => {
341
+ floatingUI.showBib();
342
+
343
+ document.dispatchEvent(
344
+ new KeyboardEvent("keydown", {
345
+ key: "Escape",
346
+ bubbles: true,
347
+ cancelable: true,
348
+ }),
349
+ );
350
+
351
+ expect(hideBibSpy.called).to.be.false;
352
+ });
353
+
354
+ it("calls preventDefault on Escape keydown while modal dialog is open", () => {
355
+ floatingUI.showBib();
356
+
357
+ const escEvent = new KeyboardEvent("keydown", {
358
+ key: "Escape",
359
+ bubbles: true,
360
+ cancelable: true,
361
+ });
362
+ const preventDefaultSpy = sinon.spy(escEvent, "preventDefault");
363
+ document.dispatchEvent(escEvent);
364
+
365
+ expect(preventDefaultSpy.calledOnce).to.be.true;
366
+ });
367
+
368
+ it("removes the modal Escape keydown handler via cleanupHideHandlers", () => {
369
+ floatingUI.showBib();
370
+ expect(floatingUI.keyDownHandler).to.be.a("function");
371
+
372
+ floatingUI.cleanupHideHandlers();
373
+ expect(floatingUI.keyDownHandler).to.be.null;
374
+ });
375
+ });
376
+
298
377
  describe("AuroFloatingUI.openingQueue and topOpeningFloatingUI", () => {
299
378
  let floatingUI1;
300
379
  let floatingUI2;