@aurodesignsystem-dev/auro-formkit 0.0.0-pr1424.2 → 0.0.0-pr1424.4

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/README.md +133 -183
  3. package/components/checkbox/demo/api.min.js +3 -3
  4. package/components/checkbox/demo/index.min.js +3 -3
  5. package/components/checkbox/dist/index.js +3 -3
  6. package/components/checkbox/dist/registered.js +3 -3
  7. package/components/combobox/demo/api.html +1 -0
  8. package/components/combobox/demo/api.js +3 -1
  9. package/components/combobox/demo/api.md +75 -0
  10. package/components/combobox/demo/api.min.js +314 -172
  11. package/components/combobox/demo/index.min.js +301 -171
  12. package/components/combobox/dist/comboboxKeyboardStrategy.d.ts +1 -1
  13. package/components/combobox/dist/index.js +291 -171
  14. package/components/combobox/dist/registered.js +291 -171
  15. package/components/counter/demo/api.html +3 -0
  16. package/components/counter/demo/api.js +4 -0
  17. package/components/counter/demo/api.md +130 -0
  18. package/components/counter/demo/api.min.js +320 -167
  19. package/components/counter/demo/index.min.js +300 -167
  20. package/components/counter/dist/counterGroupKeyboardStrategy.d.ts +3 -0
  21. package/components/counter/dist/index.js +300 -167
  22. package/components/counter/dist/registered.js +300 -167
  23. package/components/datepicker/demo/api.html +1 -0
  24. package/components/datepicker/demo/api.js +2 -0
  25. package/components/datepicker/demo/api.md +57 -0
  26. package/components/datepicker/demo/api.min.js +376 -171
  27. package/components/datepicker/demo/index.min.js +364 -171
  28. package/components/datepicker/dist/datepickerKeyboardStrategy.d.ts +3 -1
  29. package/components/datepicker/dist/index.js +364 -171
  30. package/components/datepicker/dist/registered.js +364 -171
  31. package/components/dropdown/demo/api.html +1 -0
  32. package/components/dropdown/demo/api.js +2 -0
  33. package/components/dropdown/demo/api.md +95 -0
  34. package/components/dropdown/demo/api.min.js +296 -165
  35. package/components/dropdown/demo/index.min.js +276 -165
  36. package/components/dropdown/dist/index.js +276 -165
  37. package/components/dropdown/dist/registered.js +276 -165
  38. package/components/form/demo/api.min.js +1254 -684
  39. package/components/form/demo/index.min.js +1254 -684
  40. package/components/input/demo/api.min.js +1 -1
  41. package/components/input/demo/index.min.js +1 -1
  42. package/components/input/dist/index.js +1 -1
  43. package/components/input/dist/registered.js +1 -1
  44. package/components/menu/demo/api.md +1 -0
  45. package/components/menu/demo/api.min.js +10 -0
  46. package/components/menu/demo/index.min.js +10 -0
  47. package/components/menu/dist/auro-menuoption.d.ts +9 -0
  48. package/components/menu/dist/index.js +10 -0
  49. package/components/menu/dist/registered.js +10 -0
  50. package/components/radio/demo/api.min.js +2 -2
  51. package/components/radio/demo/index.min.js +2 -2
  52. package/components/radio/dist/index.js +2 -2
  53. package/components/radio/dist/registered.js +2 -2
  54. package/components/select/demo/api.html +1 -0
  55. package/components/select/demo/api.js +2 -0
  56. package/components/select/demo/api.md +76 -0
  57. package/components/select/demo/api.min.js +306 -169
  58. package/components/select/demo/index.min.js +293 -169
  59. package/components/select/dist/index.js +283 -169
  60. package/components/select/dist/registered.js +283 -169
  61. package/custom-elements.json +48 -3
  62. package/package.json +5 -3
@@ -1904,11 +1904,19 @@ class AuroFloatingUI {
1904
1904
  * This ensures that the bib content has the same dimensions as the sizer element.
1905
1905
  */
1906
1906
  mirrorSize() {
1907
+ const element = this.element;
1908
+ if (!element) {
1909
+ return;
1910
+ }
1911
+
1907
1912
  // mirror the boxsize from bibSizer
1908
- if (this.element.bibSizer && this.element.matchWidth) {
1909
- const sizerStyle = window.getComputedStyle(this.element.bibSizer);
1910
- const bibContent =
1911
- this.element.bib.shadowRoot.querySelector(".container");
1913
+ if (element.bibSizer && element.matchWidth && element.bib?.shadowRoot) {
1914
+ const sizerStyle = window.getComputedStyle(element.bibSizer);
1915
+ const bibContent = element.bib.shadowRoot.querySelector(".container");
1916
+ if (!bibContent) {
1917
+ return;
1918
+ }
1919
+
1912
1920
  if (sizerStyle.width !== "0px") {
1913
1921
  bibContent.style.width = sizerStyle.width;
1914
1922
  }
@@ -1930,9 +1938,14 @@ class AuroFloatingUI {
1930
1938
  * @returns {String} The positioning strategy, one of 'fullscreen', 'floating', 'cover'.
1931
1939
  */
1932
1940
  getPositioningStrategy() {
1941
+ const element = this.element;
1942
+ if (!element) {
1943
+ return "floating";
1944
+ }
1945
+
1933
1946
  const breakpoint =
1934
- this.element.bib.mobileFullscreenBreakpoint ||
1935
- this.element.floaterConfig?.fullscreenBreakpoint;
1947
+ element.bib?.mobileFullscreenBreakpoint ||
1948
+ element.floaterConfig?.fullscreenBreakpoint;
1936
1949
  switch (this.behavior) {
1937
1950
  case "tooltip":
1938
1951
  return "floating";
@@ -1943,9 +1956,9 @@ class AuroFloatingUI {
1943
1956
  `(max-width: ${breakpoint})`,
1944
1957
  ).matches;
1945
1958
 
1946
- this.element.expanded = smallerThanBreakpoint;
1959
+ element.expanded = smallerThanBreakpoint;
1947
1960
  }
1948
- if (this.element.nested) {
1961
+ if (element.nested) {
1949
1962
  return "cover";
1950
1963
  }
1951
1964
  return "fullscreen";
@@ -1975,42 +1988,65 @@ class AuroFloatingUI {
1975
1988
  * and applies the calculated position to the bib's style.
1976
1989
  */
1977
1990
  position() {
1991
+ const element = this.element;
1992
+ if (!element) {
1993
+ return;
1994
+ }
1995
+
1978
1996
  const strategy = this.getPositioningStrategy();
1979
1997
  this.configureBibStrategy(strategy);
1980
1998
 
1981
1999
  if (strategy === "floating") {
2000
+ if (!element.trigger || !element.bib) {
2001
+ return;
2002
+ }
2003
+
1982
2004
  this.mirrorSize();
1983
2005
  // Define the middlware for the floater configuration
1984
2006
  const middleware = [
1985
- offset(this.element.floaterConfig?.offset || 0),
1986
- ...(this.element.floaterConfig?.shift ? [shift()] : []), // Add shift middleware if shift is enabled.
1987
- ...(this.element.floaterConfig?.flip ? [flip()] : []), // Add flip middleware if flip is enabled.
1988
- ...(this.element.floaterConfig?.autoPlacement ? [autoPlacement()] : []), // Add autoPlacement middleware if autoPlacement is enabled.
2007
+ offset(element.floaterConfig?.offset || 0),
2008
+ ...(element.floaterConfig?.shift ? [shift()] : []), // Add shift middleware if shift is enabled.
2009
+ ...(element.floaterConfig?.flip ? [flip()] : []), // Add flip middleware if flip is enabled.
2010
+ ...(element.floaterConfig?.autoPlacement ? [autoPlacement()] : []), // Add autoPlacement middleware if autoPlacement is enabled.
1989
2011
  ];
1990
2012
 
1991
2013
  // Compute the position of the bib
1992
- computePosition(this.element.trigger, this.element.bib, {
1993
- strategy: this.element.floaterConfig?.strategy || "fixed",
1994
- placement: this.element.floaterConfig?.placement,
2014
+ computePosition(element.trigger, element.bib, {
2015
+ strategy: element.floaterConfig?.strategy || "fixed",
2016
+ placement: element.floaterConfig?.placement,
1995
2017
  middleware: middleware || [],
1996
2018
  }).then(({ x, y }) => {
1997
2019
  // eslint-disable-line id-length
1998
- Object.assign(this.element.bib.style, {
2020
+ const currentElement = this.element;
2021
+ if (!currentElement?.bib) {
2022
+ return;
2023
+ }
2024
+
2025
+ Object.assign(currentElement.bib.style, {
1999
2026
  left: `${x}px`,
2000
2027
  top: `${y}px`,
2001
2028
  });
2002
2029
  });
2003
2030
  } else if (strategy === "cover") {
2031
+ if (!element.parentNode || !element.bib) {
2032
+ return;
2033
+ }
2034
+
2004
2035
  // Compute the position of the bib
2005
- computePosition(this.element.parentNode, this.element.bib, {
2036
+ computePosition(element.parentNode, element.bib, {
2006
2037
  placement: "bottom-start",
2007
2038
  }).then(({ x, y }) => {
2008
2039
  // eslint-disable-line id-length
2009
- Object.assign(this.element.bib.style, {
2040
+ const currentElement = this.element;
2041
+ if (!currentElement?.bib || !currentElement.parentNode) {
2042
+ return;
2043
+ }
2044
+
2045
+ Object.assign(currentElement.bib.style, {
2010
2046
  left: `${x}px`,
2011
- top: `${y - this.element.parentNode.offsetHeight}px`,
2012
- width: `${this.element.parentNode.offsetWidth}px`,
2013
- height: `${this.element.parentNode.offsetHeight}px`,
2047
+ top: `${y - currentElement.parentNode.offsetHeight}px`,
2048
+ width: `${currentElement.parentNode.offsetWidth}px`,
2049
+ height: `${currentElement.parentNode.offsetHeight}px`,
2014
2050
  });
2015
2051
  });
2016
2052
  }
@@ -2022,11 +2058,17 @@ class AuroFloatingUI {
2022
2058
  * @param {Boolean} lock - If true, locks the body's scrolling functionlity; otherwise, unlock.
2023
2059
  */
2024
2060
  lockScroll(lock = true) {
2061
+ const element = this.element;
2062
+
2025
2063
  if (lock) {
2064
+ if (!element?.bib) {
2065
+ return;
2066
+ }
2067
+
2026
2068
  document.body.style.overflow = "hidden"; // hide body's scrollbar
2027
2069
 
2028
2070
  // Move `bib` by the amount the viewport is shifted to stay aligned in fullscreen.
2029
- this.element.bib.style.transform = `translateY(${window?.visualViewport?.offsetTop}px)`;
2071
+ element.bib.style.transform = `translateY(${window?.visualViewport?.offsetTop}px)`;
2030
2072
  } else {
2031
2073
  document.body.style.overflow = "";
2032
2074
  }
@@ -2042,20 +2084,24 @@ class AuroFloatingUI {
2042
2084
  * @param {string} strategy - The positioning strategy ('fullscreen' or 'floating').
2043
2085
  */
2044
2086
  configureBibStrategy(value) {
2087
+ const element = this.element;
2088
+ if (!element?.bib) {
2089
+ return;
2090
+ }
2091
+
2045
2092
  if (value === "fullscreen") {
2046
- this.element.isBibFullscreen = true;
2093
+ element.isBibFullscreen = true;
2047
2094
  // reset the prev position
2048
- this.element.bib.setAttribute("isfullscreen", "");
2049
- this.element.bib.style.position = "fixed";
2050
- this.element.bib.style.top = "0px";
2051
- this.element.bib.style.left = "0px";
2052
- this.element.bib.style.width = "";
2053
- this.element.bib.style.height = "";
2054
- this.element.style.contain = "";
2095
+ element.bib.setAttribute("isfullscreen", "");
2096
+ element.bib.style.position = "fixed";
2097
+ element.bib.style.top = "0px";
2098
+ element.bib.style.left = "0px";
2099
+ element.bib.style.width = "";
2100
+ element.bib.style.height = "";
2101
+ element.style.contain = "";
2055
2102
 
2056
2103
  // reset the size that was mirroring `size` css-part
2057
- const bibContent =
2058
- this.element.bib.shadowRoot.querySelector(".container");
2104
+ const bibContent = element.bib.shadowRoot?.querySelector(".container");
2059
2105
  if (bibContent) {
2060
2106
  bibContent.style.width = "";
2061
2107
  bibContent.style.height = "";
@@ -2070,14 +2116,14 @@ class AuroFloatingUI {
2070
2116
  }, 0);
2071
2117
  }
2072
2118
 
2073
- if (this.element.isPopoverVisible) {
2119
+ if (element.isPopoverVisible) {
2074
2120
  this.lockScroll(true);
2075
2121
  }
2076
2122
  } else {
2077
- this.element.bib.style.position = "";
2078
- this.element.bib.removeAttribute("isfullscreen");
2079
- this.element.isBibFullscreen = false;
2080
- this.element.style.contain = "layout";
2123
+ element.bib.style.position = "";
2124
+ element.bib.removeAttribute("isfullscreen");
2125
+ element.isBibFullscreen = false;
2126
+ element.style.contain = "layout";
2081
2127
  }
2082
2128
 
2083
2129
  const isChanged = this.strategy && this.strategy !== value;
@@ -2095,16 +2141,21 @@ class AuroFloatingUI {
2095
2141
  },
2096
2142
  );
2097
2143
 
2098
- this.element.dispatchEvent(event);
2144
+ element.dispatchEvent(event);
2099
2145
  }
2100
2146
  }
2101
2147
 
2102
2148
  updateState() {
2103
- const isVisible = this.element.isPopoverVisible;
2149
+ const element = this.element;
2150
+ if (!element) {
2151
+ return;
2152
+ }
2153
+
2154
+ const isVisible = element.isPopoverVisible;
2104
2155
  if (!isVisible) {
2105
2156
  this.cleanupHideHandlers();
2106
2157
  try {
2107
- this.element.cleanup?.();
2158
+ element.cleanup?.();
2108
2159
  } catch (error) {
2109
2160
  // Do nothing
2110
2161
  }
@@ -2120,28 +2171,30 @@ class AuroFloatingUI {
2120
2171
  * If not, and if the bib isn't in fullscreen mode with focus lost, it hides the bib.
2121
2172
  */
2122
2173
  handleFocusLoss() {
2174
+ const element = this.element;
2175
+ if (!element?.bib) {
2176
+ return;
2177
+ }
2178
+
2123
2179
  // if mouse is being pressed, skip and let click event to handle the action
2124
2180
  if (AuroFloatingUI.isMousePressed) {
2125
2181
  return;
2126
2182
  }
2127
2183
 
2128
2184
  if (
2129
- this.element.noHideOnThisFocusLoss ||
2130
- this.element.hasAttribute("noHideOnThisFocusLoss")
2185
+ element.noHideOnThisFocusLoss ||
2186
+ element.hasAttribute("noHideOnThisFocusLoss")
2131
2187
  ) {
2132
2188
  return;
2133
2189
  }
2134
2190
 
2135
2191
  // if focus is still inside of trigger or bib, do not close
2136
- if (
2137
- this.element.matches(":focus") ||
2138
- this.element.matches(":focus-within")
2139
- ) {
2192
+ if (element.matches(":focus") || element.matches(":focus-within")) {
2140
2193
  return;
2141
2194
  }
2142
2195
 
2143
2196
  // if fullscreen bib is in fullscreen mode, do not close
2144
- if (this.element.bib.hasAttribute("isfullscreen")) {
2197
+ if (element.bib.hasAttribute("isfullscreen")) {
2145
2198
  return;
2146
2199
  }
2147
2200
 
@@ -2149,23 +2202,33 @@ class AuroFloatingUI {
2149
2202
  }
2150
2203
 
2151
2204
  setupHideHandlers() {
2205
+ const element = this.element;
2206
+ if (!element) {
2207
+ return;
2208
+ }
2209
+
2152
2210
  // Define handlers & store references
2153
2211
  this.focusHandler = () => this.handleFocusLoss();
2154
2212
 
2155
2213
  this.clickHandler = (evt) => {
2214
+ const element = this.element;
2215
+ if (!element?.bib) {
2216
+ return;
2217
+ }
2218
+
2156
2219
  // When the bib is fullscreen (modal dialog), don't close on outside
2157
2220
  // clicks. VoiceOver's synthetic click events inside a top-layer modal
2158
2221
  // <dialog> may not include the bib in composedPath(), causing false
2159
2222
  // positives. This mirrors the fullscreen guard in handleFocusLoss().
2160
- if (this.element.bib && this.element.bib.hasAttribute("isfullscreen")) {
2223
+ if (element.bib.hasAttribute("isfullscreen")) {
2161
2224
  return;
2162
2225
  }
2163
2226
 
2164
2227
  if (
2165
- (!evt.composedPath().includes(this.element.trigger) &&
2166
- !evt.composedPath().includes(this.element.bib)) ||
2167
- (this.element.bib.backdrop &&
2168
- evt.composedPath().includes(this.element.bib.backdrop))
2228
+ (!evt.composedPath().includes(element.trigger) &&
2229
+ !evt.composedPath().includes(element.bib)) ||
2230
+ (element.bib.backdrop &&
2231
+ evt.composedPath().includes(element.bib.backdrop))
2169
2232
  ) {
2170
2233
  const existedVisibleFloatingUI =
2171
2234
  document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
@@ -2186,7 +2249,12 @@ class AuroFloatingUI {
2186
2249
 
2187
2250
  // ESC key handler
2188
2251
  this.keyDownHandler = (evt) => {
2189
- if (evt.key === "Escape" && this.element.isPopoverVisible) {
2252
+ const element = this.element;
2253
+ if (!element) {
2254
+ return;
2255
+ }
2256
+
2257
+ if (evt.key === "Escape" && element.isPopoverVisible) {
2190
2258
  const existedVisibleFloatingUI =
2191
2259
  document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
2192
2260
  if (
@@ -2243,6 +2311,10 @@ class AuroFloatingUI {
2243
2311
  }
2244
2312
 
2245
2313
  updateCurrentExpandedDropdown() {
2314
+ if (!this.element) {
2315
+ return;
2316
+ }
2317
+
2246
2318
  // Close any other dropdown that is already open
2247
2319
  const existedVisibleFloatingUI =
2248
2320
  document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
@@ -2259,25 +2331,34 @@ class AuroFloatingUI {
2259
2331
  }
2260
2332
 
2261
2333
  showBib() {
2262
- if (!this.element.disabled && !this.showing) {
2334
+ const element = this.element;
2335
+ if (!element) {
2336
+ return;
2337
+ }
2338
+
2339
+ if (!element.bib || (!element.trigger && !element.parentNode)) {
2340
+ return;
2341
+ }
2342
+
2343
+ if (!element.disabled && !this.showing) {
2263
2344
  this.updateCurrentExpandedDropdown();
2264
- this.element.triggerChevron?.setAttribute("data-expanded", true);
2345
+ element.triggerChevron?.setAttribute("data-expanded", true);
2265
2346
 
2266
2347
  // prevent double showing: isPopovervisible gets first and showBib gets called later
2267
2348
  if (!this.showing) {
2268
- if (!this.element.modal) {
2349
+ if (!element.modal) {
2269
2350
  this.setupHideHandlers();
2270
2351
  }
2271
2352
  this.showing = true;
2272
- this.element.isPopoverVisible = true;
2353
+ element.isPopoverVisible = true;
2273
2354
  this.position();
2274
2355
  this.dispatchEventDropdownToggle();
2275
2356
  }
2276
2357
 
2277
2358
  // Setup auto update to handle resize and scroll
2278
- this.element.cleanup = autoUpdate(
2279
- this.element.trigger || this.element.parentNode,
2280
- this.element.bib,
2359
+ element.cleanup = autoUpdate(
2360
+ element.trigger || element.parentNode,
2361
+ element.bib,
2281
2362
  () => {
2282
2363
  this.position();
2283
2364
  },
@@ -2290,22 +2371,27 @@ class AuroFloatingUI {
2290
2371
  * @param {String} eventType - The event type that triggered the hiding action.
2291
2372
  */
2292
2373
  hideBib(eventType = "unknown") {
2293
- if (this.element.disabled) {
2374
+ const element = this.element;
2375
+ if (!element) {
2376
+ return;
2377
+ }
2378
+
2379
+ if (element.disabled) {
2294
2380
  return;
2295
2381
  }
2296
2382
 
2297
2383
  // noToggle dropdowns should not close when the trigger is clicked (the
2298
2384
  // "toggle" behavior), but they CAN still close via other interactions like
2299
2385
  // Escape key or focus loss.
2300
- if (this.element.noToggle && eventType === "click") {
2386
+ if (element.noToggle && eventType === "click") {
2301
2387
  return;
2302
2388
  }
2303
2389
 
2304
2390
  this.lockScroll(false);
2305
- this.element.triggerChevron?.removeAttribute("data-expanded");
2391
+ element.triggerChevron?.removeAttribute("data-expanded");
2306
2392
 
2307
- if (this.element.isPopoverVisible) {
2308
- this.element.isPopoverVisible = false;
2393
+ if (element.isPopoverVisible) {
2394
+ element.isPopoverVisible = false;
2309
2395
  }
2310
2396
  if (this.showing) {
2311
2397
  this.cleanupHideHandlers();
@@ -2325,6 +2411,11 @@ class AuroFloatingUI {
2325
2411
  * @param {String} eventType - The event type that triggered the toggle action.
2326
2412
  */
2327
2413
  dispatchEventDropdownToggle(eventType) {
2414
+ const element = this.element;
2415
+ if (!element) {
2416
+ return;
2417
+ }
2418
+
2328
2419
  const event = new CustomEvent(
2329
2420
  this.eventPrefix ? `${this.eventPrefix}-toggled` : "toggled",
2330
2421
  {
@@ -2336,11 +2427,16 @@ class AuroFloatingUI {
2336
2427
  },
2337
2428
  );
2338
2429
 
2339
- this.element.dispatchEvent(event);
2430
+ element.dispatchEvent(event);
2340
2431
  }
2341
2432
 
2342
2433
  handleClick() {
2343
- if (this.element.isPopoverVisible) {
2434
+ const element = this.element;
2435
+ if (!element) {
2436
+ return;
2437
+ }
2438
+
2439
+ if (element.isPopoverVisible) {
2344
2440
  this.hideBib("click");
2345
2441
  } else {
2346
2442
  this.showBib();
@@ -2351,63 +2447,66 @@ class AuroFloatingUI {
2351
2447
  {
2352
2448
  composed: true,
2353
2449
  detail: {
2354
- expanded: this.element.isPopoverVisible,
2450
+ expanded: element.isPopoverVisible,
2355
2451
  },
2356
2452
  },
2357
2453
  );
2358
2454
 
2359
- this.element.dispatchEvent(event);
2455
+ element.dispatchEvent(event);
2360
2456
  }
2361
2457
 
2362
2458
  handleEvent(event) {
2363
- if (!this.element.disableEventShow) {
2364
- switch (event.type) {
2365
- case "keydown": {
2366
- // Support both Enter and Space keys for accessibility
2367
- // Space is included as it's expected behavior for interactive elements
2368
-
2369
- const origin = event.composedPath()[0];
2370
- if (
2371
- event.key === "Enter" ||
2372
- (event.key === " " && (!origin || origin.tagName !== "INPUT"))
2373
- ) {
2374
- event.preventDefault();
2375
- this.handleClick();
2376
- }
2377
- break;
2378
- }
2379
- case "mouseenter":
2380
- if (this.element.hoverToggle) {
2381
- this.showBib();
2382
- }
2383
- break;
2384
- case "mouseleave":
2385
- if (this.element.hoverToggle) {
2386
- this.hideBib("mouseleave");
2387
- }
2388
- break;
2389
- case "focus":
2390
- if (this.element.focusShow) {
2391
- /*
2392
- This needs to better handle clicking that gives focus -
2393
- currently it shows and then immediately hides the bib
2394
- */
2395
- this.showBib();
2396
- }
2397
- break;
2398
- case "blur":
2399
- // send this task 100ms later queue to
2400
- // wait a frame in case focus moves within the floating element/bib
2401
- setTimeout(() => this.handleFocusLoss(), 0);
2402
- break;
2403
- case "click":
2404
- if (document.activeElement === document.body) {
2405
- event.currentTarget.focus();
2406
- }
2459
+ const element = this.element;
2460
+ if (!element || element.disableEventShow) {
2461
+ return;
2462
+ }
2463
+
2464
+ switch (event.type) {
2465
+ case "keydown": {
2466
+ // Support both Enter and Space keys for accessibility
2467
+ // Space is included as it's expected behavior for interactive elements
2468
+
2469
+ const origin = event.composedPath()[0];
2470
+ if (
2471
+ event.key === "Enter" ||
2472
+ (event.key === " " && (!origin || origin.tagName !== "INPUT"))
2473
+ ) {
2474
+ event.preventDefault();
2407
2475
  this.handleClick();
2408
- break;
2409
- // Do nothing
2476
+ }
2477
+ break;
2410
2478
  }
2479
+ case "mouseenter":
2480
+ if (element.hoverToggle) {
2481
+ this.showBib();
2482
+ }
2483
+ break;
2484
+ case "mouseleave":
2485
+ if (element.hoverToggle) {
2486
+ this.hideBib("mouseleave");
2487
+ }
2488
+ break;
2489
+ case "focus":
2490
+ if (element.focusShow) {
2491
+ /*
2492
+ This needs to better handle clicking that gives focus -
2493
+ currently it shows and then immediately hides the bib
2494
+ */
2495
+ this.showBib();
2496
+ }
2497
+ break;
2498
+ case "blur":
2499
+ // send this task 100ms later queue to
2500
+ // wait a frame in case focus moves within the floating element/bib
2501
+ setTimeout(() => this.handleFocusLoss(), 0);
2502
+ break;
2503
+ case "click":
2504
+ if (document.activeElement === document.body) {
2505
+ event.currentTarget.focus();
2506
+ }
2507
+ this.handleClick();
2508
+ break;
2509
+ // Do nothing
2411
2510
  }
2412
2511
  }
2413
2512
 
@@ -2418,6 +2517,11 @@ class AuroFloatingUI {
2418
2517
  * This prevents the component itself from being focusable when the trigger element already handles focus.
2419
2518
  */
2420
2519
  handleTriggerTabIndex() {
2520
+ const element = this.element;
2521
+ if (!element) {
2522
+ return;
2523
+ }
2524
+
2421
2525
  const focusableElementSelectors = [
2422
2526
  "a",
2423
2527
  "button",
@@ -2430,7 +2534,7 @@ class AuroFloatingUI {
2430
2534
  "auro-hyperlink",
2431
2535
  ];
2432
2536
 
2433
- const triggerNode = this.element.querySelectorAll('[slot="trigger"]')[0];
2537
+ const triggerNode = element.querySelectorAll('[slot="trigger"]')[0];
2434
2538
  if (!triggerNode) {
2435
2539
  return;
2436
2540
  }
@@ -2439,13 +2543,13 @@ class AuroFloatingUI {
2439
2543
  focusableElementSelectors.forEach((selector) => {
2440
2544
  // Check if the trigger node element is focusable
2441
2545
  if (triggerNodeTagName === selector) {
2442
- this.element.tabIndex = -1;
2546
+ element.tabIndex = -1;
2443
2547
  return;
2444
2548
  }
2445
2549
 
2446
2550
  // Check if any child is focusable
2447
2551
  if (triggerNode.querySelector(selector)) {
2448
- this.element.tabIndex = -1;
2552
+ element.tabIndex = -1;
2449
2553
  }
2450
2554
  });
2451
2555
  }
@@ -2455,13 +2559,18 @@ class AuroFloatingUI {
2455
2559
  * @param {*} eventPrefix
2456
2560
  */
2457
2561
  regenerateBibId() {
2458
- this.id = this.element.getAttribute("id");
2562
+ const element = this.element;
2563
+ if (!element) {
2564
+ return;
2565
+ }
2566
+
2567
+ this.id = element.getAttribute("id");
2459
2568
  if (!this.id) {
2460
2569
  this.id = window.crypto.randomUUID();
2461
- this.element.setAttribute("id", this.id);
2570
+ element.setAttribute("id", this.id);
2462
2571
  }
2463
2572
 
2464
- this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
2573
+ element.bib?.setAttribute("id", `${this.id}-floater-bib`);
2465
2574
  }
2466
2575
 
2467
2576
  configure(elem, eventPrefix, enableKeyboardHandling = true) {
@@ -2473,67 +2582,69 @@ class AuroFloatingUI {
2473
2582
  this.element = elem;
2474
2583
  }
2475
2584
 
2476
- if (this.behavior !== this.element.behavior) {
2477
- this.behavior = this.element.behavior;
2585
+ const element = this.element;
2586
+ if (!element) {
2587
+ return;
2478
2588
  }
2479
2589
 
2480
- if (this.element.trigger) {
2481
- this.disconnect();
2590
+ if (this.behavior !== element.behavior) {
2591
+ this.behavior = element.behavior;
2482
2592
  }
2483
- this.element.trigger =
2484
- this.element.triggerElement ||
2485
- this.element.shadowRoot.querySelector("#trigger") ||
2486
- this.element.trigger;
2487
- this.element.bib =
2488
- this.element.shadowRoot.querySelector("#bib") || this.element.bib;
2489
- this.element.bibSizer = this.element.shadowRoot.querySelector("#bibSizer");
2490
- this.element.triggerChevron =
2491
- this.element.shadowRoot.querySelector("#showStateIcon");
2492
2593
 
2493
- if (this.element.floaterConfig) {
2494
- this.element.hoverToggle = this.element.floaterConfig.hoverToggle;
2594
+ if (element.trigger) {
2595
+ this.disconnect();
2596
+ }
2597
+ element.trigger =
2598
+ element.triggerElement ||
2599
+ element.shadowRoot?.querySelector("#trigger") ||
2600
+ element.trigger;
2601
+ element.bib = element.shadowRoot?.querySelector("#bib") || element.bib;
2602
+ element.bibSizer = element.shadowRoot?.querySelector("#bibSizer");
2603
+ element.triggerChevron =
2604
+ element.shadowRoot?.querySelector("#showStateIcon");
2605
+
2606
+ if (element.floaterConfig) {
2607
+ element.hoverToggle = element.floaterConfig.hoverToggle;
2495
2608
  }
2496
2609
 
2497
2610
  this.regenerateBibId();
2498
2611
  this.handleTriggerTabIndex();
2499
2612
 
2500
2613
  this.handleEvent = this.handleEvent.bind(this);
2501
- if (this.element.trigger) {
2614
+ if (element.trigger) {
2502
2615
  if (this.enableKeyboardHandling) {
2503
- this.element.trigger.addEventListener("keydown", this.handleEvent);
2616
+ element.trigger.addEventListener("keydown", this.handleEvent);
2504
2617
  }
2505
- this.element.trigger.addEventListener("click", this.handleEvent);
2506
- this.element.trigger.addEventListener("mouseenter", this.handleEvent);
2507
- this.element.trigger.addEventListener("mouseleave", this.handleEvent);
2508
- this.element.trigger.addEventListener("focus", this.handleEvent);
2509
- this.element.trigger.addEventListener("blur", this.handleEvent);
2618
+ element.trigger.addEventListener("click", this.handleEvent);
2619
+ element.trigger.addEventListener("mouseenter", this.handleEvent);
2620
+ element.trigger.addEventListener("mouseleave", this.handleEvent);
2621
+ element.trigger.addEventListener("focus", this.handleEvent);
2622
+ element.trigger.addEventListener("blur", this.handleEvent);
2510
2623
  }
2511
2624
  }
2512
2625
 
2513
2626
  disconnect() {
2514
2627
  this.cleanupHideHandlers();
2515
- if (this.element) {
2516
- this.element.cleanup?.();
2517
2628
 
2518
- if (this.element.bib) {
2519
- this.element.shadowRoot.append(this.element.bib);
2520
- }
2629
+ const element = this.element;
2630
+ if (!element) {
2631
+ return;
2632
+ }
2521
2633
 
2522
- // Remove event & keyboard listeners
2523
- if (this.element?.trigger) {
2524
- this.element.trigger.removeEventListener("keydown", this.handleEvent);
2525
- this.element.trigger.removeEventListener("click", this.handleEvent);
2526
- this.element.trigger.removeEventListener(
2527
- "mouseenter",
2528
- this.handleEvent,
2529
- );
2530
- this.element.trigger.removeEventListener(
2531
- "mouseleave",
2532
- this.handleEvent,
2533
- );
2534
- this.element.trigger.removeEventListener("focus", this.handleEvent);
2535
- this.element.trigger.removeEventListener("blur", this.handleEvent);
2536
- }
2634
+ element.cleanup?.();
2635
+
2636
+ if (element.bib && element.shadowRoot) {
2637
+ element.shadowRoot.append(element.bib);
2638
+ }
2639
+
2640
+ // Remove event & keyboard listeners
2641
+ if (element.trigger) {
2642
+ element.trigger.removeEventListener("keydown", this.handleEvent);
2643
+ element.trigger.removeEventListener("click", this.handleEvent);
2644
+ element.trigger.removeEventListener("mouseenter", this.handleEvent);
2645
+ element.trigger.removeEventListener("mouseleave", this.handleEvent);
2646
+ element.trigger.removeEventListener("focus", this.handleEvent);
2647
+ element.trigger.removeEventListener("blur", this.handleEvent);
2537
2648
  }
2538
2649
  }
2539
2650
  }
@@ -3692,7 +3803,7 @@ class AuroHelpText extends i {
3692
3803
  }
3693
3804
  }
3694
3805
 
3695
- var formkitVersion = '202604072212';
3806
+ var formkitVersion = '202604091759';
3696
3807
 
3697
3808
  class AuroElement extends i {
3698
3809
  static get properties() {
@@ -3798,7 +3909,7 @@ class AuroElement extends i {
3798
3909
  }
3799
3910
  }
3800
3911
 
3801
- // Copyright (c) 2026 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
3912
+ // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
3802
3913
  // See LICENSE in the project root for license information.
3803
3914
 
3804
3915