@aurodesignsystem/auro-library 5.11.3 → 5.12.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Semantic Release Automated Changelog
2
2
 
3
+ # [5.12.0](https://github.com/AlaskaAirlines/auro-library/compare/v5.11.3...v5.12.0) (2026-04-01)
4
+
5
+
6
+ ### Features
7
+
8
+ * add keyboard handling toggle to AuroFloatingUI ([100bbe9](https://github.com/AlaskaAirlines/auro-library/commit/100bbe940ff2f1589d8b738ce83631bd5c7b8568))
9
+
3
10
  ## [5.11.3](https://github.com/AlaskaAirlines/auro-library/compare/v5.11.2...v5.11.3) (2026-03-31)
4
11
 
5
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurodesignsystem/auro-library",
3
- "version": "5.11.3",
3
+ "version": "5.12.0",
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,189 @@
1
+ import { expect } from "@open-wc/testing";
2
+ import { html, render } from "lit";
3
+ import sinon from "sinon";
4
+ import AuroFloatingUI from "../../floatingUI.mjs";
5
+
6
+ async function fixture(template) {
7
+ const wrapper = document.createElement("div");
8
+ render(template, wrapper);
9
+ document.body.appendChild(wrapper);
10
+ await new Promise((resolve) => setTimeout(resolve, 0));
11
+ return wrapper.firstElementChild;
12
+ }
13
+
14
+ /**
15
+ * Builds a minimal element stub that satisfies the properties AuroFloatingUI
16
+ * reads during configure() and keyboard event handling.
17
+ */
18
+ function makeElement(trigger, bib) {
19
+ return {
20
+ trigger,
21
+ bib,
22
+ bibSizer: null,
23
+ triggerChevron: null,
24
+ shadowRoot: {
25
+ querySelector: () => null,
26
+ append: () => {},
27
+ },
28
+ behavior: "dropdown",
29
+ disabled: false,
30
+ isPopoverVisible: false,
31
+ showing: false,
32
+ noToggle: false,
33
+ modal: false,
34
+ disableEventShow: false,
35
+ hoverToggle: false,
36
+ focusShow: false,
37
+ floaterConfig: null,
38
+ cleanup: null,
39
+ contains: () => false,
40
+ dispatchEvent: () => {},
41
+ getAttribute: () => null,
42
+ setAttribute: () => {},
43
+ querySelectorAll: () => [],
44
+ style: {},
45
+ };
46
+ }
47
+
48
+ describe("AuroFloatingUI keyboard gate (enableKeyboardHandling)", () => {
49
+ let triggerEl;
50
+ let bibEl;
51
+ let elem;
52
+ let floatingUi;
53
+
54
+ beforeEach(async () => {
55
+ triggerEl = await fixture(html`<button id="trigger">Toggle</button>`);
56
+ bibEl = await fixture(html`<div id="bib"></div>`);
57
+
58
+ elem = makeElement(triggerEl, bibEl);
59
+ floatingUi = new AuroFloatingUI(elem, "dropdown");
60
+ });
61
+
62
+ afterEach(async () => {
63
+ // Let any setTimeout(0) handlers (e.g. click listener setup in setupHideHandlers)
64
+ // fire before cleanup so cleanupHideHandlers can remove them.
65
+ await new Promise((resolve) => setTimeout(resolve, 10));
66
+ document.expandedAuroFloater = null;
67
+ document.expandedAuroFormkitDropdown = null;
68
+ floatingUi?.disconnect();
69
+ floatingUi = null;
70
+ triggerEl?.parentNode?.remove();
71
+ bibEl?.parentNode?.remove();
72
+ sinon.restore();
73
+ });
74
+
75
+ describe("default behavior (enableKeyboardHandling = true)", () => {
76
+ beforeEach(() => {
77
+ floatingUi.configure(elem, "auro-dropdown", true);
78
+ });
79
+
80
+ it("Enter on the trigger calls handleClick()", () => {
81
+ const spy = sinon.spy(floatingUi, "handleClick");
82
+ triggerEl.dispatchEvent(
83
+ new KeyboardEvent("keydown", {
84
+ key: "Enter",
85
+ bubbles: true,
86
+ composed: true,
87
+ }),
88
+ );
89
+ expect(spy.calledOnce).to.be.true;
90
+ });
91
+
92
+ it("Space on the trigger calls handleClick()", () => {
93
+ const spy = sinon.spy(floatingUi, "handleClick");
94
+ triggerEl.dispatchEvent(
95
+ new KeyboardEvent("keydown", {
96
+ key: " ",
97
+ bubbles: true,
98
+ composed: true,
99
+ }),
100
+ );
101
+ expect(spy.calledOnce).to.be.true;
102
+ });
103
+
104
+ it("Escape dismisses when bib is visible", () => {
105
+ elem.isPopoverVisible = true;
106
+ floatingUi.showing = true;
107
+ document.expandedAuroFloater = floatingUi;
108
+ const spy = sinon.spy(floatingUi, "hideBib");
109
+
110
+ // setupHideHandlers attaches the document keydown listener
111
+ floatingUi.setupHideHandlers();
112
+ document.dispatchEvent(
113
+ new KeyboardEvent("keydown", { key: "Escape", bubbles: true }),
114
+ );
115
+
116
+ expect(spy.calledOnce).to.be.true;
117
+ document.expandedAuroFloater = null;
118
+ });
119
+ });
120
+
121
+ describe("keyboard disabled (enableKeyboardHandling = false)", () => {
122
+ beforeEach(() => {
123
+ floatingUi.configure(elem, "auro-dropdown", false);
124
+ });
125
+
126
+ it("Enter on the trigger does NOT call handleClick()", () => {
127
+ const spy = sinon.spy(floatingUi, "handleClick");
128
+ triggerEl.dispatchEvent(
129
+ new KeyboardEvent("keydown", {
130
+ key: "Enter",
131
+ bubbles: true,
132
+ composed: true,
133
+ }),
134
+ );
135
+ expect(spy.called).to.be.false;
136
+ });
137
+
138
+ it("Space on the trigger does NOT call handleClick()", () => {
139
+ const spy = sinon.spy(floatingUi, "handleClick");
140
+ triggerEl.dispatchEvent(
141
+ new KeyboardEvent("keydown", {
142
+ key: " ",
143
+ bubbles: true,
144
+ composed: true,
145
+ }),
146
+ );
147
+ expect(spy.called).to.be.false;
148
+ });
149
+
150
+ it("Escape does NOT dismiss the bib", () => {
151
+ elem.isPopoverVisible = true;
152
+ floatingUi.showing = true;
153
+ document.expandedAuroFloater = floatingUi;
154
+ const spy = sinon.spy(floatingUi, "hideBib");
155
+
156
+ // setupHideHandlers should skip attaching the document keydown listener
157
+ floatingUi.setupHideHandlers();
158
+ document.dispatchEvent(
159
+ new KeyboardEvent("keydown", { key: "Escape", bubbles: true }),
160
+ );
161
+
162
+ expect(spy.called).to.be.false;
163
+ document.expandedAuroFloater = null;
164
+ });
165
+
166
+ it("click on the trigger still calls handleClick()", () => {
167
+ const spy = sinon.spy(floatingUi, "handleClick");
168
+ triggerEl.dispatchEvent(
169
+ new MouseEvent("click", { bubbles: true, composed: true }),
170
+ );
171
+ expect(spy.calledOnce).to.be.true;
172
+ });
173
+ });
174
+
175
+ describe("default argument", () => {
176
+ it("omitting enableKeyboardHandling defaults to true (Enter still works)", () => {
177
+ floatingUi.configure(elem, "auro-dropdown");
178
+ const spy = sinon.spy(floatingUi, "handleClick");
179
+ triggerEl.dispatchEvent(
180
+ new KeyboardEvent("keydown", {
181
+ key: "Enter",
182
+ bubbles: true,
183
+ composed: true,
184
+ }),
185
+ );
186
+ expect(spy.calledOnce).to.be.true;
187
+ });
188
+ });
189
+ });
@@ -71,6 +71,11 @@ export default class AuroFloatingUI {
71
71
  this.clickHandler = null;
72
72
  this.keyDownHandler = null;
73
73
 
74
+ /**
75
+ * @private
76
+ */
77
+ this.enableKeyboardHandling = true;
78
+
74
79
  /**
75
80
  * @private
76
81
  */
@@ -405,7 +410,9 @@ export default class AuroFloatingUI {
405
410
  document.addEventListener("focusin", this.focusHandler);
406
411
  }
407
412
 
408
- document.addEventListener("keydown", this.keyDownHandler);
413
+ if (this.enableKeyboardHandling) {
414
+ document.addEventListener("keydown", this.keyDownHandler);
415
+ }
409
416
 
410
417
  // send this task to the end of queue to prevent conflicting
411
418
  // it conflicts if showBib gets call from a button that's not this.element.trigger
@@ -662,8 +669,9 @@ export default class AuroFloatingUI {
662
669
  this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
663
670
  }
664
671
 
665
- configure(elem, eventPrefix) {
672
+ configure(elem, eventPrefix, enableKeyboardHandling = true) {
666
673
  AuroFloatingUI.setupMousePressChecker();
674
+ this.enableKeyboardHandling = enableKeyboardHandling;
667
675
 
668
676
  this.eventPrefix = eventPrefix;
669
677
  if (this.element !== elem) {
@@ -696,7 +704,9 @@ export default class AuroFloatingUI {
696
704
 
697
705
  this.handleEvent = this.handleEvent.bind(this);
698
706
  if (this.element.trigger) {
699
- this.element.trigger.addEventListener("keydown", this.handleEvent);
707
+ if (this.enableKeyboardHandling) {
708
+ this.element.trigger.addEventListener("keydown", this.handleEvent);
709
+ }
700
710
  this.element.trigger.addEventListener("click", this.handleEvent);
701
711
  this.element.trigger.addEventListener("mouseenter", this.handleEvent);
702
712
  this.element.trigger.addEventListener("mouseleave", this.handleEvent);