@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
@@ -1840,11 +1840,19 @@ class AuroFloatingUI {
1840
1840
  * This ensures that the bib content has the same dimensions as the sizer element.
1841
1841
  */
1842
1842
  mirrorSize() {
1843
+ const element = this.element;
1844
+ if (!element) {
1845
+ return;
1846
+ }
1847
+
1843
1848
  // mirror the boxsize from bibSizer
1844
- if (this.element.bibSizer && this.element.matchWidth) {
1845
- const sizerStyle = window.getComputedStyle(this.element.bibSizer);
1846
- const bibContent =
1847
- this.element.bib.shadowRoot.querySelector(".container");
1849
+ if (element.bibSizer && element.matchWidth && element.bib?.shadowRoot) {
1850
+ const sizerStyle = window.getComputedStyle(element.bibSizer);
1851
+ const bibContent = element.bib.shadowRoot.querySelector(".container");
1852
+ if (!bibContent) {
1853
+ return;
1854
+ }
1855
+
1848
1856
  if (sizerStyle.width !== "0px") {
1849
1857
  bibContent.style.width = sizerStyle.width;
1850
1858
  }
@@ -1866,9 +1874,14 @@ class AuroFloatingUI {
1866
1874
  * @returns {String} The positioning strategy, one of 'fullscreen', 'floating', 'cover'.
1867
1875
  */
1868
1876
  getPositioningStrategy() {
1877
+ const element = this.element;
1878
+ if (!element) {
1879
+ return "floating";
1880
+ }
1881
+
1869
1882
  const breakpoint =
1870
- this.element.bib.mobileFullscreenBreakpoint ||
1871
- this.element.floaterConfig?.fullscreenBreakpoint;
1883
+ element.bib?.mobileFullscreenBreakpoint ||
1884
+ element.floaterConfig?.fullscreenBreakpoint;
1872
1885
  switch (this.behavior) {
1873
1886
  case "tooltip":
1874
1887
  return "floating";
@@ -1879,9 +1892,9 @@ class AuroFloatingUI {
1879
1892
  `(max-width: ${breakpoint})`,
1880
1893
  ).matches;
1881
1894
 
1882
- this.element.expanded = smallerThanBreakpoint;
1895
+ element.expanded = smallerThanBreakpoint;
1883
1896
  }
1884
- if (this.element.nested) {
1897
+ if (element.nested) {
1885
1898
  return "cover";
1886
1899
  }
1887
1900
  return "fullscreen";
@@ -1911,42 +1924,65 @@ class AuroFloatingUI {
1911
1924
  * and applies the calculated position to the bib's style.
1912
1925
  */
1913
1926
  position() {
1927
+ const element = this.element;
1928
+ if (!element) {
1929
+ return;
1930
+ }
1931
+
1914
1932
  const strategy = this.getPositioningStrategy();
1915
1933
  this.configureBibStrategy(strategy);
1916
1934
 
1917
1935
  if (strategy === "floating") {
1936
+ if (!element.trigger || !element.bib) {
1937
+ return;
1938
+ }
1939
+
1918
1940
  this.mirrorSize();
1919
1941
  // Define the middlware for the floater configuration
1920
1942
  const middleware = [
1921
- offset(this.element.floaterConfig?.offset || 0),
1922
- ...(this.element.floaterConfig?.shift ? [shift()] : []), // Add shift middleware if shift is enabled.
1923
- ...(this.element.floaterConfig?.flip ? [flip()] : []), // Add flip middleware if flip is enabled.
1924
- ...(this.element.floaterConfig?.autoPlacement ? [autoPlacement()] : []), // Add autoPlacement middleware if autoPlacement is enabled.
1943
+ offset(element.floaterConfig?.offset || 0),
1944
+ ...(element.floaterConfig?.shift ? [shift()] : []), // Add shift middleware if shift is enabled.
1945
+ ...(element.floaterConfig?.flip ? [flip()] : []), // Add flip middleware if flip is enabled.
1946
+ ...(element.floaterConfig?.autoPlacement ? [autoPlacement()] : []), // Add autoPlacement middleware if autoPlacement is enabled.
1925
1947
  ];
1926
1948
 
1927
1949
  // Compute the position of the bib
1928
- computePosition(this.element.trigger, this.element.bib, {
1929
- strategy: this.element.floaterConfig?.strategy || "fixed",
1930
- placement: this.element.floaterConfig?.placement,
1950
+ computePosition(element.trigger, element.bib, {
1951
+ strategy: element.floaterConfig?.strategy || "fixed",
1952
+ placement: element.floaterConfig?.placement,
1931
1953
  middleware: middleware || [],
1932
1954
  }).then(({ x, y }) => {
1933
1955
  // eslint-disable-line id-length
1934
- Object.assign(this.element.bib.style, {
1956
+ const currentElement = this.element;
1957
+ if (!currentElement?.bib) {
1958
+ return;
1959
+ }
1960
+
1961
+ Object.assign(currentElement.bib.style, {
1935
1962
  left: `${x}px`,
1936
1963
  top: `${y}px`,
1937
1964
  });
1938
1965
  });
1939
1966
  } else if (strategy === "cover") {
1967
+ if (!element.parentNode || !element.bib) {
1968
+ return;
1969
+ }
1970
+
1940
1971
  // Compute the position of the bib
1941
- computePosition(this.element.parentNode, this.element.bib, {
1972
+ computePosition(element.parentNode, element.bib, {
1942
1973
  placement: "bottom-start",
1943
1974
  }).then(({ x, y }) => {
1944
1975
  // eslint-disable-line id-length
1945
- Object.assign(this.element.bib.style, {
1976
+ const currentElement = this.element;
1977
+ if (!currentElement?.bib || !currentElement.parentNode) {
1978
+ return;
1979
+ }
1980
+
1981
+ Object.assign(currentElement.bib.style, {
1946
1982
  left: `${x}px`,
1947
- top: `${y - this.element.parentNode.offsetHeight}px`,
1948
- width: `${this.element.parentNode.offsetWidth}px`,
1949
- height: `${this.element.parentNode.offsetHeight}px`,
1983
+ top: `${y - currentElement.parentNode.offsetHeight}px`,
1984
+ width: `${currentElement.parentNode.offsetWidth}px`,
1985
+ height: `${currentElement.parentNode.offsetHeight}px`,
1950
1986
  });
1951
1987
  });
1952
1988
  }
@@ -1958,11 +1994,17 @@ class AuroFloatingUI {
1958
1994
  * @param {Boolean} lock - If true, locks the body's scrolling functionlity; otherwise, unlock.
1959
1995
  */
1960
1996
  lockScroll(lock = true) {
1997
+ const element = this.element;
1998
+
1961
1999
  if (lock) {
2000
+ if (!element?.bib) {
2001
+ return;
2002
+ }
2003
+
1962
2004
  document.body.style.overflow = "hidden"; // hide body's scrollbar
1963
2005
 
1964
2006
  // Move `bib` by the amount the viewport is shifted to stay aligned in fullscreen.
1965
- this.element.bib.style.transform = `translateY(${window?.visualViewport?.offsetTop}px)`;
2007
+ element.bib.style.transform = `translateY(${window?.visualViewport?.offsetTop}px)`;
1966
2008
  } else {
1967
2009
  document.body.style.overflow = "";
1968
2010
  }
@@ -1978,20 +2020,24 @@ class AuroFloatingUI {
1978
2020
  * @param {string} strategy - The positioning strategy ('fullscreen' or 'floating').
1979
2021
  */
1980
2022
  configureBibStrategy(value) {
2023
+ const element = this.element;
2024
+ if (!element?.bib) {
2025
+ return;
2026
+ }
2027
+
1981
2028
  if (value === "fullscreen") {
1982
- this.element.isBibFullscreen = true;
2029
+ element.isBibFullscreen = true;
1983
2030
  // reset the prev position
1984
- this.element.bib.setAttribute("isfullscreen", "");
1985
- this.element.bib.style.position = "fixed";
1986
- this.element.bib.style.top = "0px";
1987
- this.element.bib.style.left = "0px";
1988
- this.element.bib.style.width = "";
1989
- this.element.bib.style.height = "";
1990
- this.element.style.contain = "";
2031
+ element.bib.setAttribute("isfullscreen", "");
2032
+ element.bib.style.position = "fixed";
2033
+ element.bib.style.top = "0px";
2034
+ element.bib.style.left = "0px";
2035
+ element.bib.style.width = "";
2036
+ element.bib.style.height = "";
2037
+ element.style.contain = "";
1991
2038
 
1992
2039
  // reset the size that was mirroring `size` css-part
1993
- const bibContent =
1994
- this.element.bib.shadowRoot.querySelector(".container");
2040
+ const bibContent = element.bib.shadowRoot?.querySelector(".container");
1995
2041
  if (bibContent) {
1996
2042
  bibContent.style.width = "";
1997
2043
  bibContent.style.height = "";
@@ -2006,14 +2052,14 @@ class AuroFloatingUI {
2006
2052
  }, 0);
2007
2053
  }
2008
2054
 
2009
- if (this.element.isPopoverVisible) {
2055
+ if (element.isPopoverVisible) {
2010
2056
  this.lockScroll(true);
2011
2057
  }
2012
2058
  } else {
2013
- this.element.bib.style.position = "";
2014
- this.element.bib.removeAttribute("isfullscreen");
2015
- this.element.isBibFullscreen = false;
2016
- this.element.style.contain = "layout";
2059
+ element.bib.style.position = "";
2060
+ element.bib.removeAttribute("isfullscreen");
2061
+ element.isBibFullscreen = false;
2062
+ element.style.contain = "layout";
2017
2063
  }
2018
2064
 
2019
2065
  const isChanged = this.strategy && this.strategy !== value;
@@ -2031,16 +2077,21 @@ class AuroFloatingUI {
2031
2077
  },
2032
2078
  );
2033
2079
 
2034
- this.element.dispatchEvent(event);
2080
+ element.dispatchEvent(event);
2035
2081
  }
2036
2082
  }
2037
2083
 
2038
2084
  updateState() {
2039
- const isVisible = this.element.isPopoverVisible;
2085
+ const element = this.element;
2086
+ if (!element) {
2087
+ return;
2088
+ }
2089
+
2090
+ const isVisible = element.isPopoverVisible;
2040
2091
  if (!isVisible) {
2041
2092
  this.cleanupHideHandlers();
2042
2093
  try {
2043
- this.element.cleanup?.();
2094
+ element.cleanup?.();
2044
2095
  } catch (error) {
2045
2096
  // Do nothing
2046
2097
  }
@@ -2056,28 +2107,30 @@ class AuroFloatingUI {
2056
2107
  * If not, and if the bib isn't in fullscreen mode with focus lost, it hides the bib.
2057
2108
  */
2058
2109
  handleFocusLoss() {
2110
+ const element = this.element;
2111
+ if (!element?.bib) {
2112
+ return;
2113
+ }
2114
+
2059
2115
  // if mouse is being pressed, skip and let click event to handle the action
2060
2116
  if (AuroFloatingUI.isMousePressed) {
2061
2117
  return;
2062
2118
  }
2063
2119
 
2064
2120
  if (
2065
- this.element.noHideOnThisFocusLoss ||
2066
- this.element.hasAttribute("noHideOnThisFocusLoss")
2121
+ element.noHideOnThisFocusLoss ||
2122
+ element.hasAttribute("noHideOnThisFocusLoss")
2067
2123
  ) {
2068
2124
  return;
2069
2125
  }
2070
2126
 
2071
2127
  // if focus is still inside of trigger or bib, do not close
2072
- if (
2073
- this.element.matches(":focus") ||
2074
- this.element.matches(":focus-within")
2075
- ) {
2128
+ if (element.matches(":focus") || element.matches(":focus-within")) {
2076
2129
  return;
2077
2130
  }
2078
2131
 
2079
2132
  // if fullscreen bib is in fullscreen mode, do not close
2080
- if (this.element.bib.hasAttribute("isfullscreen")) {
2133
+ if (element.bib.hasAttribute("isfullscreen")) {
2081
2134
  return;
2082
2135
  }
2083
2136
 
@@ -2085,23 +2138,33 @@ class AuroFloatingUI {
2085
2138
  }
2086
2139
 
2087
2140
  setupHideHandlers() {
2141
+ const element = this.element;
2142
+ if (!element) {
2143
+ return;
2144
+ }
2145
+
2088
2146
  // Define handlers & store references
2089
2147
  this.focusHandler = () => this.handleFocusLoss();
2090
2148
 
2091
2149
  this.clickHandler = (evt) => {
2150
+ const element = this.element;
2151
+ if (!element?.bib) {
2152
+ return;
2153
+ }
2154
+
2092
2155
  // When the bib is fullscreen (modal dialog), don't close on outside
2093
2156
  // clicks. VoiceOver's synthetic click events inside a top-layer modal
2094
2157
  // <dialog> may not include the bib in composedPath(), causing false
2095
2158
  // positives. This mirrors the fullscreen guard in handleFocusLoss().
2096
- if (this.element.bib && this.element.bib.hasAttribute("isfullscreen")) {
2159
+ if (element.bib.hasAttribute("isfullscreen")) {
2097
2160
  return;
2098
2161
  }
2099
2162
 
2100
2163
  if (
2101
- (!evt.composedPath().includes(this.element.trigger) &&
2102
- !evt.composedPath().includes(this.element.bib)) ||
2103
- (this.element.bib.backdrop &&
2104
- evt.composedPath().includes(this.element.bib.backdrop))
2164
+ (!evt.composedPath().includes(element.trigger) &&
2165
+ !evt.composedPath().includes(element.bib)) ||
2166
+ (element.bib.backdrop &&
2167
+ evt.composedPath().includes(element.bib.backdrop))
2105
2168
  ) {
2106
2169
  const existedVisibleFloatingUI =
2107
2170
  document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
@@ -2122,7 +2185,12 @@ class AuroFloatingUI {
2122
2185
 
2123
2186
  // ESC key handler
2124
2187
  this.keyDownHandler = (evt) => {
2125
- if (evt.key === "Escape" && this.element.isPopoverVisible) {
2188
+ const element = this.element;
2189
+ if (!element) {
2190
+ return;
2191
+ }
2192
+
2193
+ if (evt.key === "Escape" && element.isPopoverVisible) {
2126
2194
  const existedVisibleFloatingUI =
2127
2195
  document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
2128
2196
  if (
@@ -2179,6 +2247,10 @@ class AuroFloatingUI {
2179
2247
  }
2180
2248
 
2181
2249
  updateCurrentExpandedDropdown() {
2250
+ if (!this.element) {
2251
+ return;
2252
+ }
2253
+
2182
2254
  // Close any other dropdown that is already open
2183
2255
  const existedVisibleFloatingUI =
2184
2256
  document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
@@ -2195,25 +2267,34 @@ class AuroFloatingUI {
2195
2267
  }
2196
2268
 
2197
2269
  showBib() {
2198
- if (!this.element.disabled && !this.showing) {
2270
+ const element = this.element;
2271
+ if (!element) {
2272
+ return;
2273
+ }
2274
+
2275
+ if (!element.bib || (!element.trigger && !element.parentNode)) {
2276
+ return;
2277
+ }
2278
+
2279
+ if (!element.disabled && !this.showing) {
2199
2280
  this.updateCurrentExpandedDropdown();
2200
- this.element.triggerChevron?.setAttribute("data-expanded", true);
2281
+ element.triggerChevron?.setAttribute("data-expanded", true);
2201
2282
 
2202
2283
  // prevent double showing: isPopovervisible gets first and showBib gets called later
2203
2284
  if (!this.showing) {
2204
- if (!this.element.modal) {
2285
+ if (!element.modal) {
2205
2286
  this.setupHideHandlers();
2206
2287
  }
2207
2288
  this.showing = true;
2208
- this.element.isPopoverVisible = true;
2289
+ element.isPopoverVisible = true;
2209
2290
  this.position();
2210
2291
  this.dispatchEventDropdownToggle();
2211
2292
  }
2212
2293
 
2213
2294
  // Setup auto update to handle resize and scroll
2214
- this.element.cleanup = autoUpdate(
2215
- this.element.trigger || this.element.parentNode,
2216
- this.element.bib,
2295
+ element.cleanup = autoUpdate(
2296
+ element.trigger || element.parentNode,
2297
+ element.bib,
2217
2298
  () => {
2218
2299
  this.position();
2219
2300
  },
@@ -2226,22 +2307,27 @@ class AuroFloatingUI {
2226
2307
  * @param {String} eventType - The event type that triggered the hiding action.
2227
2308
  */
2228
2309
  hideBib(eventType = "unknown") {
2229
- if (this.element.disabled) {
2310
+ const element = this.element;
2311
+ if (!element) {
2312
+ return;
2313
+ }
2314
+
2315
+ if (element.disabled) {
2230
2316
  return;
2231
2317
  }
2232
2318
 
2233
2319
  // noToggle dropdowns should not close when the trigger is clicked (the
2234
2320
  // "toggle" behavior), but they CAN still close via other interactions like
2235
2321
  // Escape key or focus loss.
2236
- if (this.element.noToggle && eventType === "click") {
2322
+ if (element.noToggle && eventType === "click") {
2237
2323
  return;
2238
2324
  }
2239
2325
 
2240
2326
  this.lockScroll(false);
2241
- this.element.triggerChevron?.removeAttribute("data-expanded");
2327
+ element.triggerChevron?.removeAttribute("data-expanded");
2242
2328
 
2243
- if (this.element.isPopoverVisible) {
2244
- this.element.isPopoverVisible = false;
2329
+ if (element.isPopoverVisible) {
2330
+ element.isPopoverVisible = false;
2245
2331
  }
2246
2332
  if (this.showing) {
2247
2333
  this.cleanupHideHandlers();
@@ -2261,6 +2347,11 @@ class AuroFloatingUI {
2261
2347
  * @param {String} eventType - The event type that triggered the toggle action.
2262
2348
  */
2263
2349
  dispatchEventDropdownToggle(eventType) {
2350
+ const element = this.element;
2351
+ if (!element) {
2352
+ return;
2353
+ }
2354
+
2264
2355
  const event = new CustomEvent(
2265
2356
  this.eventPrefix ? `${this.eventPrefix}-toggled` : "toggled",
2266
2357
  {
@@ -2272,11 +2363,16 @@ class AuroFloatingUI {
2272
2363
  },
2273
2364
  );
2274
2365
 
2275
- this.element.dispatchEvent(event);
2366
+ element.dispatchEvent(event);
2276
2367
  }
2277
2368
 
2278
2369
  handleClick() {
2279
- if (this.element.isPopoverVisible) {
2370
+ const element = this.element;
2371
+ if (!element) {
2372
+ return;
2373
+ }
2374
+
2375
+ if (element.isPopoverVisible) {
2280
2376
  this.hideBib("click");
2281
2377
  } else {
2282
2378
  this.showBib();
@@ -2287,63 +2383,66 @@ class AuroFloatingUI {
2287
2383
  {
2288
2384
  composed: true,
2289
2385
  detail: {
2290
- expanded: this.element.isPopoverVisible,
2386
+ expanded: element.isPopoverVisible,
2291
2387
  },
2292
2388
  },
2293
2389
  );
2294
2390
 
2295
- this.element.dispatchEvent(event);
2391
+ element.dispatchEvent(event);
2296
2392
  }
2297
2393
 
2298
2394
  handleEvent(event) {
2299
- if (!this.element.disableEventShow) {
2300
- switch (event.type) {
2301
- case "keydown": {
2302
- // Support both Enter and Space keys for accessibility
2303
- // Space is included as it's expected behavior for interactive elements
2304
-
2305
- const origin = event.composedPath()[0];
2306
- if (
2307
- event.key === "Enter" ||
2308
- (event.key === " " && (!origin || origin.tagName !== "INPUT"))
2309
- ) {
2310
- event.preventDefault();
2311
- this.handleClick();
2312
- }
2313
- break;
2314
- }
2315
- case "mouseenter":
2316
- if (this.element.hoverToggle) {
2317
- this.showBib();
2318
- }
2319
- break;
2320
- case "mouseleave":
2321
- if (this.element.hoverToggle) {
2322
- this.hideBib("mouseleave");
2323
- }
2324
- break;
2325
- case "focus":
2326
- if (this.element.focusShow) {
2327
- /*
2328
- This needs to better handle clicking that gives focus -
2329
- currently it shows and then immediately hides the bib
2330
- */
2331
- this.showBib();
2332
- }
2333
- break;
2334
- case "blur":
2335
- // send this task 100ms later queue to
2336
- // wait a frame in case focus moves within the floating element/bib
2337
- setTimeout(() => this.handleFocusLoss(), 0);
2338
- break;
2339
- case "click":
2340
- if (document.activeElement === document.body) {
2341
- event.currentTarget.focus();
2342
- }
2395
+ const element = this.element;
2396
+ if (!element || element.disableEventShow) {
2397
+ return;
2398
+ }
2399
+
2400
+ switch (event.type) {
2401
+ case "keydown": {
2402
+ // Support both Enter and Space keys for accessibility
2403
+ // Space is included as it's expected behavior for interactive elements
2404
+
2405
+ const origin = event.composedPath()[0];
2406
+ if (
2407
+ event.key === "Enter" ||
2408
+ (event.key === " " && (!origin || origin.tagName !== "INPUT"))
2409
+ ) {
2410
+ event.preventDefault();
2343
2411
  this.handleClick();
2344
- break;
2345
- // Do nothing
2412
+ }
2413
+ break;
2346
2414
  }
2415
+ case "mouseenter":
2416
+ if (element.hoverToggle) {
2417
+ this.showBib();
2418
+ }
2419
+ break;
2420
+ case "mouseleave":
2421
+ if (element.hoverToggle) {
2422
+ this.hideBib("mouseleave");
2423
+ }
2424
+ break;
2425
+ case "focus":
2426
+ if (element.focusShow) {
2427
+ /*
2428
+ This needs to better handle clicking that gives focus -
2429
+ currently it shows and then immediately hides the bib
2430
+ */
2431
+ this.showBib();
2432
+ }
2433
+ break;
2434
+ case "blur":
2435
+ // send this task 100ms later queue to
2436
+ // wait a frame in case focus moves within the floating element/bib
2437
+ setTimeout(() => this.handleFocusLoss(), 0);
2438
+ break;
2439
+ case "click":
2440
+ if (document.activeElement === document.body) {
2441
+ event.currentTarget.focus();
2442
+ }
2443
+ this.handleClick();
2444
+ break;
2445
+ // Do nothing
2347
2446
  }
2348
2447
  }
2349
2448
 
@@ -2354,6 +2453,11 @@ class AuroFloatingUI {
2354
2453
  * This prevents the component itself from being focusable when the trigger element already handles focus.
2355
2454
  */
2356
2455
  handleTriggerTabIndex() {
2456
+ const element = this.element;
2457
+ if (!element) {
2458
+ return;
2459
+ }
2460
+
2357
2461
  const focusableElementSelectors = [
2358
2462
  "a",
2359
2463
  "button",
@@ -2366,7 +2470,7 @@ class AuroFloatingUI {
2366
2470
  "auro-hyperlink",
2367
2471
  ];
2368
2472
 
2369
- const triggerNode = this.element.querySelectorAll('[slot="trigger"]')[0];
2473
+ const triggerNode = element.querySelectorAll('[slot="trigger"]')[0];
2370
2474
  if (!triggerNode) {
2371
2475
  return;
2372
2476
  }
@@ -2375,13 +2479,13 @@ class AuroFloatingUI {
2375
2479
  focusableElementSelectors.forEach((selector) => {
2376
2480
  // Check if the trigger node element is focusable
2377
2481
  if (triggerNodeTagName === selector) {
2378
- this.element.tabIndex = -1;
2482
+ element.tabIndex = -1;
2379
2483
  return;
2380
2484
  }
2381
2485
 
2382
2486
  // Check if any child is focusable
2383
2487
  if (triggerNode.querySelector(selector)) {
2384
- this.element.tabIndex = -1;
2488
+ element.tabIndex = -1;
2385
2489
  }
2386
2490
  });
2387
2491
  }
@@ -2391,13 +2495,18 @@ class AuroFloatingUI {
2391
2495
  * @param {*} eventPrefix
2392
2496
  */
2393
2497
  regenerateBibId() {
2394
- this.id = this.element.getAttribute("id");
2498
+ const element = this.element;
2499
+ if (!element) {
2500
+ return;
2501
+ }
2502
+
2503
+ this.id = element.getAttribute("id");
2395
2504
  if (!this.id) {
2396
2505
  this.id = window.crypto.randomUUID();
2397
- this.element.setAttribute("id", this.id);
2506
+ element.setAttribute("id", this.id);
2398
2507
  }
2399
2508
 
2400
- this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
2509
+ element.bib?.setAttribute("id", `${this.id}-floater-bib`);
2401
2510
  }
2402
2511
 
2403
2512
  configure(elem, eventPrefix, enableKeyboardHandling = true) {
@@ -2409,67 +2518,69 @@ class AuroFloatingUI {
2409
2518
  this.element = elem;
2410
2519
  }
2411
2520
 
2412
- if (this.behavior !== this.element.behavior) {
2413
- this.behavior = this.element.behavior;
2521
+ const element = this.element;
2522
+ if (!element) {
2523
+ return;
2414
2524
  }
2415
2525
 
2416
- if (this.element.trigger) {
2417
- this.disconnect();
2526
+ if (this.behavior !== element.behavior) {
2527
+ this.behavior = element.behavior;
2418
2528
  }
2419
- this.element.trigger =
2420
- this.element.triggerElement ||
2421
- this.element.shadowRoot.querySelector("#trigger") ||
2422
- this.element.trigger;
2423
- this.element.bib =
2424
- this.element.shadowRoot.querySelector("#bib") || this.element.bib;
2425
- this.element.bibSizer = this.element.shadowRoot.querySelector("#bibSizer");
2426
- this.element.triggerChevron =
2427
- this.element.shadowRoot.querySelector("#showStateIcon");
2428
2529
 
2429
- if (this.element.floaterConfig) {
2430
- this.element.hoverToggle = this.element.floaterConfig.hoverToggle;
2530
+ if (element.trigger) {
2531
+ this.disconnect();
2532
+ }
2533
+ element.trigger =
2534
+ element.triggerElement ||
2535
+ element.shadowRoot?.querySelector("#trigger") ||
2536
+ element.trigger;
2537
+ element.bib = element.shadowRoot?.querySelector("#bib") || element.bib;
2538
+ element.bibSizer = element.shadowRoot?.querySelector("#bibSizer");
2539
+ element.triggerChevron =
2540
+ element.shadowRoot?.querySelector("#showStateIcon");
2541
+
2542
+ if (element.floaterConfig) {
2543
+ element.hoverToggle = element.floaterConfig.hoverToggle;
2431
2544
  }
2432
2545
 
2433
2546
  this.regenerateBibId();
2434
2547
  this.handleTriggerTabIndex();
2435
2548
 
2436
2549
  this.handleEvent = this.handleEvent.bind(this);
2437
- if (this.element.trigger) {
2550
+ if (element.trigger) {
2438
2551
  if (this.enableKeyboardHandling) {
2439
- this.element.trigger.addEventListener("keydown", this.handleEvent);
2552
+ element.trigger.addEventListener("keydown", this.handleEvent);
2440
2553
  }
2441
- this.element.trigger.addEventListener("click", this.handleEvent);
2442
- this.element.trigger.addEventListener("mouseenter", this.handleEvent);
2443
- this.element.trigger.addEventListener("mouseleave", this.handleEvent);
2444
- this.element.trigger.addEventListener("focus", this.handleEvent);
2445
- this.element.trigger.addEventListener("blur", this.handleEvent);
2554
+ element.trigger.addEventListener("click", this.handleEvent);
2555
+ element.trigger.addEventListener("mouseenter", this.handleEvent);
2556
+ element.trigger.addEventListener("mouseleave", this.handleEvent);
2557
+ element.trigger.addEventListener("focus", this.handleEvent);
2558
+ element.trigger.addEventListener("blur", this.handleEvent);
2446
2559
  }
2447
2560
  }
2448
2561
 
2449
2562
  disconnect() {
2450
2563
  this.cleanupHideHandlers();
2451
- if (this.element) {
2452
- this.element.cleanup?.();
2453
2564
 
2454
- if (this.element.bib) {
2455
- this.element.shadowRoot.append(this.element.bib);
2456
- }
2565
+ const element = this.element;
2566
+ if (!element) {
2567
+ return;
2568
+ }
2457
2569
 
2458
- // Remove event & keyboard listeners
2459
- if (this.element?.trigger) {
2460
- this.element.trigger.removeEventListener("keydown", this.handleEvent);
2461
- this.element.trigger.removeEventListener("click", this.handleEvent);
2462
- this.element.trigger.removeEventListener(
2463
- "mouseenter",
2464
- this.handleEvent,
2465
- );
2466
- this.element.trigger.removeEventListener(
2467
- "mouseleave",
2468
- this.handleEvent,
2469
- );
2470
- this.element.trigger.removeEventListener("focus", this.handleEvent);
2471
- this.element.trigger.removeEventListener("blur", this.handleEvent);
2472
- }
2570
+ element.cleanup?.();
2571
+
2572
+ if (element.bib && element.shadowRoot) {
2573
+ element.shadowRoot.append(element.bib);
2574
+ }
2575
+
2576
+ // Remove event & keyboard listeners
2577
+ if (element.trigger) {
2578
+ element.trigger.removeEventListener("keydown", this.handleEvent);
2579
+ element.trigger.removeEventListener("click", this.handleEvent);
2580
+ element.trigger.removeEventListener("mouseenter", this.handleEvent);
2581
+ element.trigger.removeEventListener("mouseleave", this.handleEvent);
2582
+ element.trigger.removeEventListener("focus", this.handleEvent);
2583
+ element.trigger.removeEventListener("blur", this.handleEvent);
2473
2584
  }
2474
2585
  }
2475
2586
  }
@@ -3597,7 +3708,7 @@ class AuroHelpText extends LitElement {
3597
3708
  }
3598
3709
  }
3599
3710
 
3600
- var formkitVersion = '202604072212';
3711
+ var formkitVersion = '202604091759';
3601
3712
 
3602
3713
  class AuroElement extends LitElement {
3603
3714
  static get properties() {
@@ -3703,7 +3814,7 @@ class AuroElement extends LitElement {
3703
3814
  }
3704
3815
  }
3705
3816
 
3706
- // Copyright (c) 2026 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
3817
+ // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
3707
3818
  // See LICENSE in the project root for license information.
3708
3819
 
3709
3820