@aurodesignsystem/auro-formkit 2.2.1-beta.2 → 2.2.1-beta.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +67 -67
  3. package/components/checkbox/README.md +1 -1
  4. package/components/checkbox/demo/readme.md +1 -1
  5. package/components/combobox/README.md +1 -1
  6. package/components/combobox/demo/api.min.js +352 -94
  7. package/components/combobox/demo/index.min.js +352 -94
  8. package/components/combobox/demo/readme.md +1 -1
  9. package/components/combobox/dist/index.js +352 -94
  10. package/components/combobox/dist/registered.js +352 -94
  11. package/components/counter/README.md +1 -1
  12. package/components/counter/demo/api.min.js +353 -95
  13. package/components/counter/demo/index.min.js +353 -95
  14. package/components/counter/demo/readme.md +1 -1
  15. package/components/counter/dist/index.js +353 -95
  16. package/components/counter/dist/registered.js +353 -95
  17. package/components/datepicker/README.md +1 -1
  18. package/components/datepicker/demo/api.min.js +466 -232
  19. package/components/datepicker/demo/index.min.js +466 -232
  20. package/components/datepicker/demo/readme.md +1 -1
  21. package/components/datepicker/dist/index.js +354 -114
  22. package/components/datepicker/dist/registered.js +354 -114
  23. package/components/dropdown/README.md +1 -1
  24. package/components/dropdown/demo/api.min.js +352 -94
  25. package/components/dropdown/demo/index.min.js +352 -94
  26. package/components/dropdown/demo/readme.md +1 -1
  27. package/components/dropdown/dist/auro-dropdown.d.ts +18 -0
  28. package/components/dropdown/dist/index.js +352 -94
  29. package/components/dropdown/dist/registered.js +352 -94
  30. package/components/form/README.md +1 -1
  31. package/components/form/demo/readme.md +1 -1
  32. package/components/input/README.md +1 -1
  33. package/components/input/demo/readme.md +1 -1
  34. package/components/menu/README.md +1 -1
  35. package/components/menu/demo/readme.md +1 -1
  36. package/components/radio/README.md +1 -1
  37. package/components/radio/demo/readme.md +1 -1
  38. package/components/select/README.md +1 -1
  39. package/components/select/demo/api.min.js +352 -94
  40. package/components/select/demo/index.min.js +352 -94
  41. package/components/select/demo/readme.md +1 -1
  42. package/components/select/dist/index.js +352 -94
  43. package/components/select/dist/registered.js +352 -94
  44. package/package.json +2 -2
@@ -2005,17 +2005,70 @@ const computePosition = (reference, floating, options) => {
2005
2005
  /* eslint-disable line-comment-position, no-inline-comments */
2006
2006
 
2007
2007
 
2008
+
2009
+ const MAX_CONFIGURATION_COUNT = 10;
2010
+
2008
2011
  class AuroFloatingUI {
2009
- constructor() {
2012
+
2013
+ /**
2014
+ * @private
2015
+ */
2016
+ static isMousePressed = false;
2017
+
2018
+ /**
2019
+ * @private
2020
+ */
2021
+ static isMousePressHandlerInitialized = false;
2022
+
2023
+ /**
2024
+ * @private
2025
+ */
2026
+ static setupMousePressChecker() {
2027
+ if (!AuroFloatingUI.isMousePressHandlerInitialized && window && window.addEventListener) {
2028
+ AuroFloatingUI.isMousePressHandlerInitialized = true;
2029
+
2030
+ const mouseEventGlobalHandler = (event) => {
2031
+ AuroFloatingUI.isMousePressed = event.type === 'mousedown';
2032
+ };
2033
+
2034
+ window.addEventListener('mousedown', mouseEventGlobalHandler);
2035
+ window.addEventListener('mouseup', mouseEventGlobalHandler);
2036
+ }
2037
+ }
2038
+
2039
+ constructor(element, behavior) {
2040
+ this.element = element;
2041
+ this.behavior = behavior;
2042
+
2010
2043
  // Store event listener references for cleanup
2011
2044
  this.focusHandler = null;
2012
2045
  this.clickHandler = null;
2013
2046
  this.keyDownHandler = null;
2014
-
2047
+
2048
+ /**
2049
+ * @private
2050
+ */
2051
+ this.configureTrial = 0;
2052
+
2015
2053
  /**
2016
2054
  * @private
2017
2055
  */
2018
2056
  this.eventPrefix = undefined;
2057
+
2058
+ /**
2059
+ * @private
2060
+ */
2061
+ this.id = undefined;
2062
+
2063
+ /**
2064
+ * @private
2065
+ */
2066
+ this.showing = false;
2067
+
2068
+ /**
2069
+ * @private
2070
+ */
2071
+ this.strategy = undefined;
2019
2072
  }
2020
2073
 
2021
2074
  /**
@@ -2043,29 +2096,48 @@ class AuroFloatingUI {
2043
2096
  * @private
2044
2097
  * Determines the positioning strategy based on the current viewport size and mobile breakpoint.
2045
2098
  *
2046
- * This method checks if the current viewport width is less than or equal to the specified mobile fullscreen breakpoint
2099
+ * This method checks if the current viewport width is less than or equal to the specified mobile fullscreen breakpoint
2047
2100
  * defined in the bib element. If it is, the strategy is set to 'fullscreen'; otherwise, it defaults to 'floating'.
2048
2101
  *
2049
- * @returns {String} The positioning strategy, either 'fullscreen' or 'floating'.
2102
+ * @returns {String} The positioning strategy, one of 'fullscreen', 'floating', 'cover'.
2050
2103
  */
2051
2104
  getPositioningStrategy() {
2052
- let strategy = 'floating';
2053
- if (this.element.bib.mobileFullscreenBreakpoint) {
2054
- const smallerThanBreakpoint = window.matchMedia(`(max-width: ${this.element.bib.mobileFullscreenBreakpoint})`).matches;
2055
- if (smallerThanBreakpoint) {
2056
- strategy = 'fullscreen';
2057
- }
2105
+ const breakpoint = this.element.bib.mobileFullscreenBreakpoint || this.element.floaterConfig?.fullscreenBreakpoint;
2106
+ switch (this.behavior) {
2107
+ case "tooltip":
2108
+ return "floating";
2109
+ case "dialog":
2110
+ case "drawer":
2111
+ if (breakpoint) {
2112
+ const smallerThanBreakpoint = window.matchMedia(`(max-width: ${breakpoint})`).matches;
2113
+
2114
+ this.element.expanded = smallerThanBreakpoint;
2115
+ }
2116
+ if (this.element.nested) {
2117
+ return "cover";
2118
+ }
2119
+ return 'fullscreen';
2120
+ case "dropdown":
2121
+ case undefined:
2122
+ case null:
2123
+ if (breakpoint) {
2124
+ const smallerThanBreakpoint = window.matchMedia(`(max-width: ${breakpoint})`).matches;
2125
+ if (smallerThanBreakpoint) {
2126
+ return 'fullscreen';
2127
+ }
2128
+ }
2129
+ return "floating";
2130
+ default:
2131
+ return this.behavior;
2058
2132
  }
2059
-
2060
- return strategy;
2061
2133
  }
2062
2134
 
2063
2135
  /**
2064
2136
  * @private
2065
2137
  * Positions the bib element based on the current configuration and positioning strategy.
2066
2138
  *
2067
- * This method determines the appropriate positioning strategy (fullscreen or not) and configures the bib accordingly.
2068
- * It also sets up middleware for the floater configuration, computes the position of the bib relative to the trigger element,
2139
+ * This method determines the appropriate positioning strategy (fullscreen or not) and configures the bib accordingly.
2140
+ * It also sets up middleware for the floater configuration, computes the position of the bib relative to the trigger element,
2069
2141
  * and applies the calculated position to the bib's style.
2070
2142
  */
2071
2143
  position() {
@@ -2076,21 +2148,33 @@ class AuroFloatingUI {
2076
2148
  this.mirrorSize();
2077
2149
  // Define the middlware for the floater configuration
2078
2150
  const middleware = [
2079
- offset(this.element.floaterConfig.offset || 0),
2080
- ...(this.element.floaterConfig.flip ? [flip()] : []), // Add flip middleware if flip is enabled
2081
- ...(this.element.floaterConfig.autoPlacement ? [autoPlacement()] : []), // Add autoPlacement middleware if autoPlacement is enabled
2151
+ offset(this.element.floaterConfig?.offset || 0),
2152
+ ...this.element.floaterConfig?.flip ? [flip()] : [], // Add flip middleware if flip is enabled.
2153
+ ...this.element.floaterConfig?.autoPlacement ? [autoPlacement()] : [], // Add autoPlacement middleware if autoPlacement is enabled.
2082
2154
  ];
2083
2155
 
2084
2156
  // Compute the position of the bib
2085
2157
  computePosition(this.element.trigger, this.element.bib, {
2086
- placement: this.element.floaterConfig.placement || 'bottom',
2158
+ placement: this.element.floaterConfig?.placement,
2087
2159
  middleware: middleware || []
2088
- }).then(({x, y}) => { // eslint-disable-line id-length
2160
+ }).then(({ x, y }) => { // eslint-disable-line id-length
2089
2161
  Object.assign(this.element.bib.style, {
2090
2162
  left: `${x}px`,
2091
2163
  top: `${y}px`,
2092
2164
  });
2093
2165
  });
2166
+ } else if (strategy === 'cover') {
2167
+ // Compute the position of the bib
2168
+ computePosition(this.element.parentNode, this.element.bib, {
2169
+ placement: 'bottom-start'
2170
+ }).then(({ x, y }) => { // eslint-disable-line id-length
2171
+ Object.assign(this.element.bib.style, {
2172
+ left: `${x}px`,
2173
+ top: `${y - this.element.parentNode.offsetHeight}px`,
2174
+ width: `${this.element.parentNode.offsetWidth}px`,
2175
+ height: `${this.element.parentNode.offsetHeight}px`
2176
+ });
2177
+ });
2094
2178
  }
2095
2179
  }
2096
2180
 
@@ -2119,34 +2203,48 @@ class AuroFloatingUI {
2119
2203
  *
2120
2204
  * @param {string} strategy - The positioning strategy ('fullscreen' or 'floating').
2121
2205
  */
2122
- configureBibStrategy(strategy) {
2123
- const prevStrategy = this.element.isBibFullscreen ? 'fullscreen' : 'floating';
2124
- if (strategy === 'fullscreen') {
2206
+ configureBibStrategy(value) {
2207
+ if (value === 'fullscreen') {
2125
2208
  this.element.isBibFullscreen = true;
2126
2209
  // reset the prev position
2210
+ this.element.bib.setAttribute('isfullscreen', "");
2211
+ this.element.bib.style.position = 'fixed';
2127
2212
  this.element.bib.style.top = "0px";
2128
2213
  this.element.bib.style.left = "0px";
2214
+ this.element.bib.style.width = '';
2215
+ this.element.bib.style.height = '';
2129
2216
 
2130
2217
  // reset the size that was mirroring `size` css-part
2131
2218
  const bibContent = this.element.bib.shadowRoot.querySelector(".container");
2132
- bibContent.style.width = '';
2133
- bibContent.style.height = '';
2134
- bibContent.style.maxWidth = '';
2135
- bibContent.style.maxHeight = `${window.visualViewport.height}px`;
2219
+ if (bibContent) {
2220
+ bibContent.style.width = '';
2221
+ bibContent.style.height = '';
2222
+ bibContent.style.maxWidth = '';
2223
+ bibContent.style.maxHeight = `${window.visualViewport.height}px`;
2224
+ this.configureTrial = 0;
2225
+ } else if (this.configureTrial < MAX_CONFIGURATION_COUNT) {
2226
+ this.configureTrial += 1;
2227
+
2228
+ setTimeout(() => {
2229
+ this.configureBibStrategy(value);
2230
+ }, 0);
2231
+ }
2136
2232
 
2137
2233
  if (this.element.isPopoverVisible) {
2138
2234
  this.lockScroll(true);
2139
2235
  }
2140
2236
  } else {
2237
+ this.element.bib.style.position = '';
2238
+ this.element.bib.removeAttribute('isfullscreen');
2141
2239
  this.element.isBibFullscreen = false;
2142
-
2143
- this.lockScroll(false);
2144
2240
  }
2145
2241
 
2146
- if (prevStrategy !== strategy) {
2242
+ const isChanged = this.strategy && this.strategy !== value;
2243
+ this.strategy = value;
2244
+ if (isChanged) {
2147
2245
  const event = new CustomEvent(this.eventPrefix ? `${this.eventPrefix}-strategy-change` : 'strategy-change', {
2148
2246
  detail: {
2149
- strategy,
2247
+ value,
2150
2248
  },
2151
2249
  composed: true
2152
2250
  });
@@ -2157,18 +2255,6 @@ class AuroFloatingUI {
2157
2255
 
2158
2256
  updateState() {
2159
2257
  const isVisible = this.element.isPopoverVisible;
2160
-
2161
- // Refactor this to apply attribute to correct focusable element
2162
- // Reference Issue: https://github.com/AlaskaAirlines/auro-library/issues/105
2163
- //
2164
- // this.element.trigger.setAttribute('aria-expanded', isVisible);
2165
-
2166
- if (isVisible) {
2167
- this.element.bib.setAttribute('data-show', true);
2168
- } else {
2169
- this.element.bib.removeAttribute('data-show');
2170
- }
2171
-
2172
2258
  if (!isVisible) {
2173
2259
  this.cleanupHideHandlers();
2174
2260
  try {
@@ -2179,16 +2265,32 @@ class AuroFloatingUI {
2179
2265
  }
2180
2266
  }
2181
2267
 
2268
+ /**
2269
+ * @private
2270
+ * getting called on 'blur' in trigger or `focusin` in document
2271
+ *
2272
+ * Hides the bib if focus moves outside of the trigger or bib, unless a 'noHideOnThisFocusLoss' flag is set.
2273
+ * This method checks if the currently active element is still within the trigger or bib.
2274
+ * If not, and if the bib isn't in fullscreen mode with focus lost, it hides the bib.
2275
+ */
2182
2276
  handleFocusLoss() {
2183
- if (this.element.noHideOnThisFocusLoss ||
2184
- this.element.hasAttribute('noHideOnThisFocusLoss')) {
2277
+ // if mouse is being pressed, skip and let click event to handle the action
2278
+ if (AuroFloatingUI.isMousePressed) {
2185
2279
  return;
2186
2280
  }
2187
2281
 
2188
- const {activeElement} = document;
2189
- if (activeElement === document.querySelector('body') ||
2190
- this.element.contains(activeElement) ||
2191
- this.element.bibContent?.contains(activeElement)) {
2282
+ if (this.element.noHideOnThisFocusLoss ||
2283
+ this.element.hasAttribute('noHideOnThisFocusLoss')) {
2284
+ return;
2285
+ }
2286
+
2287
+ const { activeElement } = document;
2288
+ // if focus is still inside of trigger or bib, do not close
2289
+ if (this.element.contains(activeElement) || this.element.bib?.contains(activeElement)) {
2290
+ return;
2291
+ }
2292
+ // if fullscreen bib is still open and the focus is missing, do not close
2293
+ if (this.element.bib.hasAttribute('isfullscreen') && activeElement === document.body) {
2192
2294
  return;
2193
2295
  }
2194
2296
 
@@ -2196,31 +2298,66 @@ class AuroFloatingUI {
2196
2298
  }
2197
2299
 
2198
2300
  setupHideHandlers() {
2301
+ this.preventFocusLoseOnBibClick = (event) => {
2302
+ event.preventDefault();
2303
+ event.stopPropagation();
2304
+ };
2305
+ this.element.bib.addEventListener('mousedown', this.preventFocusLoseOnBibClick);
2306
+
2199
2307
  // Define handlers & store references
2200
2308
  this.focusHandler = () => this.handleFocusLoss();
2201
2309
 
2202
2310
  this.clickHandler = (evt) => {
2203
- if (!evt.composedPath().includes(this.element.trigger) &&
2204
- !evt.composedPath().includes(this.element.bibContent)) {
2205
- this.hideBib();
2311
+ if ((!evt.composedPath().includes(this.element.trigger) &&
2312
+ !evt.composedPath().includes(this.element.bib)) ||
2313
+ (this.element.bib.backdrop && evt.composedPath().includes(this.element.bib.backdrop))) {
2314
+ const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
2315
+
2316
+ if (existedVisibleFloatingUI && existedVisibleFloatingUI.element.isPopoverVisible) {
2317
+ // if something else is open, close that
2318
+ existedVisibleFloatingUI.hideBib();
2319
+ document.expandedAuroFormkitDropdown = null;
2320
+ document.expandedAuroFloater = this;
2321
+ } else {
2322
+ this.hideBib();
2323
+ }
2206
2324
  }
2207
2325
  };
2208
2326
 
2209
2327
  // ESC key handler
2210
2328
  this.keyDownHandler = (evt) => {
2211
2329
  if (evt.key === 'Escape' && this.element.isPopoverVisible) {
2330
+ const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
2331
+ if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this && existedVisibleFloatingUI.element.isPopoverVisible) {
2332
+ // if something else is open, let it handle itself
2333
+ return;
2334
+ }
2212
2335
  this.hideBib();
2213
2336
  }
2214
2337
  };
2215
2338
 
2216
- // Add event listeners using the stored references
2217
- document.addEventListener('focusin', this.focusHandler);
2218
- window.addEventListener('click', this.clickHandler);
2339
+ if (this.behavior !== 'drawer' && this.behavior !== 'dialog') {
2340
+ // Add event listeners using the stored references
2341
+ document.addEventListener('focusin', this.focusHandler);
2342
+ }
2343
+
2219
2344
  document.addEventListener('keydown', this.keyDownHandler);
2345
+
2346
+ // send this task to the end of queue to prevent conflicting
2347
+ // it conflicts if showBib gets call from a button that's not this.element.trigger
2348
+ setTimeout(() => {
2349
+ window.addEventListener('click', this.clickHandler);
2350
+ }, 0);
2220
2351
  }
2221
2352
 
2222
2353
  cleanupHideHandlers() {
2223
2354
  // Remove event listeners if they exist
2355
+
2356
+ if (this.preventFocusLoseOnBibClick) {
2357
+ this.element.bib.removeEventListener('mousedown', this.preventFocusLoseOnBibClick);
2358
+ delete this.preventFocusLoseOnBibClick;
2359
+ }
2360
+
2224
2361
  if (this.focusHandler) {
2225
2362
  document.removeEventListener('focusin', this.focusHandler);
2226
2363
  this.focusHandler = null;
@@ -2245,40 +2382,54 @@ class AuroFloatingUI {
2245
2382
 
2246
2383
  updateCurrentExpandedDropdown() {
2247
2384
  // Close any other dropdown that is already open
2248
- if (document.expandedAuroFormkitDropdown) {
2249
- document.expandedAuroFormkitDropdown.hide;
2385
+ const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
2386
+ if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this &&
2387
+ existedVisibleFloatingUI.isPopoverVisible &&
2388
+ document.expandedAuroFloater.eventPrefix === this.eventPrefix) {
2389
+ document.expandedAuroFloater.hideBib();
2250
2390
  }
2251
2391
 
2252
- document.expandedAuroFormkitDropdown = this;
2392
+ document.expandedAuroFloater = this;
2253
2393
  }
2254
2394
 
2255
2395
  showBib() {
2256
- if (!this.element.disabled && !this.element.isPopoverVisible) {
2396
+ if (!this.element.disabled && !this.showing) {
2257
2397
  this.updateCurrentExpandedDropdown();
2258
- this.element.isPopoverVisible = true;
2259
2398
  this.element.triggerChevron?.setAttribute('data-expanded', true);
2260
-
2261
- this.dispatchEventDropdownToggle();
2262
- this.position();
2263
-
2264
- // Clean up any existing handlers before setting up new ones
2265
- this.cleanupHideHandlers();
2266
- this.setupHideHandlers();
2399
+
2400
+ // prevent double showing: isPopovervisible gets first and showBib gets called later
2401
+ if (!this.showing) {
2402
+ if (!this.element.modal) {
2403
+ this.setupHideHandlers();
2404
+ }
2405
+ this.showing = true;
2406
+ this.element.isPopoverVisible = true;
2407
+ this.position();
2408
+ this.dispatchEventDropdownToggle();
2409
+ }
2267
2410
 
2268
2411
  // Setup auto update to handle resize and scroll
2269
- this.element.cleanup = autoUpdate(this.element.trigger, this.element.bib, () => {
2412
+ this.element.cleanup = autoUpdate(this.element.trigger || this.element.parentNode, this.element.bib, () => {
2270
2413
  this.position();
2271
2414
  });
2272
2415
  }
2273
2416
  }
2274
2417
 
2275
2418
  hideBib() {
2276
- if (this.element.isPopoverVisible && !this.element.disabled && !this.element.noToggle) {
2277
- this.element.isPopoverVisible = false;
2419
+ if (!this.element.disabled && !this.element.noToggle) {
2278
2420
  this.lockScroll(false);
2279
2421
  this.element.triggerChevron?.removeAttribute('data-expanded');
2280
- this.dispatchEventDropdownToggle();
2422
+
2423
+ if (this.element.isPopoverVisible) {
2424
+ this.element.isPopoverVisible = false;
2425
+ }
2426
+ if (this.showing) {
2427
+ this.cleanupHideHandlers();
2428
+ this.showing = false;
2429
+ this.dispatchEventDropdownToggle();
2430
+ }
2281
2431
  }
2432
+ document.expandedAuroFloater = null;
2282
2433
  }
2283
2434
 
2284
2435
  /**
@@ -2288,7 +2439,7 @@ class AuroFloatingUI {
2288
2439
  dispatchEventDropdownToggle() {
2289
2440
  const event = new CustomEvent(this.eventPrefix ? `${this.eventPrefix}-toggled` : 'toggled', {
2290
2441
  detail: {
2291
- expanded: this.element.isPopoverVisible,
2442
+ expanded: this.showing,
2292
2443
  },
2293
2444
  composed: true
2294
2445
  });
@@ -2336,15 +2487,18 @@ class AuroFloatingUI {
2336
2487
  break;
2337
2488
  case 'focus':
2338
2489
  if (this.element.focusShow) {
2490
+
2339
2491
  /*
2340
- This needs to better handle clicking that gives focus -
2341
- currently it shows and then immediately hides the bib
2492
+ This needs to better handle clicking that gives focus -
2493
+ currently it shows and then immediately hides the bib
2342
2494
  */
2343
2495
  this.showBib();
2344
2496
  }
2345
2497
  break;
2346
2498
  case 'blur':
2347
- this.handleFocusLoss();
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);
2348
2502
  break;
2349
2503
  case 'click':
2350
2504
  if (document.activeElement === document.body) {
@@ -2352,7 +2506,7 @@ class AuroFloatingUI {
2352
2506
  }
2353
2507
  this.handleClick();
2354
2508
  break;
2355
- // Do nothing
2509
+ // Do nothing
2356
2510
  }
2357
2511
  }
2358
2512
  }
@@ -2396,39 +2550,79 @@ class AuroFloatingUI {
2396
2550
  });
2397
2551
  }
2398
2552
 
2553
+ /**
2554
+ *
2555
+ * @param {*} eventPrefix
2556
+ */
2557
+ regenerateBibId() {
2558
+ this.id = this.element.getAttribute('id');
2559
+ if (!this.id) {
2560
+ this.id = window.crypto.randomUUID();
2561
+ this.element.setAttribute('id', this.id);
2562
+ }
2563
+
2564
+ this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
2565
+ }
2566
+
2399
2567
  configure(elem, eventPrefix) {
2568
+ AuroFloatingUI.setupMousePressChecker();
2569
+
2400
2570
  this.eventPrefix = eventPrefix;
2401
- this.element = elem;
2402
- this.element.trigger = this.element.shadowRoot.querySelector('#trigger');
2403
- this.element.bib = this.element.shadowRoot.querySelector('#bib');
2571
+ if (this.element !== elem) {
2572
+ this.element = elem;
2573
+ }
2574
+
2575
+ if (this.behavior !== this.element.behavior) {
2576
+ this.behavior = this.element.behavior;
2577
+ }
2578
+
2579
+ if (this.element.trigger) {
2580
+ this.disconnect();
2581
+ }
2582
+ this.element.trigger = this.element.triggerElement || this.element.shadowRoot.querySelector('#trigger') || this.element.trigger;
2583
+ this.element.bib = this.element.shadowRoot.querySelector('#bib') || this.element.bib;
2404
2584
  this.element.bibSizer = this.element.shadowRoot.querySelector('#bibSizer');
2405
2585
  this.element.triggerChevron = this.element.shadowRoot.querySelector('#showStateIcon');
2406
2586
 
2587
+
2588
+ if (this.element.floaterConfig) {
2589
+ this.element.hoverToggle = this.element.floaterConfig.hoverToggle;
2590
+ }
2591
+
2407
2592
  document.body.append(this.element.bib);
2408
2593
 
2594
+ this.regenerateBibId();
2409
2595
  this.handleTriggerTabIndex();
2410
2596
 
2411
2597
  this.handleEvent = this.handleEvent.bind(this);
2412
- this.element.trigger.addEventListener('keydown', this.handleEvent);
2413
- this.element.trigger.addEventListener('click', this.handleEvent);
2414
- this.element.trigger.addEventListener('mouseenter', this.handleEvent);
2415
- this.element.trigger.addEventListener('mouseleave', this.handleEvent);
2416
- this.element.trigger.addEventListener('focus', this.handleEvent);
2417
- this.element.trigger.addEventListener('blur', this.handleEvent);
2598
+ if (this.element.trigger) {
2599
+ this.element.trigger.addEventListener('keydown', this.handleEvent);
2600
+ this.element.trigger.addEventListener('click', this.handleEvent);
2601
+ this.element.trigger.addEventListener('mouseenter', this.handleEvent);
2602
+ this.element.trigger.addEventListener('mouseleave', this.handleEvent);
2603
+ this.element.trigger.addEventListener('focus', this.handleEvent);
2604
+ this.element.trigger.addEventListener('blur', this.handleEvent);
2605
+ }
2418
2606
  }
2419
2607
 
2420
2608
  disconnect() {
2421
2609
  this.cleanupHideHandlers();
2422
- this.element.cleanup?.();
2423
-
2424
- // Remove event & keyboard listeners
2425
- if (this.element?.trigger) {
2426
- this.element.trigger.removeEventListener('keydown', this.handleEvent);
2427
- this.element.trigger.removeEventListener('click', this.handleEvent);
2428
- this.element.trigger.removeEventListener('mouseenter', this.handleEvent);
2429
- this.element.trigger.removeEventListener('mouseleave', this.handleEvent);
2430
- this.element.trigger.removeEventListener('focus', this.handleEvent);
2431
- this.element.trigger.removeEventListener('blur', this.handleEvent);
2610
+ if (this.element) {
2611
+ this.element.cleanup?.();
2612
+
2613
+ if (this.element.bib) {
2614
+ this.element.shadowRoot.append(this.element.bib);
2615
+ }
2616
+
2617
+ // Remove event & keyboard listeners
2618
+ if (this.element?.trigger) {
2619
+ this.element.trigger.removeEventListener('keydown', this.handleEvent);
2620
+ this.element.trigger.removeEventListener('click', this.handleEvent);
2621
+ this.element.trigger.removeEventListener('mouseenter', this.handleEvent);
2622
+ this.element.trigger.removeEventListener('mouseleave', this.handleEvent);
2623
+ this.element.trigger.removeEventListener('focus', this.handleEvent);
2624
+ this.element.trigger.removeEventListener('blur', this.handleEvent);
2625
+ }
2432
2626
  }
2433
2627
  }
2434
2628
  }
@@ -3391,6 +3585,11 @@ class AuroDropdown extends LitElement {
3391
3585
  * @private
3392
3586
  */
3393
3587
  this.helpTextTag = versioning.generateTag('auro-formkit-dropdown-helptext', helpTextVersion$1, AuroHelpText$1);
3588
+
3589
+ /**
3590
+ * @private
3591
+ */
3592
+ this.bindFocusEventToTrigger = this.bindFocusEventToTrigger.bind(this);
3394
3593
  }
3395
3594
 
3396
3595
  /**
@@ -3659,6 +3858,7 @@ class AuroDropdown extends LitElement {
3659
3858
  disconnectedCallback() {
3660
3859
  super.disconnectedCallback();
3661
3860
  this.floater.disconnect();
3861
+ this.clearTriggerFocusEventBinding();
3662
3862
  }
3663
3863
 
3664
3864
  updated(changedProperties) {
@@ -3773,6 +3973,62 @@ class AuroDropdown extends LitElement {
3773
3973
  return result;
3774
3974
  }
3775
3975
 
3976
+ /**
3977
+ * @private
3978
+ * Creates and dispatches a duplicate focus event on the trigger element.
3979
+ * @param {Event} event - The original focus event.
3980
+ */
3981
+ bindFocusEventToTrigger(event) {
3982
+ const dupEvent = new FocusEvent(event.type, {
3983
+ bubbles: false,
3984
+ cancelable: false,
3985
+ composed: true,
3986
+ });
3987
+ this.trigger.dispatchEvent(dupEvent);
3988
+ }
3989
+
3990
+ /**
3991
+ * @private
3992
+ * Sets up event listeners to deliver focus and blur events from nested Auro components within the trigger slot to trigger.
3993
+ * This ensures that focus/blur events originating from within these components are propagated to the trigger element itself.
3994
+ */
3995
+ setupTriggerFocusEventBinding() {
3996
+ if (!this.triggerContentSlot || this.triggerContentSlot.length === 0) {
3997
+ return;
3998
+ }
3999
+
4000
+ this.triggerContentSlot.forEach((node) => {
4001
+ if (node.querySelectorAll) {
4002
+ const auroElements = node.querySelectorAll('auro-input, [auro-input], auro-button, [auro-button], button, input');
4003
+ auroElements.forEach((auroEl) => {
4004
+ auroEl.addEventListener('focus', this.bindFocusEventToTrigger);
4005
+ auroEl.addEventListener('blur', this.bindFocusEventToTrigger);
4006
+ });
4007
+ }
4008
+ });
4009
+ }
4010
+
4011
+ /**
4012
+ * Clears focus and blur event listeners from nested Auro components within the trigger slot.
4013
+ * @private
4014
+ * @returns {void}
4015
+ */
4016
+ clearTriggerFocusEventBinding() {
4017
+ if (!this.triggerContentSlot || this.triggerContentSlot.length === 0) {
4018
+ return;
4019
+ }
4020
+
4021
+ this.triggerContentSlot.forEach((node) => {
4022
+ if (node.querySelectorAll) {
4023
+ const auroElements = node.querySelectorAll('auro-input, [auro-input], auro-button, [auro-button], button, input');
4024
+ auroElements.forEach((auroEl) => {
4025
+ auroEl.removeEventListener('focus', this.bindFocusEventToTrigger);
4026
+ auroEl.removeEventListener('blur', this.bindFocusEventToTrigger);
4027
+ });
4028
+ }
4029
+ });
4030
+ }
4031
+
3776
4032
  /**
3777
4033
  * Handles changes to the trigger content slot and updates related properties.
3778
4034
  *
@@ -3820,6 +4076,7 @@ class AuroDropdown extends LitElement {
3820
4076
  }
3821
4077
 
3822
4078
  if (this.triggerContentSlot) {
4079
+ this.setupTriggerFocusEventBinding();
3823
4080
  this.hasTriggerContent = this.triggerContentSlot.some((slot) => {
3824
4081
  if (slot.textContent.trim()) {
3825
4082
  return true;
@@ -3925,6 +4182,7 @@ class AuroDropdown extends LitElement {
3925
4182
  <${this.dropdownBibTag}
3926
4183
  id="bib"
3927
4184
  role="tooltip"
4185
+ ?data-show="${this.isPopoverVisible}"
3928
4186
  ?isfullscreen="${this.isBibFullscreen}"
3929
4187
  ?common="${this.common}"
3930
4188
  ?rounded="${this.common || this.rounded}"
@@ -110,7 +110,7 @@ The use of any Auro custom element has a dependency on the [Auro Design Tokens](
110
110
  In cases where the project is not able to process JS assets, there are pre-processed assets available for use. Legacy browsers such as IE11 are no longer supported.
111
111
 
112
112
  ```html
113
- <script type="module" src="https://cdn.jsdelivr.net/npm/@aurodesignsystem/auro-formkit@2.2.1-beta.1/auro-counter/+esm"></script>
113
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@aurodesignsystem/auro-formkit@2.2.1-beta.2/auro-counter/+esm"></script>
114
114
  ```
115
115
  <!-- AURO-GENERATED-CONTENT:END -->
116
116