@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
@@ -107,7 +107,7 @@ The use of any Auro custom element has a dependency on the [Auro Design Tokens](
107
107
  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.
108
108
 
109
109
  ```html
110
- <script type="module" src="https://cdn.jsdelivr.net/npm/@aurodesignsystem/auro-formkit@2.2.1-beta.1/auro-dropdown/+esm"></script>
110
+ <script type="module" src="https://cdn.jsdelivr.net/npm/@aurodesignsystem/auro-formkit@2.2.1-beta.3/auro-dropdown/+esm"></script>
111
111
  ```
112
112
  <!-- AURO-GENERATED-CONTENT:END -->
113
113
 
@@ -1636,17 +1636,70 @@ const computePosition = (reference, floating, options) => {
1636
1636
  /* eslint-disable line-comment-position, no-inline-comments */
1637
1637
 
1638
1638
 
1639
+
1640
+ const MAX_CONFIGURATION_COUNT = 10;
1641
+
1639
1642
  class AuroFloatingUI {
1640
- constructor() {
1643
+
1644
+ /**
1645
+ * @private
1646
+ */
1647
+ static isMousePressed = false;
1648
+
1649
+ /**
1650
+ * @private
1651
+ */
1652
+ static isMousePressHandlerInitialized = false;
1653
+
1654
+ /**
1655
+ * @private
1656
+ */
1657
+ static setupMousePressChecker() {
1658
+ if (!AuroFloatingUI.isMousePressHandlerInitialized && window && window.addEventListener) {
1659
+ AuroFloatingUI.isMousePressHandlerInitialized = true;
1660
+
1661
+ const mouseEventGlobalHandler = (event) => {
1662
+ AuroFloatingUI.isMousePressed = event.type === 'mousedown';
1663
+ };
1664
+
1665
+ window.addEventListener('mousedown', mouseEventGlobalHandler);
1666
+ window.addEventListener('mouseup', mouseEventGlobalHandler);
1667
+ }
1668
+ }
1669
+
1670
+ constructor(element, behavior) {
1671
+ this.element = element;
1672
+ this.behavior = behavior;
1673
+
1641
1674
  // Store event listener references for cleanup
1642
1675
  this.focusHandler = null;
1643
1676
  this.clickHandler = null;
1644
1677
  this.keyDownHandler = null;
1645
-
1678
+
1679
+ /**
1680
+ * @private
1681
+ */
1682
+ this.configureTrial = 0;
1683
+
1646
1684
  /**
1647
1685
  * @private
1648
1686
  */
1649
1687
  this.eventPrefix = undefined;
1688
+
1689
+ /**
1690
+ * @private
1691
+ */
1692
+ this.id = undefined;
1693
+
1694
+ /**
1695
+ * @private
1696
+ */
1697
+ this.showing = false;
1698
+
1699
+ /**
1700
+ * @private
1701
+ */
1702
+ this.strategy = undefined;
1650
1703
  }
1651
1704
 
1652
1705
  /**
@@ -1674,29 +1727,48 @@ class AuroFloatingUI {
1674
1727
  * @private
1675
1728
  * Determines the positioning strategy based on the current viewport size and mobile breakpoint.
1676
1729
  *
1677
- * This method checks if the current viewport width is less than or equal to the specified mobile fullscreen breakpoint
1730
+ * This method checks if the current viewport width is less than or equal to the specified mobile fullscreen breakpoint
1678
1731
  * defined in the bib element. If it is, the strategy is set to 'fullscreen'; otherwise, it defaults to 'floating'.
1679
1732
  *
1680
- * @returns {String} The positioning strategy, either 'fullscreen' or 'floating'.
1733
+ * @returns {String} The positioning strategy, one of 'fullscreen', 'floating', 'cover'.
1681
1734
  */
1682
1735
  getPositioningStrategy() {
1683
- let strategy = 'floating';
1684
- if (this.element.bib.mobileFullscreenBreakpoint) {
1685
- const smallerThanBreakpoint = window.matchMedia(`(max-width: ${this.element.bib.mobileFullscreenBreakpoint})`).matches;
1686
- if (smallerThanBreakpoint) {
1687
- strategy = 'fullscreen';
1688
- }
1736
+ const breakpoint = this.element.bib.mobileFullscreenBreakpoint || this.element.floaterConfig?.fullscreenBreakpoint;
1737
+ switch (this.behavior) {
1738
+ case "tooltip":
1739
+ return "floating";
1740
+ case "dialog":
1741
+ case "drawer":
1742
+ if (breakpoint) {
1743
+ const smallerThanBreakpoint = window.matchMedia(`(max-width: ${breakpoint})`).matches;
1744
+
1745
+ this.element.expanded = smallerThanBreakpoint;
1746
+ }
1747
+ if (this.element.nested) {
1748
+ return "cover";
1749
+ }
1750
+ return 'fullscreen';
1751
+ case "dropdown":
1752
+ case undefined:
1753
+ case null:
1754
+ if (breakpoint) {
1755
+ const smallerThanBreakpoint = window.matchMedia(`(max-width: ${breakpoint})`).matches;
1756
+ if (smallerThanBreakpoint) {
1757
+ return 'fullscreen';
1758
+ }
1759
+ }
1760
+ return "floating";
1761
+ default:
1762
+ return this.behavior;
1689
1763
  }
1690
-
1691
- return strategy;
1692
1764
  }
1693
1765
 
1694
1766
  /**
1695
1767
  * @private
1696
1768
  * Positions the bib element based on the current configuration and positioning strategy.
1697
1769
  *
1698
- * This method determines the appropriate positioning strategy (fullscreen or not) and configures the bib accordingly.
1699
- * It also sets up middleware for the floater configuration, computes the position of the bib relative to the trigger element,
1770
+ * This method determines the appropriate positioning strategy (fullscreen or not) and configures the bib accordingly.
1771
+ * It also sets up middleware for the floater configuration, computes the position of the bib relative to the trigger element,
1700
1772
  * and applies the calculated position to the bib's style.
1701
1773
  */
1702
1774
  position() {
@@ -1707,21 +1779,33 @@ class AuroFloatingUI {
1707
1779
  this.mirrorSize();
1708
1780
  // Define the middlware for the floater configuration
1709
1781
  const middleware = [
1710
- offset(this.element.floaterConfig.offset || 0),
1711
- ...(this.element.floaterConfig.flip ? [flip()] : []), // Add flip middleware if flip is enabled
1712
- ...(this.element.floaterConfig.autoPlacement ? [autoPlacement()] : []), // Add autoPlacement middleware if autoPlacement is enabled
1782
+ offset(this.element.floaterConfig?.offset || 0),
1783
+ ...this.element.floaterConfig?.flip ? [flip()] : [], // Add flip middleware if flip is enabled.
1784
+ ...this.element.floaterConfig?.autoPlacement ? [autoPlacement()] : [], // Add autoPlacement middleware if autoPlacement is enabled.
1713
1785
  ];
1714
1786
 
1715
1787
  // Compute the position of the bib
1716
1788
  computePosition(this.element.trigger, this.element.bib, {
1717
- placement: this.element.floaterConfig.placement || 'bottom',
1789
+ placement: this.element.floaterConfig?.placement,
1718
1790
  middleware: middleware || []
1719
- }).then(({x, y}) => { // eslint-disable-line id-length
1791
+ }).then(({ x, y }) => { // eslint-disable-line id-length
1720
1792
  Object.assign(this.element.bib.style, {
1721
1793
  left: `${x}px`,
1722
1794
  top: `${y}px`,
1723
1795
  });
1724
1796
  });
1797
+ } else if (strategy === 'cover') {
1798
+ // Compute the position of the bib
1799
+ computePosition(this.element.parentNode, this.element.bib, {
1800
+ placement: 'bottom-start'
1801
+ }).then(({ x, y }) => { // eslint-disable-line id-length
1802
+ Object.assign(this.element.bib.style, {
1803
+ left: `${x}px`,
1804
+ top: `${y - this.element.parentNode.offsetHeight}px`,
1805
+ width: `${this.element.parentNode.offsetWidth}px`,
1806
+ height: `${this.element.parentNode.offsetHeight}px`
1807
+ });
1808
+ });
1725
1809
  }
1726
1810
  }
1727
1811
 
@@ -1750,34 +1834,48 @@ class AuroFloatingUI {
1750
1834
  *
1751
1835
  * @param {string} strategy - The positioning strategy ('fullscreen' or 'floating').
1752
1836
  */
1753
- configureBibStrategy(strategy) {
1754
- const prevStrategy = this.element.isBibFullscreen ? 'fullscreen' : 'floating';
1755
- if (strategy === 'fullscreen') {
1837
+ configureBibStrategy(value) {
1838
+ if (value === 'fullscreen') {
1756
1839
  this.element.isBibFullscreen = true;
1757
1840
  // reset the prev position
1841
+ this.element.bib.setAttribute('isfullscreen', "");
1842
+ this.element.bib.style.position = 'fixed';
1758
1843
  this.element.bib.style.top = "0px";
1759
1844
  this.element.bib.style.left = "0px";
1845
+ this.element.bib.style.width = '';
1846
+ this.element.bib.style.height = '';
1760
1847
 
1761
1848
  // reset the size that was mirroring `size` css-part
1762
1849
  const bibContent = this.element.bib.shadowRoot.querySelector(".container");
1763
- bibContent.style.width = '';
1764
- bibContent.style.height = '';
1765
- bibContent.style.maxWidth = '';
1766
- bibContent.style.maxHeight = `${window.visualViewport.height}px`;
1850
+ if (bibContent) {
1851
+ bibContent.style.width = '';
1852
+ bibContent.style.height = '';
1853
+ bibContent.style.maxWidth = '';
1854
+ bibContent.style.maxHeight = `${window.visualViewport.height}px`;
1855
+ this.configureTrial = 0;
1856
+ } else if (this.configureTrial < MAX_CONFIGURATION_COUNT) {
1857
+ this.configureTrial += 1;
1858
+
1859
+ setTimeout(() => {
1860
+ this.configureBibStrategy(value);
1861
+ }, 0);
1862
+ }
1767
1863
 
1768
1864
  if (this.element.isPopoverVisible) {
1769
1865
  this.lockScroll(true);
1770
1866
  }
1771
1867
  } else {
1868
+ this.element.bib.style.position = '';
1869
+ this.element.bib.removeAttribute('isfullscreen');
1772
1870
  this.element.isBibFullscreen = false;
1773
-
1774
- this.lockScroll(false);
1775
1871
  }
1776
1872
 
1777
- if (prevStrategy !== strategy) {
1873
+ const isChanged = this.strategy && this.strategy !== value;
1874
+ this.strategy = value;
1875
+ if (isChanged) {
1778
1876
  const event = new CustomEvent(this.eventPrefix ? `${this.eventPrefix}-strategy-change` : 'strategy-change', {
1779
1877
  detail: {
1780
- strategy,
1878
+ value,
1781
1879
  },
1782
1880
  composed: true
1783
1881
  });
@@ -1788,18 +1886,6 @@ class AuroFloatingUI {
1788
1886
 
1789
1887
  updateState() {
1790
1888
  const isVisible = this.element.isPopoverVisible;
1791
-
1792
- // Refactor this to apply attribute to correct focusable element
1793
- // Reference Issue: https://github.com/AlaskaAirlines/auro-library/issues/105
1794
- //
1795
- // this.element.trigger.setAttribute('aria-expanded', isVisible);
1796
-
1797
- if (isVisible) {
1798
- this.element.bib.setAttribute('data-show', true);
1799
- } else {
1800
- this.element.bib.removeAttribute('data-show');
1801
- }
1802
-
1803
1889
  if (!isVisible) {
1804
1890
  this.cleanupHideHandlers();
1805
1891
  try {
@@ -1810,16 +1896,32 @@ class AuroFloatingUI {
1810
1896
  }
1811
1897
  }
1812
1898
 
1899
+ /**
1900
+ * @private
1901
+ * getting called on 'blur' in trigger or `focusin` in document
1902
+ *
1903
+ * Hides the bib if focus moves outside of the trigger or bib, unless a 'noHideOnThisFocusLoss' flag is set.
1904
+ * This method checks if the currently active element is still within the trigger or bib.
1905
+ * If not, and if the bib isn't in fullscreen mode with focus lost, it hides the bib.
1906
+ */
1813
1907
  handleFocusLoss() {
1814
- if (this.element.noHideOnThisFocusLoss ||
1815
- this.element.hasAttribute('noHideOnThisFocusLoss')) {
1908
+ // if mouse is being pressed, skip and let click event to handle the action
1909
+ if (AuroFloatingUI.isMousePressed) {
1910
+ return;
1911
+ }
1912
+
1913
+ if (this.element.noHideOnThisFocusLoss ||
1914
+ this.element.hasAttribute('noHideOnThisFocusLoss')) {
1816
1915
  return;
1817
1916
  }
1818
1917
 
1819
- const {activeElement} = document;
1820
- if (activeElement === document.querySelector('body') ||
1821
- this.element.contains(activeElement) ||
1822
- this.element.bibContent?.contains(activeElement)) {
1918
+ const { activeElement } = document;
1919
+ // if focus is still inside of trigger or bib, do not close
1920
+ if (this.element.contains(activeElement) || this.element.bib?.contains(activeElement)) {
1921
+ return;
1922
+ }
1923
+ // if fullscreen bib is still open and the focus is missing, do not close
1924
+ if (this.element.bib.hasAttribute('isfullscreen') && activeElement === document.body) {
1823
1925
  return;
1824
1926
  }
1825
1927
 
@@ -1827,31 +1929,66 @@ class AuroFloatingUI {
1827
1929
  }
1828
1930
 
1829
1931
  setupHideHandlers() {
1932
+ this.preventFocusLoseOnBibClick = (event) => {
1933
+ event.preventDefault();
1934
+ event.stopPropagation();
1935
+ };
1936
+ this.element.bib.addEventListener('mousedown', this.preventFocusLoseOnBibClick);
1937
+
1830
1938
  // Define handlers & store references
1831
1939
  this.focusHandler = () => this.handleFocusLoss();
1832
1940
 
1833
1941
  this.clickHandler = (evt) => {
1834
- if (!evt.composedPath().includes(this.element.trigger) &&
1835
- !evt.composedPath().includes(this.element.bibContent)) {
1836
- this.hideBib();
1942
+ if ((!evt.composedPath().includes(this.element.trigger) &&
1943
+ !evt.composedPath().includes(this.element.bib)) ||
1944
+ (this.element.bib.backdrop && evt.composedPath().includes(this.element.bib.backdrop))) {
1945
+ const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
1946
+
1947
+ if (existedVisibleFloatingUI && existedVisibleFloatingUI.element.isPopoverVisible) {
1948
+ // if something else is open, close that
1949
+ existedVisibleFloatingUI.hideBib();
1950
+ document.expandedAuroFormkitDropdown = null;
1951
+ document.expandedAuroFloater = this;
1952
+ } else {
1953
+ this.hideBib();
1954
+ }
1837
1955
  }
1838
1956
  };
1839
1957
 
1840
1958
  // ESC key handler
1841
1959
  this.keyDownHandler = (evt) => {
1842
1960
  if (evt.key === 'Escape' && this.element.isPopoverVisible) {
1961
+ const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
1962
+ if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this && existedVisibleFloatingUI.element.isPopoverVisible) {
1963
+ // if something else is open, let it handle itself
1964
+ return;
1965
+ }
1843
1966
  this.hideBib();
1844
1967
  }
1845
1968
  };
1846
1969
 
1847
- // Add event listeners using the stored references
1848
- document.addEventListener('focusin', this.focusHandler);
1849
- window.addEventListener('click', this.clickHandler);
1970
+ if (this.behavior !== 'drawer' && this.behavior !== 'dialog') {
1971
+ // Add event listeners using the stored references
1972
+ document.addEventListener('focusin', this.focusHandler);
1973
+ }
1974
+
1850
1975
  document.addEventListener('keydown', this.keyDownHandler);
1976
+
1977
+ // send this task to the end of queue to prevent conflicting
1978
+ // it conflicts if showBib gets call from a button that's not this.element.trigger
1979
+ setTimeout(() => {
1980
+ window.addEventListener('click', this.clickHandler);
1981
+ }, 0);
1851
1982
  }
1852
1983
 
1853
1984
  cleanupHideHandlers() {
1854
1985
  // Remove event listeners if they exist
1986
+
1987
+ if (this.preventFocusLoseOnBibClick) {
1988
+ this.element.bib.removeEventListener('mousedown', this.preventFocusLoseOnBibClick);
1989
+ delete this.preventFocusLoseOnBibClick;
1990
+ }
1991
+
1855
1992
  if (this.focusHandler) {
1856
1993
  document.removeEventListener('focusin', this.focusHandler);
1857
1994
  this.focusHandler = null;
@@ -1876,40 +2013,54 @@ class AuroFloatingUI {
1876
2013
 
1877
2014
  updateCurrentExpandedDropdown() {
1878
2015
  // Close any other dropdown that is already open
1879
- if (document.expandedAuroFormkitDropdown) {
1880
- document.expandedAuroFormkitDropdown.hide;
2016
+ const existedVisibleFloatingUI = document.expandedAuroFormkitDropdown || document.expandedAuroFloater;
2017
+ if (existedVisibleFloatingUI && existedVisibleFloatingUI !== this &&
2018
+ existedVisibleFloatingUI.isPopoverVisible &&
2019
+ document.expandedAuroFloater.eventPrefix === this.eventPrefix) {
2020
+ document.expandedAuroFloater.hideBib();
1881
2021
  }
1882
2022
 
1883
- document.expandedAuroFormkitDropdown = this;
2023
+ document.expandedAuroFloater = this;
1884
2024
  }
1885
2025
 
1886
2026
  showBib() {
1887
- if (!this.element.disabled && !this.element.isPopoverVisible) {
2027
+ if (!this.element.disabled && !this.showing) {
1888
2028
  this.updateCurrentExpandedDropdown();
1889
- this.element.isPopoverVisible = true;
1890
2029
  this.element.triggerChevron?.setAttribute('data-expanded', true);
1891
-
1892
- this.dispatchEventDropdownToggle();
1893
- this.position();
1894
-
1895
- // Clean up any existing handlers before setting up new ones
1896
- this.cleanupHideHandlers();
1897
- this.setupHideHandlers();
2030
+
2031
+ // prevent double showing: isPopovervisible gets first and showBib gets called later
2032
+ if (!this.showing) {
2033
+ if (!this.element.modal) {
2034
+ this.setupHideHandlers();
2035
+ }
2036
+ this.showing = true;
2037
+ this.element.isPopoverVisible = true;
2038
+ this.position();
2039
+ this.dispatchEventDropdownToggle();
2040
+ }
1898
2041
 
1899
2042
  // Setup auto update to handle resize and scroll
1900
- this.element.cleanup = autoUpdate(this.element.trigger, this.element.bib, () => {
2043
+ this.element.cleanup = autoUpdate(this.element.trigger || this.element.parentNode, this.element.bib, () => {
1901
2044
  this.position();
1902
2045
  });
1903
2046
  }
1904
2047
  }
1905
2048
 
1906
2049
  hideBib() {
1907
- if (this.element.isPopoverVisible && !this.element.disabled && !this.element.noToggle) {
1908
- this.element.isPopoverVisible = false;
2050
+ if (!this.element.disabled && !this.element.noToggle) {
1909
2051
  this.lockScroll(false);
1910
2052
  this.element.triggerChevron?.removeAttribute('data-expanded');
1911
- this.dispatchEventDropdownToggle();
2053
+
2054
+ if (this.element.isPopoverVisible) {
2055
+ this.element.isPopoverVisible = false;
2056
+ }
2057
+ if (this.showing) {
2058
+ this.cleanupHideHandlers();
2059
+ this.showing = false;
2060
+ this.dispatchEventDropdownToggle();
2061
+ }
1912
2062
  }
2063
+ document.expandedAuroFloater = null;
1913
2064
  }
1914
2065
 
1915
2066
  /**
@@ -1919,7 +2070,7 @@ class AuroFloatingUI {
1919
2070
  dispatchEventDropdownToggle() {
1920
2071
  const event = new CustomEvent(this.eventPrefix ? `${this.eventPrefix}-toggled` : 'toggled', {
1921
2072
  detail: {
1922
- expanded: this.element.isPopoverVisible,
2073
+ expanded: this.showing,
1923
2074
  },
1924
2075
  composed: true
1925
2076
  });
@@ -1967,15 +2118,18 @@ class AuroFloatingUI {
1967
2118
  break;
1968
2119
  case 'focus':
1969
2120
  if (this.element.focusShow) {
2121
+
1970
2122
  /*
1971
- This needs to better handle clicking that gives focus -
1972
- currently it shows and then immediately hides the bib
2123
+ This needs to better handle clicking that gives focus -
2124
+ currently it shows and then immediately hides the bib
1973
2125
  */
1974
2126
  this.showBib();
1975
2127
  }
1976
2128
  break;
1977
2129
  case 'blur':
1978
- this.handleFocusLoss();
2130
+ // send this task 100ms later queue to
2131
+ // wait a frame in case focus moves within the floating element/bib
2132
+ setTimeout(() => this.handleFocusLoss(), 0);
1979
2133
  break;
1980
2134
  case 'click':
1981
2135
  if (document.activeElement === document.body) {
@@ -1983,7 +2137,7 @@ class AuroFloatingUI {
1983
2137
  }
1984
2138
  this.handleClick();
1985
2139
  break;
1986
- // Do nothing
2140
+ // Do nothing
1987
2141
  }
1988
2142
  }
1989
2143
  }
@@ -2027,39 +2181,79 @@ class AuroFloatingUI {
2027
2181
  });
2028
2182
  }
2029
2183
 
2184
+ /**
2185
+ *
2186
+ * @param {*} eventPrefix
2187
+ */
2188
+ regenerateBibId() {
2189
+ this.id = this.element.getAttribute('id');
2190
+ if (!this.id) {
2191
+ this.id = window.crypto.randomUUID();
2192
+ this.element.setAttribute('id', this.id);
2193
+ }
2194
+
2195
+ this.element.bib.setAttribute("id", `${this.id}-floater-bib`);
2196
+ }
2197
+
2030
2198
  configure(elem, eventPrefix) {
2199
+ AuroFloatingUI.setupMousePressChecker();
2200
+
2031
2201
  this.eventPrefix = eventPrefix;
2032
- this.element = elem;
2033
- this.element.trigger = this.element.shadowRoot.querySelector('#trigger');
2034
- this.element.bib = this.element.shadowRoot.querySelector('#bib');
2202
+ if (this.element !== elem) {
2203
+ this.element = elem;
2204
+ }
2205
+
2206
+ if (this.behavior !== this.element.behavior) {
2207
+ this.behavior = this.element.behavior;
2208
+ }
2209
+
2210
+ if (this.element.trigger) {
2211
+ this.disconnect();
2212
+ }
2213
+ this.element.trigger = this.element.triggerElement || this.element.shadowRoot.querySelector('#trigger') || this.element.trigger;
2214
+ this.element.bib = this.element.shadowRoot.querySelector('#bib') || this.element.bib;
2035
2215
  this.element.bibSizer = this.element.shadowRoot.querySelector('#bibSizer');
2036
2216
  this.element.triggerChevron = this.element.shadowRoot.querySelector('#showStateIcon');
2037
2217
 
2218
+
2219
+ if (this.element.floaterConfig) {
2220
+ this.element.hoverToggle = this.element.floaterConfig.hoverToggle;
2221
+ }
2222
+
2038
2223
  document.body.append(this.element.bib);
2039
2224
 
2225
+ this.regenerateBibId();
2040
2226
  this.handleTriggerTabIndex();
2041
2227
 
2042
2228
  this.handleEvent = this.handleEvent.bind(this);
2043
- this.element.trigger.addEventListener('keydown', this.handleEvent);
2044
- this.element.trigger.addEventListener('click', this.handleEvent);
2045
- this.element.trigger.addEventListener('mouseenter', this.handleEvent);
2046
- this.element.trigger.addEventListener('mouseleave', this.handleEvent);
2047
- this.element.trigger.addEventListener('focus', this.handleEvent);
2048
- this.element.trigger.addEventListener('blur', this.handleEvent);
2229
+ if (this.element.trigger) {
2230
+ this.element.trigger.addEventListener('keydown', this.handleEvent);
2231
+ this.element.trigger.addEventListener('click', this.handleEvent);
2232
+ this.element.trigger.addEventListener('mouseenter', this.handleEvent);
2233
+ this.element.trigger.addEventListener('mouseleave', this.handleEvent);
2234
+ this.element.trigger.addEventListener('focus', this.handleEvent);
2235
+ this.element.trigger.addEventListener('blur', this.handleEvent);
2236
+ }
2049
2237
  }
2050
2238
 
2051
2239
  disconnect() {
2052
2240
  this.cleanupHideHandlers();
2053
- this.element.cleanup?.();
2054
-
2055
- // Remove event & keyboard listeners
2056
- if (this.element?.trigger) {
2057
- this.element.trigger.removeEventListener('keydown', this.handleEvent);
2058
- this.element.trigger.removeEventListener('click', this.handleEvent);
2059
- this.element.trigger.removeEventListener('mouseenter', this.handleEvent);
2060
- this.element.trigger.removeEventListener('mouseleave', this.handleEvent);
2061
- this.element.trigger.removeEventListener('focus', this.handleEvent);
2062
- this.element.trigger.removeEventListener('blur', this.handleEvent);
2241
+ if (this.element) {
2242
+ this.element.cleanup?.();
2243
+
2244
+ if (this.element.bib) {
2245
+ this.element.shadowRoot.append(this.element.bib);
2246
+ }
2247
+
2248
+ // Remove event & keyboard listeners
2249
+ if (this.element?.trigger) {
2250
+ this.element.trigger.removeEventListener('keydown', this.handleEvent);
2251
+ this.element.trigger.removeEventListener('click', this.handleEvent);
2252
+ this.element.trigger.removeEventListener('mouseenter', this.handleEvent);
2253
+ this.element.trigger.removeEventListener('mouseleave', this.handleEvent);
2254
+ this.element.trigger.removeEventListener('focus', this.handleEvent);
2255
+ this.element.trigger.removeEventListener('blur', this.handleEvent);
2256
+ }
2063
2257
  }
2064
2258
  }
2065
2259
  }
@@ -3041,6 +3235,11 @@ class AuroDropdown extends r {
3041
3235
  * @private
3042
3236
  */
3043
3237
  this.helpTextTag = versioning.generateTag('auro-formkit-dropdown-helptext', helpTextVersion, AuroHelpText);
3238
+
3239
+ /**
3240
+ * @private
3241
+ */
3242
+ this.bindFocusEventToTrigger = this.bindFocusEventToTrigger.bind(this);
3044
3243
  }
3045
3244
 
3046
3245
  /**
@@ -3309,6 +3508,7 @@ class AuroDropdown extends r {
3309
3508
  disconnectedCallback() {
3310
3509
  super.disconnectedCallback();
3311
3510
  this.floater.disconnect();
3511
+ this.clearTriggerFocusEventBinding();
3312
3512
  }
3313
3513
 
3314
3514
  updated(changedProperties) {
@@ -3423,6 +3623,62 @@ class AuroDropdown extends r {
3423
3623
  return result;
3424
3624
  }
3425
3625
 
3626
+ /**
3627
+ * @private
3628
+ * Creates and dispatches a duplicate focus event on the trigger element.
3629
+ * @param {Event} event - The original focus event.
3630
+ */
3631
+ bindFocusEventToTrigger(event) {
3632
+ const dupEvent = new FocusEvent(event.type, {
3633
+ bubbles: false,
3634
+ cancelable: false,
3635
+ composed: true,
3636
+ });
3637
+ this.trigger.dispatchEvent(dupEvent);
3638
+ }
3639
+
3640
+ /**
3641
+ * @private
3642
+ * Sets up event listeners to deliver focus and blur events from nested Auro components within the trigger slot to trigger.
3643
+ * This ensures that focus/blur events originating from within these components are propagated to the trigger element itself.
3644
+ */
3645
+ setupTriggerFocusEventBinding() {
3646
+ if (!this.triggerContentSlot || this.triggerContentSlot.length === 0) {
3647
+ return;
3648
+ }
3649
+
3650
+ this.triggerContentSlot.forEach((node) => {
3651
+ if (node.querySelectorAll) {
3652
+ const auroElements = node.querySelectorAll('auro-input, [auro-input], auro-button, [auro-button], button, input');
3653
+ auroElements.forEach((auroEl) => {
3654
+ auroEl.addEventListener('focus', this.bindFocusEventToTrigger);
3655
+ auroEl.addEventListener('blur', this.bindFocusEventToTrigger);
3656
+ });
3657
+ }
3658
+ });
3659
+ }
3660
+
3661
+ /**
3662
+ * Clears focus and blur event listeners from nested Auro components within the trigger slot.
3663
+ * @private
3664
+ * @returns {void}
3665
+ */
3666
+ clearTriggerFocusEventBinding() {
3667
+ if (!this.triggerContentSlot || this.triggerContentSlot.length === 0) {
3668
+ return;
3669
+ }
3670
+
3671
+ this.triggerContentSlot.forEach((node) => {
3672
+ if (node.querySelectorAll) {
3673
+ const auroElements = node.querySelectorAll('auro-input, [auro-input], auro-button, [auro-button], button, input');
3674
+ auroElements.forEach((auroEl) => {
3675
+ auroEl.removeEventListener('focus', this.bindFocusEventToTrigger);
3676
+ auroEl.removeEventListener('blur', this.bindFocusEventToTrigger);
3677
+ });
3678
+ }
3679
+ });
3680
+ }
3681
+
3426
3682
  /**
3427
3683
  * Handles changes to the trigger content slot and updates related properties.
3428
3684
  *
@@ -3470,6 +3726,7 @@ class AuroDropdown extends r {
3470
3726
  }
3471
3727
 
3472
3728
  if (this.triggerContentSlot) {
3729
+ this.setupTriggerFocusEventBinding();
3473
3730
  this.hasTriggerContent = this.triggerContentSlot.some((slot) => {
3474
3731
  if (slot.textContent.trim()) {
3475
3732
  return true;
@@ -3575,6 +3832,7 @@ class AuroDropdown extends r {
3575
3832
  <${this.dropdownBibTag}
3576
3833
  id="bib"
3577
3834
  role="tooltip"
3835
+ ?data-show="${this.isPopoverVisible}"
3578
3836
  ?isfullscreen="${this.isBibFullscreen}"
3579
3837
  ?common="${this.common}"
3580
3838
  ?rounded="${this.common || this.rounded}"