@aurodesignsystem/auro-formkit 2.2.1-beta.2 → 2.2.1

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 +35 -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
@@ -2216,17 +2216,70 @@ const computePosition = (reference, floating, options) => {
2216
2216
  /* eslint-disable line-comment-position, no-inline-comments */
2217
2217
 
2218
2218
 
2219
+
2220
+ const MAX_CONFIGURATION_COUNT = 10;
2221
+
2219
2222
  class AuroFloatingUI {
2220
- constructor() {
2223
+
2224
+ /**
2225
+ * @private
2226
+ */
2227
+ static isMousePressed = false;
2228
+
2229
+ /**
2230
+ * @private
2231
+ */
2232
+ static isMousePressHandlerInitialized = false;
2233
+
2234
+ /**
2235
+ * @private
2236
+ */
2237
+ static setupMousePressChecker() {
2238
+ if (!AuroFloatingUI.isMousePressHandlerInitialized && window && window.addEventListener) {
2239
+ AuroFloatingUI.isMousePressHandlerInitialized = true;
2240
+
2241
+ const mouseEventGlobalHandler = (event) => {
2242
+ AuroFloatingUI.isMousePressed = event.type === 'mousedown';
2243
+ };
2244
+
2245
+ window.addEventListener('mousedown', mouseEventGlobalHandler);
2246
+ window.addEventListener('mouseup', mouseEventGlobalHandler);
2247
+ }
2248
+ }
2249
+
2250
+ constructor(element, behavior) {
2251
+ this.element = element;
2252
+ this.behavior = behavior;
2253
+
2221
2254
  // Store event listener references for cleanup
2222
2255
  this.focusHandler = null;
2223
2256
  this.clickHandler = null;
2224
2257
  this.keyDownHandler = null;
2225
-
2258
+
2259
+ /**
2260
+ * @private
2261
+ */
2262
+ this.configureTrial = 0;
2263
+
2226
2264
  /**
2227
2265
  * @private
2228
2266
  */
2229
2267
  this.eventPrefix = undefined;
2268
+
2269
+ /**
2270
+ * @private
2271
+ */
2272
+ this.id = undefined;
2273
+
2274
+ /**
2275
+ * @private
2276
+ */
2277
+ this.showing = false;
2278
+
2279
+ /**
2280
+ * @private
2281
+ */
2282
+ this.strategy = undefined;
2230
2283
  }
2231
2284
 
2232
2285
  /**
@@ -2254,29 +2307,48 @@ class AuroFloatingUI {
2254
2307
  * @private
2255
2308
  * Determines the positioning strategy based on the current viewport size and mobile breakpoint.
2256
2309
  *
2257
- * This method checks if the current viewport width is less than or equal to the specified mobile fullscreen breakpoint
2310
+ * This method checks if the current viewport width is less than or equal to the specified mobile fullscreen breakpoint
2258
2311
  * defined in the bib element. If it is, the strategy is set to 'fullscreen'; otherwise, it defaults to 'floating'.
2259
2312
  *
2260
- * @returns {String} The positioning strategy, either 'fullscreen' or 'floating'.
2313
+ * @returns {String} The positioning strategy, one of 'fullscreen', 'floating', 'cover'.
2261
2314
  */
2262
2315
  getPositioningStrategy() {
2263
- let strategy = 'floating';
2264
- if (this.element.bib.mobileFullscreenBreakpoint) {
2265
- const smallerThanBreakpoint = window.matchMedia(`(max-width: ${this.element.bib.mobileFullscreenBreakpoint})`).matches;
2266
- if (smallerThanBreakpoint) {
2267
- strategy = 'fullscreen';
2268
- }
2316
+ const breakpoint = this.element.bib.mobileFullscreenBreakpoint || this.element.floaterConfig?.fullscreenBreakpoint;
2317
+ switch (this.behavior) {
2318
+ case "tooltip":
2319
+ return "floating";
2320
+ case "dialog":
2321
+ case "drawer":
2322
+ if (breakpoint) {
2323
+ const smallerThanBreakpoint = window.matchMedia(`(max-width: ${breakpoint})`).matches;
2324
+
2325
+ this.element.expanded = smallerThanBreakpoint;
2326
+ }
2327
+ if (this.element.nested) {
2328
+ return "cover";
2329
+ }
2330
+ return 'fullscreen';
2331
+ case "dropdown":
2332
+ case undefined:
2333
+ case null:
2334
+ if (breakpoint) {
2335
+ const smallerThanBreakpoint = window.matchMedia(`(max-width: ${breakpoint})`).matches;
2336
+ if (smallerThanBreakpoint) {
2337
+ return 'fullscreen';
2338
+ }
2339
+ }
2340
+ return "floating";
2341
+ default:
2342
+ return this.behavior;
2269
2343
  }
2270
-
2271
- return strategy;
2272
2344
  }
2273
2345
 
2274
2346
  /**
2275
2347
  * @private
2276
2348
  * Positions the bib element based on the current configuration and positioning strategy.
2277
2349
  *
2278
- * This method determines the appropriate positioning strategy (fullscreen or not) and configures the bib accordingly.
2279
- * It also sets up middleware for the floater configuration, computes the position of the bib relative to the trigger element,
2350
+ * This method determines the appropriate positioning strategy (fullscreen or not) and configures the bib accordingly.
2351
+ * It also sets up middleware for the floater configuration, computes the position of the bib relative to the trigger element,
2280
2352
  * and applies the calculated position to the bib's style.
2281
2353
  */
2282
2354
  position() {
@@ -2287,21 +2359,33 @@ class AuroFloatingUI {
2287
2359
  this.mirrorSize();
2288
2360
  // Define the middlware for the floater configuration
2289
2361
  const middleware = [
2290
- offset(this.element.floaterConfig.offset || 0),
2291
- ...(this.element.floaterConfig.flip ? [flip()] : []), // Add flip middleware if flip is enabled
2292
- ...(this.element.floaterConfig.autoPlacement ? [autoPlacement()] : []), // Add autoPlacement middleware if autoPlacement is enabled
2362
+ offset(this.element.floaterConfig?.offset || 0),
2363
+ ...this.element.floaterConfig?.flip ? [flip()] : [], // Add flip middleware if flip is enabled.
2364
+ ...this.element.floaterConfig?.autoPlacement ? [autoPlacement()] : [], // Add autoPlacement middleware if autoPlacement is enabled.
2293
2365
  ];
2294
2366
 
2295
2367
  // Compute the position of the bib
2296
2368
  computePosition(this.element.trigger, this.element.bib, {
2297
- placement: this.element.floaterConfig.placement || 'bottom',
2369
+ placement: this.element.floaterConfig?.placement,
2298
2370
  middleware: middleware || []
2299
- }).then(({x, y}) => { // eslint-disable-line id-length
2371
+ }).then(({ x, y }) => { // eslint-disable-line id-length
2300
2372
  Object.assign(this.element.bib.style, {
2301
2373
  left: `${x}px`,
2302
2374
  top: `${y}px`,
2303
2375
  });
2304
2376
  });
2377
+ } else if (strategy === 'cover') {
2378
+ // Compute the position of the bib
2379
+ computePosition(this.element.parentNode, this.element.bib, {
2380
+ placement: 'bottom-start'
2381
+ }).then(({ x, y }) => { // eslint-disable-line id-length
2382
+ Object.assign(this.element.bib.style, {
2383
+ left: `${x}px`,
2384
+ top: `${y - this.element.parentNode.offsetHeight}px`,
2385
+ width: `${this.element.parentNode.offsetWidth}px`,
2386
+ height: `${this.element.parentNode.offsetHeight}px`
2387
+ });
2388
+ });
2305
2389
  }
2306
2390
  }
2307
2391
 
@@ -2330,34 +2414,48 @@ class AuroFloatingUI {
2330
2414
  *
2331
2415
  * @param {string} strategy - The positioning strategy ('fullscreen' or 'floating').
2332
2416
  */
2333
- configureBibStrategy(strategy) {
2334
- const prevStrategy = this.element.isBibFullscreen ? 'fullscreen' : 'floating';
2335
- if (strategy === 'fullscreen') {
2417
+ configureBibStrategy(value) {
2418
+ if (value === 'fullscreen') {
2336
2419
  this.element.isBibFullscreen = true;
2337
2420
  // reset the prev position
2421
+ this.element.bib.setAttribute('isfullscreen', "");
2422
+ this.element.bib.style.position = 'fixed';
2338
2423
  this.element.bib.style.top = "0px";
2339
2424
  this.element.bib.style.left = "0px";
2425
+ this.element.bib.style.width = '';
2426
+ this.element.bib.style.height = '';
2340
2427
 
2341
2428
  // reset the size that was mirroring `size` css-part
2342
2429
  const bibContent = this.element.bib.shadowRoot.querySelector(".container");
2343
- bibContent.style.width = '';
2344
- bibContent.style.height = '';
2345
- bibContent.style.maxWidth = '';
2346
- bibContent.style.maxHeight = `${window.visualViewport.height}px`;
2430
+ if (bibContent) {
2431
+ bibContent.style.width = '';
2432
+ bibContent.style.height = '';
2433
+ bibContent.style.maxWidth = '';
2434
+ bibContent.style.maxHeight = `${window.visualViewport.height}px`;
2435
+ this.configureTrial = 0;
2436
+ } else if (this.configureTrial < MAX_CONFIGURATION_COUNT) {
2437
+ this.configureTrial += 1;
2438
+
2439
+ setTimeout(() => {
2440
+ this.configureBibStrategy(value);
2441
+ }, 0);
2442
+ }
2347
2443
 
2348
2444
  if (this.element.isPopoverVisible) {
2349
2445
  this.lockScroll(true);
2350
2446
  }
2351
2447
  } else {
2448
+ this.element.bib.style.position = '';
2449
+ this.element.bib.removeAttribute('isfullscreen');
2352
2450
  this.element.isBibFullscreen = false;
2353
-
2354
- this.lockScroll(false);
2355
2451
  }
2356
2452
 
2357
- if (prevStrategy !== strategy) {
2453
+ const isChanged = this.strategy && this.strategy !== value;
2454
+ this.strategy = value;
2455
+ if (isChanged) {
2358
2456
  const event = new CustomEvent(this.eventPrefix ? `${this.eventPrefix}-strategy-change` : 'strategy-change', {
2359
2457
  detail: {
2360
- strategy,
2458
+ value,
2361
2459
  },
2362
2460
  composed: true
2363
2461
  });
@@ -2368,18 +2466,6 @@ class AuroFloatingUI {
2368
2466
 
2369
2467
  updateState() {
2370
2468
  const isVisible = this.element.isPopoverVisible;
2371
-
2372
- // Refactor this to apply attribute to correct focusable element
2373
- // Reference Issue: https://github.com/AlaskaAirlines/auro-library/issues/105
2374
- //
2375
- // this.element.trigger.setAttribute('aria-expanded', isVisible);
2376
-
2377
- if (isVisible) {
2378
- this.element.bib.setAttribute('data-show', true);
2379
- } else {
2380
- this.element.bib.removeAttribute('data-show');
2381
- }
2382
-
2383
2469
  if (!isVisible) {
2384
2470
  this.cleanupHideHandlers();
2385
2471
  try {
@@ -2390,16 +2476,32 @@ class AuroFloatingUI {
2390
2476
  }
2391
2477
  }
2392
2478
 
2479
+ /**
2480
+ * @private
2481
+ * getting called on 'blur' in trigger or `focusin` in document
2482
+ *
2483
+ * Hides the bib if focus moves outside of the trigger or bib, unless a 'noHideOnThisFocusLoss' flag is set.
2484
+ * This method checks if the currently active element is still within the trigger or bib.
2485
+ * If not, and if the bib isn't in fullscreen mode with focus lost, it hides the bib.
2486
+ */
2393
2487
  handleFocusLoss() {
2394
- if (this.element.noHideOnThisFocusLoss ||
2395
- this.element.hasAttribute('noHideOnThisFocusLoss')) {
2488
+ // if mouse is being pressed, skip and let click event to handle the action
2489
+ if (AuroFloatingUI.isMousePressed) {
2396
2490
  return;
2397
2491
  }
2398
2492
 
2399
- const {activeElement} = document;
2400
- if (activeElement === document.querySelector('body') ||
2401
- this.element.contains(activeElement) ||
2402
- this.element.bibContent?.contains(activeElement)) {
2493
+ if (this.element.noHideOnThisFocusLoss ||
2494
+ this.element.hasAttribute('noHideOnThisFocusLoss')) {
2495
+ return;
2496
+ }
2497
+
2498
+ const { activeElement } = document;
2499
+ // if focus is still inside of trigger or bib, do not close
2500
+ if (this.element.contains(activeElement) || this.element.bib?.contains(activeElement)) {
2501
+ return;
2502
+ }
2503
+ // if fullscreen bib is still open and the focus is missing, do not close
2504
+ if (this.element.bib.hasAttribute('isfullscreen') && activeElement === document.body) {
2403
2505
  return;
2404
2506
  }
2405
2507
 
@@ -2407,31 +2509,66 @@ class AuroFloatingUI {
2407
2509
  }
2408
2510
 
2409
2511
  setupHideHandlers() {
2512
+ this.preventFocusLoseOnBibClick = (event) => {
2513
+ event.preventDefault();
2514
+ event.stopPropagation();
2515
+ };
2516
+ this.element.bib.addEventListener('mousedown', this.preventFocusLoseOnBibClick);
2517
+
2410
2518
  // Define handlers & store references
2411
2519
  this.focusHandler = () => this.handleFocusLoss();
2412
2520
 
2413
2521
  this.clickHandler = (evt) => {
2414
- if (!evt.composedPath().includes(this.element.trigger) &&
2415
- !evt.composedPath().includes(this.element.bibContent)) {
2416
- this.hideBib();
2522
+ if ((!evt.composedPath().includes(this.element.trigger) &&
2523
+ !evt.composedPath().includes(this.element.bib)) ||
2524
+ (this.element.bib.backdrop && evt.composedPath().includes(this.element.bib.backdrop))) {
2525
+ const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
2526
+
2527
+ if (existedVisibleFloatingUI && existedVisibleFloatingUI.element.isPopoverVisible) {
2528
+ // if something else is open, close that
2529
+ existedVisibleFloatingUI.hideBib();
2530
+ document.expandedAuroFormkitDropdown = null;
2531
+ document.expandedAuroFloater = this;
2532
+ } else {
2533
+ this.hideBib();
2534
+ }
2417
2535
  }
2418
2536
  };
2419
2537
 
2420
2538
  // ESC key handler
2421
2539
  this.keyDownHandler = (evt) => {
2422
2540
  if (evt.key === 'Escape' && this.element.isPopoverVisible) {
2541
+ const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
2542
+ if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this && existedVisibleFloatingUI.element.isPopoverVisible) {
2543
+ // if something else is open, let it handle itself
2544
+ return;
2545
+ }
2423
2546
  this.hideBib();
2424
2547
  }
2425
2548
  };
2426
2549
 
2427
- // Add event listeners using the stored references
2428
- document.addEventListener('focusin', this.focusHandler);
2429
- window.addEventListener('click', this.clickHandler);
2550
+ if (this.behavior !== 'drawer' && this.behavior !== 'dialog') {
2551
+ // Add event listeners using the stored references
2552
+ document.addEventListener('focusin', this.focusHandler);
2553
+ }
2554
+
2430
2555
  document.addEventListener('keydown', this.keyDownHandler);
2556
+
2557
+ // send this task to the end of queue to prevent conflicting
2558
+ // it conflicts if showBib gets call from a button that's not this.element.trigger
2559
+ setTimeout(() => {
2560
+ window.addEventListener('click', this.clickHandler);
2561
+ }, 0);
2431
2562
  }
2432
2563
 
2433
2564
  cleanupHideHandlers() {
2434
2565
  // Remove event listeners if they exist
2566
+
2567
+ if (this.preventFocusLoseOnBibClick) {
2568
+ this.element.bib.removeEventListener('mousedown', this.preventFocusLoseOnBibClick);
2569
+ delete this.preventFocusLoseOnBibClick;
2570
+ }
2571
+
2435
2572
  if (this.focusHandler) {
2436
2573
  document.removeEventListener('focusin', this.focusHandler);
2437
2574
  this.focusHandler = null;
@@ -2456,40 +2593,54 @@ class AuroFloatingUI {
2456
2593
 
2457
2594
  updateCurrentExpandedDropdown() {
2458
2595
  // Close any other dropdown that is already open
2459
- if (document.expandedAuroFormkitDropdown) {
2460
- document.expandedAuroFormkitDropdown.hide;
2596
+ const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
2597
+ if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this &&
2598
+ existedVisibleFloatingUI.isPopoverVisible &&
2599
+ document.expandedAuroFloater.eventPrefix === this.eventPrefix) {
2600
+ document.expandedAuroFloater.hideBib();
2461
2601
  }
2462
2602
 
2463
- document.expandedAuroFormkitDropdown = this;
2603
+ document.expandedAuroFloater = this;
2464
2604
  }
2465
2605
 
2466
2606
  showBib() {
2467
- if (!this.element.disabled && !this.element.isPopoverVisible) {
2607
+ if (!this.element.disabled && !this.showing) {
2468
2608
  this.updateCurrentExpandedDropdown();
2469
- this.element.isPopoverVisible = true;
2470
2609
  this.element.triggerChevron?.setAttribute('data-expanded', true);
2471
-
2472
- this.dispatchEventDropdownToggle();
2473
- this.position();
2474
-
2475
- // Clean up any existing handlers before setting up new ones
2476
- this.cleanupHideHandlers();
2477
- this.setupHideHandlers();
2610
+
2611
+ // prevent double showing: isPopovervisible gets first and showBib gets called later
2612
+ if (!this.showing) {
2613
+ if (!this.element.modal) {
2614
+ this.setupHideHandlers();
2615
+ }
2616
+ this.showing = true;
2617
+ this.element.isPopoverVisible = true;
2618
+ this.position();
2619
+ this.dispatchEventDropdownToggle();
2620
+ }
2478
2621
 
2479
2622
  // Setup auto update to handle resize and scroll
2480
- this.element.cleanup = autoUpdate(this.element.trigger, this.element.bib, () => {
2623
+ this.element.cleanup = autoUpdate(this.element.trigger || this.element.parentNode, this.element.bib, () => {
2481
2624
  this.position();
2482
2625
  });
2483
2626
  }
2484
2627
  }
2485
2628
 
2486
2629
  hideBib() {
2487
- if (this.element.isPopoverVisible && !this.element.disabled && !this.element.noToggle) {
2488
- this.element.isPopoverVisible = false;
2630
+ if (!this.element.disabled && !this.element.noToggle) {
2489
2631
  this.lockScroll(false);
2490
2632
  this.element.triggerChevron?.removeAttribute('data-expanded');
2491
- this.dispatchEventDropdownToggle();
2633
+
2634
+ if (this.element.isPopoverVisible) {
2635
+ this.element.isPopoverVisible = false;
2636
+ }
2637
+ if (this.showing) {
2638
+ this.cleanupHideHandlers();
2639
+ this.showing = false;
2640
+ this.dispatchEventDropdownToggle();
2641
+ }
2492
2642
  }
2643
+ document.expandedAuroFloater = null;
2493
2644
  }
2494
2645
 
2495
2646
  /**
@@ -2499,7 +2650,7 @@ class AuroFloatingUI {
2499
2650
  dispatchEventDropdownToggle() {
2500
2651
  const event = new CustomEvent(this.eventPrefix ? `${this.eventPrefix}-toggled` : 'toggled', {
2501
2652
  detail: {
2502
- expanded: this.element.isPopoverVisible,
2653
+ expanded: this.showing,
2503
2654
  },
2504
2655
  composed: true
2505
2656
  });
@@ -2547,15 +2698,18 @@ class AuroFloatingUI {
2547
2698
  break;
2548
2699
  case 'focus':
2549
2700
  if (this.element.focusShow) {
2701
+
2550
2702
  /*
2551
- This needs to better handle clicking that gives focus -
2552
- currently it shows and then immediately hides the bib
2703
+ This needs to better handle clicking that gives focus -
2704
+ currently it shows and then immediately hides the bib
2553
2705
  */
2554
2706
  this.showBib();
2555
2707
  }
2556
2708
  break;
2557
2709
  case 'blur':
2558
- this.handleFocusLoss();
2710
+ // send this task 100ms later queue to
2711
+ // wait a frame in case focus moves within the floating element/bib
2712
+ setTimeout(() => this.handleFocusLoss(), 0);
2559
2713
  break;
2560
2714
  case 'click':
2561
2715
  if (document.activeElement === document.body) {
@@ -2563,7 +2717,7 @@ class AuroFloatingUI {
2563
2717
  }
2564
2718
  this.handleClick();
2565
2719
  break;
2566
- // Do nothing
2720
+ // Do nothing
2567
2721
  }
2568
2722
  }
2569
2723
  }
@@ -2607,39 +2761,79 @@ class AuroFloatingUI {
2607
2761
  });
2608
2762
  }
2609
2763
 
2764
+ /**
2765
+ *
2766
+ * @param {*} eventPrefix
2767
+ */
2768
+ regenerateBibId() {
2769
+ this.id = this.element.getAttribute('id');
2770
+ if (!this.id) {
2771
+ this.id = window.crypto.randomUUID();
2772
+ this.element.setAttribute('id', this.id);
2773
+ }
2774
+
2775
+ this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
2776
+ }
2777
+
2610
2778
  configure(elem, eventPrefix) {
2779
+ AuroFloatingUI.setupMousePressChecker();
2780
+
2611
2781
  this.eventPrefix = eventPrefix;
2612
- this.element = elem;
2613
- this.element.trigger = this.element.shadowRoot.querySelector('#trigger');
2614
- this.element.bib = this.element.shadowRoot.querySelector('#bib');
2782
+ if (this.element !== elem) {
2783
+ this.element = elem;
2784
+ }
2785
+
2786
+ if (this.behavior !== this.element.behavior) {
2787
+ this.behavior = this.element.behavior;
2788
+ }
2789
+
2790
+ if (this.element.trigger) {
2791
+ this.disconnect();
2792
+ }
2793
+ this.element.trigger = this.element.triggerElement || this.element.shadowRoot.querySelector('#trigger') || this.element.trigger;
2794
+ this.element.bib = this.element.shadowRoot.querySelector('#bib') || this.element.bib;
2615
2795
  this.element.bibSizer = this.element.shadowRoot.querySelector('#bibSizer');
2616
2796
  this.element.triggerChevron = this.element.shadowRoot.querySelector('#showStateIcon');
2617
2797
 
2798
+
2799
+ if (this.element.floaterConfig) {
2800
+ this.element.hoverToggle = this.element.floaterConfig.hoverToggle;
2801
+ }
2802
+
2618
2803
  document.body.append(this.element.bib);
2619
2804
 
2805
+ this.regenerateBibId();
2620
2806
  this.handleTriggerTabIndex();
2621
2807
 
2622
2808
  this.handleEvent = this.handleEvent.bind(this);
2623
- this.element.trigger.addEventListener('keydown', this.handleEvent);
2624
- this.element.trigger.addEventListener('click', this.handleEvent);
2625
- this.element.trigger.addEventListener('mouseenter', this.handleEvent);
2626
- this.element.trigger.addEventListener('mouseleave', this.handleEvent);
2627
- this.element.trigger.addEventListener('focus', this.handleEvent);
2628
- this.element.trigger.addEventListener('blur', this.handleEvent);
2809
+ if (this.element.trigger) {
2810
+ this.element.trigger.addEventListener('keydown', this.handleEvent);
2811
+ this.element.trigger.addEventListener('click', this.handleEvent);
2812
+ this.element.trigger.addEventListener('mouseenter', this.handleEvent);
2813
+ this.element.trigger.addEventListener('mouseleave', this.handleEvent);
2814
+ this.element.trigger.addEventListener('focus', this.handleEvent);
2815
+ this.element.trigger.addEventListener('blur', this.handleEvent);
2816
+ }
2629
2817
  }
2630
2818
 
2631
2819
  disconnect() {
2632
2820
  this.cleanupHideHandlers();
2633
- this.element.cleanup?.();
2634
-
2635
- // Remove event & keyboard listeners
2636
- if (this.element?.trigger) {
2637
- this.element.trigger.removeEventListener('keydown', this.handleEvent);
2638
- this.element.trigger.removeEventListener('click', this.handleEvent);
2639
- this.element.trigger.removeEventListener('mouseenter', this.handleEvent);
2640
- this.element.trigger.removeEventListener('mouseleave', this.handleEvent);
2641
- this.element.trigger.removeEventListener('focus', this.handleEvent);
2642
- this.element.trigger.removeEventListener('blur', this.handleEvent);
2821
+ if (this.element) {
2822
+ this.element.cleanup?.();
2823
+
2824
+ if (this.element.bib) {
2825
+ this.element.shadowRoot.append(this.element.bib);
2826
+ }
2827
+
2828
+ // Remove event & keyboard listeners
2829
+ if (this.element?.trigger) {
2830
+ this.element.trigger.removeEventListener('keydown', this.handleEvent);
2831
+ this.element.trigger.removeEventListener('click', this.handleEvent);
2832
+ this.element.trigger.removeEventListener('mouseenter', this.handleEvent);
2833
+ this.element.trigger.removeEventListener('mouseleave', this.handleEvent);
2834
+ this.element.trigger.removeEventListener('focus', this.handleEvent);
2835
+ this.element.trigger.removeEventListener('blur', this.handleEvent);
2836
+ }
2643
2837
  }
2644
2838
  }
2645
2839
  }
@@ -3602,6 +3796,11 @@ class AuroDropdown extends r$1 {
3602
3796
  * @private
3603
3797
  */
3604
3798
  this.helpTextTag = versioning.generateTag('auro-formkit-dropdown-helptext', helpTextVersion$1, AuroHelpText$1);
3799
+
3800
+ /**
3801
+ * @private
3802
+ */
3803
+ this.bindFocusEventToTrigger = this.bindFocusEventToTrigger.bind(this);
3605
3804
  }
3606
3805
 
3607
3806
  /**
@@ -3870,6 +4069,7 @@ class AuroDropdown extends r$1 {
3870
4069
  disconnectedCallback() {
3871
4070
  super.disconnectedCallback();
3872
4071
  this.floater.disconnect();
4072
+ this.clearTriggerFocusEventBinding();
3873
4073
  }
3874
4074
 
3875
4075
  updated(changedProperties) {
@@ -3984,6 +4184,62 @@ class AuroDropdown extends r$1 {
3984
4184
  return result;
3985
4185
  }
3986
4186
 
4187
+ /**
4188
+ * @private
4189
+ * Creates and dispatches a duplicate focus event on the trigger element.
4190
+ * @param {Event} event - The original focus event.
4191
+ */
4192
+ bindFocusEventToTrigger(event) {
4193
+ const dupEvent = new FocusEvent(event.type, {
4194
+ bubbles: false,
4195
+ cancelable: false,
4196
+ composed: true,
4197
+ });
4198
+ this.trigger.dispatchEvent(dupEvent);
4199
+ }
4200
+
4201
+ /**
4202
+ * @private
4203
+ * Sets up event listeners to deliver focus and blur events from nested Auro components within the trigger slot to trigger.
4204
+ * This ensures that focus/blur events originating from within these components are propagated to the trigger element itself.
4205
+ */
4206
+ setupTriggerFocusEventBinding() {
4207
+ if (!this.triggerContentSlot || this.triggerContentSlot.length === 0) {
4208
+ return;
4209
+ }
4210
+
4211
+ this.triggerContentSlot.forEach((node) => {
4212
+ if (node.querySelectorAll) {
4213
+ const auroElements = node.querySelectorAll('auro-input, [auro-input], auro-button, [auro-button], button, input');
4214
+ auroElements.forEach((auroEl) => {
4215
+ auroEl.addEventListener('focus', this.bindFocusEventToTrigger);
4216
+ auroEl.addEventListener('blur', this.bindFocusEventToTrigger);
4217
+ });
4218
+ }
4219
+ });
4220
+ }
4221
+
4222
+ /**
4223
+ * Clears focus and blur event listeners from nested Auro components within the trigger slot.
4224
+ * @private
4225
+ * @returns {void}
4226
+ */
4227
+ clearTriggerFocusEventBinding() {
4228
+ if (!this.triggerContentSlot || this.triggerContentSlot.length === 0) {
4229
+ return;
4230
+ }
4231
+
4232
+ this.triggerContentSlot.forEach((node) => {
4233
+ if (node.querySelectorAll) {
4234
+ const auroElements = node.querySelectorAll('auro-input, [auro-input], auro-button, [auro-button], button, input');
4235
+ auroElements.forEach((auroEl) => {
4236
+ auroEl.removeEventListener('focus', this.bindFocusEventToTrigger);
4237
+ auroEl.removeEventListener('blur', this.bindFocusEventToTrigger);
4238
+ });
4239
+ }
4240
+ });
4241
+ }
4242
+
3987
4243
  /**
3988
4244
  * Handles changes to the trigger content slot and updates related properties.
3989
4245
  *
@@ -4031,6 +4287,7 @@ class AuroDropdown extends r$1 {
4031
4287
  }
4032
4288
 
4033
4289
  if (this.triggerContentSlot) {
4290
+ this.setupTriggerFocusEventBinding();
4034
4291
  this.hasTriggerContent = this.triggerContentSlot.some((slot) => {
4035
4292
  if (slot.textContent.trim()) {
4036
4293
  return true;
@@ -4136,6 +4393,7 @@ class AuroDropdown extends r$1 {
4136
4393
  <${this.dropdownBibTag}
4137
4394
  id="bib"
4138
4395
  role="tooltip"
4396
+ ?data-show="${this.isPopoverVisible}"
4139
4397
  ?isfullscreen="${this.isBibFullscreen}"
4140
4398
  ?common="${this.common}"
4141
4399
  ?rounded="${this.common || this.rounded}"