@schukai/monster 4.136.3 → 4.136.5

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.
@@ -41,6 +41,7 @@ import { getLocaleOfDocument } from "../../dom/locale.mjs";
41
41
  import {
42
42
  findElementWithSelectorUpwards,
43
43
  getDocument,
44
+ getWindow,
44
45
  } from "../../dom/util.mjs";
45
46
  import {
46
47
  getDocumentTranslations,
@@ -69,6 +70,7 @@ import {
69
70
  isPositionedPopperOpen,
70
71
  openPositionedPopper,
71
72
  positionPopper,
73
+ resolveClippingBoundaryElement,
72
74
  } from "./util/floating-ui.mjs";
73
75
  import { Pathfinder } from "../../data/pathfinder.mjs";
74
76
  import { TokenList } from "../../types/tokenlist.mjs";
@@ -76,9 +78,14 @@ import { TokenList } from "../../types/tokenlist.mjs";
76
78
  import "../datatable/pagination.mjs";
77
79
 
78
80
  export {
81
+ getDefaultSelectPopperPositionProfile,
79
82
  getSelectionTemplate,
80
83
  getSummaryTemplate,
81
84
  popperElementSymbol,
85
+ resolveSelectPopperWidthConstraints,
86
+ resolveSelectListDimension,
87
+ resolveSelectVisibleRect,
88
+ resolveSelectViewportMetrics,
82
89
  Select,
83
90
  };
84
91
 
@@ -129,6 +136,14 @@ const clearOptionEventHandler = Symbol("clearOptionEventHandler");
129
136
  * @type {Symbol}
130
137
  */
131
138
  const resizeObserverSymbol = Symbol("resizeObserver");
139
+ const resizeObserverFrameSymbol = Symbol("resizeObserverFrame");
140
+ const visualViewportResizeHandlerSymbol = Symbol("visualViewportResizeHandler");
141
+ const visualViewportScrollHandlerSymbol = Symbol("visualViewportScrollHandler");
142
+ const visibilityChangeHandlerSymbol = Symbol("visibilityChangeHandler");
143
+ const windowResizeHandlerSymbol = Symbol("windowResizeHandler");
144
+ const windowOrientationChangeHandlerSymbol = Symbol(
145
+ "windowOrientationChangeHandler",
146
+ );
132
147
 
133
148
  /**
134
149
  * local symbol
@@ -343,6 +358,9 @@ const FILTER_POSITION_POPPER = "popper";
343
358
  * @type {string}
344
359
  */
345
360
  const FILTER_POSITION_INLINE = "inline";
361
+ const SELECT_MIN_POPPER_WIDTH = 240;
362
+ const SELECT_MAX_POPPER_HEIGHT = 500;
363
+ const SELECT_VIEWPORT_PADDING = 12;
346
364
 
347
365
  /**
348
366
  * A select control that can be used to select o
@@ -1765,55 +1783,20 @@ function getTranslations() {
1765
1783
  */
1766
1784
  function lookupSelection() {
1767
1785
  const self = this;
1786
+ const IntersectionObserverImplementation =
1787
+ getGlobal().IntersectionObserver;
1788
+
1789
+ if (!(IntersectionObserverImplementation instanceof Function)) {
1790
+ runSelectionLookupWhenVisible(self);
1791
+ return;
1792
+ }
1768
1793
 
1769
- const observer = new IntersectionObserver(
1794
+ const observer = new IntersectionObserverImplementation(
1770
1795
  (entries, obs) => {
1771
1796
  for (const entry of entries) {
1772
1797
  if (entry.isIntersecting) {
1773
1798
  obs.disconnect();
1774
-
1775
- setTimeout(() => {
1776
- const selection = self.getOption("selection");
1777
- if (
1778
- selection.length === 0 ||
1779
- self[isLoadingSymbol] ||
1780
- self[lazyLoadDoneSymbol]
1781
- ) {
1782
- return;
1783
- }
1784
-
1785
- let url = self.getOption("lookup.url") || self.getOption("url");
1786
- self[cleanupOptionsListSymbol] = false;
1787
-
1788
- if (self.getOption("lookup.grouping") === true) {
1789
- const values = selection
1790
- .map((s) => s?.["value"])
1791
- .filter(
1792
- (value) => isEmptyLookupValue.call(self, value) === false,
1793
- );
1794
- if (values.length === 0) {
1795
- return;
1796
- }
1797
- filterFromRemoteByValue
1798
- .call(self, url, { filter: values.join(",") })
1799
- .catch((e) => {
1800
- addErrorAttribute(self, e);
1801
- });
1802
- return;
1803
- }
1804
-
1805
- for (const s of selection) {
1806
- const value = s?.["value"];
1807
- if (isEmptyLookupValue.call(self, value)) {
1808
- continue;
1809
- }
1810
- filterFromRemoteByValue
1811
- .call(self, url, { filter: value })
1812
- .catch((e) => {
1813
- addErrorAttribute(self, e);
1814
- });
1815
- }
1816
- }, 100);
1799
+ runSelectionLookupWhenVisible(self);
1817
1800
  }
1818
1801
  }
1819
1802
  },
@@ -1823,6 +1806,49 @@ function lookupSelection() {
1823
1806
  observer.observe(self);
1824
1807
  }
1825
1808
 
1809
+ function runSelectionLookupWhenVisible(self) {
1810
+ setTimeout(() => {
1811
+ const selection = self.getOption("selection");
1812
+ if (
1813
+ selection.length === 0 ||
1814
+ self[isLoadingSymbol] ||
1815
+ self[lazyLoadDoneSymbol]
1816
+ ) {
1817
+ return;
1818
+ }
1819
+
1820
+ let url = self.getOption("lookup.url") || self.getOption("url");
1821
+ self[cleanupOptionsListSymbol] = false;
1822
+
1823
+ if (self.getOption("lookup.grouping") === true) {
1824
+ const values = selection
1825
+ .map((s) => s?.["value"])
1826
+ .filter((value) => isEmptyLookupValue.call(self, value) === false);
1827
+ if (values.length === 0) {
1828
+ return;
1829
+ }
1830
+ filterFromRemoteByValue
1831
+ .call(self, url, { filter: values.join(",") })
1832
+ .catch((e) => {
1833
+ addErrorAttribute(self, e);
1834
+ });
1835
+ return;
1836
+ }
1837
+
1838
+ for (const s of selection) {
1839
+ const value = s?.["value"];
1840
+ if (isEmptyLookupValue.call(self, value)) {
1841
+ continue;
1842
+ }
1843
+ filterFromRemoteByValue
1844
+ .call(self, url, { filter: value })
1845
+ .catch((e) => {
1846
+ addErrorAttribute(self, e);
1847
+ });
1848
+ }
1849
+ }, 100);
1850
+ }
1851
+
1826
1852
  /**
1827
1853
  * @private
1828
1854
  * @param {*} value
@@ -1967,21 +1993,8 @@ function initOptionsFromArguments() {
1967
1993
  * @private
1968
1994
  */
1969
1995
  function attachResizeObserver() {
1970
- // against flickering
1971
- this[resizeObserverSymbol] = new ResizeObserver((entries) => {
1972
- if (this[timerCallbackSymbol] instanceof DeadMansSwitch) {
1973
- try {
1974
- this[timerCallbackSymbol].touch();
1975
- return;
1976
- } catch (e) {
1977
- delete this[timerCallbackSymbol];
1978
- }
1979
- }
1980
-
1981
- this[timerCallbackSymbol] = new DeadMansSwitch(200, () => {
1982
- updatePopper.call(this);
1983
- delete this[timerCallbackSymbol];
1984
- });
1996
+ this[resizeObserverSymbol] = new ResizeObserver(() => {
1997
+ scheduleResizeObserverPopperUpdate.call(this);
1985
1998
  });
1986
1999
 
1987
2000
  let parent = this.parentNode;
@@ -1992,6 +2005,70 @@ function attachResizeObserver() {
1992
2005
  if (parent instanceof HTMLElement) {
1993
2006
  this[resizeObserverSymbol].observe(parent);
1994
2007
  }
2008
+
2009
+ for (const element of [
2010
+ this,
2011
+ this[controlElementSymbol],
2012
+ this[popperElementSymbol],
2013
+ this[popperFilterContainerElementSymbol],
2014
+ this[optionsElementSymbol],
2015
+ this[paginationElementSymbol],
2016
+ ]) {
2017
+ if (element instanceof HTMLElement) {
2018
+ this[resizeObserverSymbol].observe(element);
2019
+ }
2020
+ }
2021
+
2022
+ const boundaryElement = resolveClippingBoundaryElement(
2023
+ this[controlElementSymbol],
2024
+ this[popperElementSymbol],
2025
+ );
2026
+ if (boundaryElement instanceof HTMLElement) {
2027
+ this[resizeObserverSymbol].observe(boundaryElement);
2028
+ }
2029
+
2030
+ const viewport = getGlobal().visualViewport;
2031
+ const windowObject = getWindow();
2032
+ this[visualViewportResizeHandlerSymbol] = () => {
2033
+ updatePopper.call(this);
2034
+ };
2035
+ this[visualViewportScrollHandlerSymbol] = () => {
2036
+ updatePopper.call(this);
2037
+ };
2038
+ this[visibilityChangeHandlerSymbol] = () => {
2039
+ if (document.visibilityState === "visible") {
2040
+ updatePopper.call(this);
2041
+ }
2042
+ };
2043
+ this[windowResizeHandlerSymbol] = () => {
2044
+ updatePopper.call(this);
2045
+ };
2046
+ this[windowOrientationChangeHandlerSymbol] = () => {
2047
+ updatePopper.call(this);
2048
+ };
2049
+
2050
+ if (viewport) {
2051
+ viewport.addEventListener(
2052
+ "resize",
2053
+ this[visualViewportResizeHandlerSymbol],
2054
+ );
2055
+ viewport.addEventListener(
2056
+ "scroll",
2057
+ this[visualViewportScrollHandlerSymbol],
2058
+ );
2059
+ }
2060
+
2061
+ document.addEventListener(
2062
+ "visibilitychange",
2063
+ this[visibilityChangeHandlerSymbol],
2064
+ );
2065
+ if (windowObject?.addEventListener instanceof Function) {
2066
+ windowObject.addEventListener("resize", this[windowResizeHandlerSymbol]);
2067
+ windowObject.addEventListener(
2068
+ "orientationchange",
2069
+ this[windowOrientationChangeHandlerSymbol],
2070
+ );
2071
+ }
1995
2072
  }
1996
2073
 
1997
2074
  /**
@@ -2001,6 +2078,83 @@ function disconnectResizeObserver() {
2001
2078
  if (this[resizeObserverSymbol] instanceof ResizeObserver) {
2002
2079
  this[resizeObserverSymbol].disconnect();
2003
2080
  }
2081
+ cancelScheduledResizeObserverPopperUpdate.call(this);
2082
+
2083
+ const viewport = getGlobal().visualViewport;
2084
+ if (
2085
+ viewport &&
2086
+ this[visualViewportResizeHandlerSymbol] instanceof Function
2087
+ ) {
2088
+ viewport.removeEventListener(
2089
+ "resize",
2090
+ this[visualViewportResizeHandlerSymbol],
2091
+ );
2092
+ }
2093
+ if (
2094
+ viewport &&
2095
+ this[visualViewportScrollHandlerSymbol] instanceof Function
2096
+ ) {
2097
+ viewport.removeEventListener(
2098
+ "scroll",
2099
+ this[visualViewportScrollHandlerSymbol],
2100
+ );
2101
+ }
2102
+ if (this[visibilityChangeHandlerSymbol] instanceof Function) {
2103
+ document.removeEventListener(
2104
+ "visibilitychange",
2105
+ this[visibilityChangeHandlerSymbol],
2106
+ );
2107
+ }
2108
+ const windowObject = getWindow();
2109
+ if (
2110
+ windowObject?.removeEventListener instanceof Function &&
2111
+ this[windowResizeHandlerSymbol] instanceof Function
2112
+ ) {
2113
+ windowObject.removeEventListener("resize", this[windowResizeHandlerSymbol]);
2114
+ }
2115
+ if (
2116
+ windowObject?.removeEventListener instanceof Function &&
2117
+ this[windowOrientationChangeHandlerSymbol] instanceof Function
2118
+ ) {
2119
+ windowObject.removeEventListener(
2120
+ "orientationchange",
2121
+ this[windowOrientationChangeHandlerSymbol],
2122
+ );
2123
+ }
2124
+ }
2125
+
2126
+ function scheduleResizeObserverPopperUpdate() {
2127
+ const globalObject = getGlobal();
2128
+ if (typeof this[resizeObserverFrameSymbol] === "number") {
2129
+ return;
2130
+ }
2131
+
2132
+ const schedule =
2133
+ globalObject?.requestAnimationFrame instanceof Function
2134
+ ? globalObject.requestAnimationFrame.bind(globalObject)
2135
+ : (callback) => {
2136
+ return globalObject.setTimeout(callback, 16);
2137
+ };
2138
+
2139
+ this[resizeObserverFrameSymbol] = schedule(() => {
2140
+ delete this[resizeObserverFrameSymbol];
2141
+ updatePopper.call(this);
2142
+ });
2143
+ }
2144
+
2145
+ function cancelScheduledResizeObserverPopperUpdate() {
2146
+ const globalObject = getGlobal();
2147
+ const frameId = this[resizeObserverFrameSymbol];
2148
+ if (typeof frameId !== "number") {
2149
+ return;
2150
+ }
2151
+
2152
+ if (globalObject?.cancelAnimationFrame instanceof Function) {
2153
+ globalObject.cancelAnimationFrame(frameId);
2154
+ } else {
2155
+ globalObject.clearTimeout(frameId);
2156
+ }
2157
+ delete this[resizeObserverFrameSymbol];
2004
2158
  }
2005
2159
 
2006
2160
  /**
@@ -2460,10 +2614,9 @@ function calcAndSetOptionsDimension() {
2460
2614
  }
2461
2615
 
2462
2616
  let visible = 0;
2463
- let optionHeight = 0;
2617
+ const visibleOptionHeights = [];
2464
2618
  const max = this.getOption("showMaxOptions", 10);
2465
2619
 
2466
- let scrollFlag = false;
2467
2620
  for (const [, option] of Object.entries(options)) {
2468
2621
  const computedStyle = getGlobal().getComputedStyle(option);
2469
2622
  if (computedStyle.display === "none") continue;
@@ -2471,18 +2624,8 @@ function calcAndSetOptionsDimension() {
2471
2624
  let h = option.getBoundingClientRect().height;
2472
2625
  h += parseInt(computedStyle.getPropertyValue("margin-top"), 10);
2473
2626
  h += parseInt(computedStyle.getPropertyValue("margin-bottom"), 10);
2474
- optionHeight += h;
2475
-
2627
+ visibleOptionHeights.push(h);
2476
2628
  visible++;
2477
-
2478
- if (visible > max) {
2479
- break;
2480
- }
2481
- }
2482
-
2483
- if (visible > max) {
2484
- visible = max;
2485
- scrollFlag = true;
2486
2629
  }
2487
2630
 
2488
2631
  if (visible === 0) {
@@ -2527,61 +2670,299 @@ function calcAndSetOptionsDimension() {
2527
2670
  let margin = parseInt(styles.getPropertyValue("margin-top"), 10);
2528
2671
  margin += parseInt(styles.getPropertyValue("margin-bottom"), 10);
2529
2672
 
2530
- let containerHeight = optionHeight + padding + margin;
2531
- const maxViewportHeight = Math.floor(getVisibleHeightLimit(this) / 3);
2532
- if (containerHeight > maxViewportHeight) {
2533
- containerHeight = maxViewportHeight;
2534
- }
2673
+ const geometry = getSelectPopperGeometry.call(this);
2674
+ const listDimension = resolveSelectListDimension({
2675
+ visibleOptionHeights,
2676
+ maxVisibleOptions: max,
2677
+ availableHeight: geometry.availableHeight,
2678
+ padding,
2679
+ margin,
2680
+ });
2681
+ const widthConstraints = resolveSelectPopperWidthConstraints({
2682
+ controlWidth: this[controlElementSymbol].getBoundingClientRect().width,
2683
+ availableWidth: geometry.availableWidth,
2684
+ });
2535
2685
 
2536
- container.style.height = `${containerHeight}px`;
2686
+ container.style.height =
2687
+ listDimension.desiredHeight > 0 ? `${listDimension.desiredHeight}px` : "0px";
2688
+ container.style.maxHeight =
2689
+ listDimension.maxHeight > 0 ? `${listDimension.maxHeight}px` : "0px";
2690
+ container.style.overflowY = listDimension.overflowY;
2537
2691
 
2538
- if (scrollFlag === true) {
2539
- container.style.overflowY = "scroll";
2692
+ this[popperElementSymbol].dataset.monsterPreferredWidth = `${Math.ceil(
2693
+ widthConstraints.preferredWidth,
2694
+ )}`;
2695
+ if (
2696
+ Number.isFinite(widthConstraints.maxWidth) &&
2697
+ widthConstraints.maxWidth > 0
2698
+ ) {
2699
+ this[popperElementSymbol].dataset.monsterPreferredMaxWidth = `${Math.ceil(
2700
+ widthConstraints.maxWidth,
2701
+ )}`;
2702
+ this[popperElementSymbol].style.maxWidth = `${Math.ceil(
2703
+ widthConstraints.maxWidth,
2704
+ )}px`;
2540
2705
  } else {
2541
- container.style.overflowY = "auto";
2706
+ delete this[popperElementSymbol].dataset.monsterPreferredMaxWidth;
2707
+ this[popperElementSymbol].style.removeProperty("maxWidth");
2542
2708
  }
2709
+ this[popperElementSymbol].style.width = "";
2710
+ this[popperElementSymbol].style.removeProperty("minWidth");
2711
+ this[popperElementSymbol].style.maxHeight = `${Math.ceil(
2712
+ Math.min(geometry.availableHeight, SELECT_MAX_POPPER_HEIGHT),
2713
+ )}px`;
2714
+ container.style.overflowX = "hidden";
2543
2715
 
2544
- const domRect = this[controlElementSymbol].getBoundingClientRect();
2716
+ if (content instanceof HTMLElement) {
2717
+ content.style.overflow = "hidden";
2718
+ content.style.maxHeight =
2719
+ listDimension.maxHeight > 0 ? `${listDimension.maxHeight}px` : "";
2720
+ }
2721
+ }
2545
2722
 
2546
- this[popperElementSymbol].dataset.monsterPreferredWidth = `${Math.ceil(
2547
- domRect.width,
2548
- )}`;
2549
- this[popperElementSymbol].style.width = `${domRect.width}px`;
2550
- this[popperElementSymbol].style.minWidth = `${domRect.width}px`;
2551
- container.style.overflowX = "auto";
2723
+ function resolveSelectPopperPreferredWidth(controlWidth) {
2724
+ return Math.max(Math.ceil(controlWidth), SELECT_MIN_POPPER_WIDTH);
2725
+ }
2552
2726
 
2553
- if (content instanceof HTMLElement) {
2554
- content.style.overflowX = "hidden";
2555
- content.style.overflowY = "hidden";
2727
+ function resolveSelectPopperWidthConstraints({
2728
+ controlWidth = 0,
2729
+ availableWidth = 0,
2730
+ }) {
2731
+ const preferredWidth = resolveSelectPopperPreferredWidth(controlWidth);
2732
+ const maxWidth = Math.max(0, availableWidth);
2733
+
2734
+ return {
2735
+ preferredWidth,
2736
+ maxWidth: maxWidth > 0 ? maxWidth : Infinity,
2737
+ };
2738
+ }
2739
+
2740
+ function resolveSelectListDimension({
2741
+ visibleOptionHeights = [],
2742
+ maxVisibleOptions = 10,
2743
+ availableHeight,
2744
+ padding = 0,
2745
+ margin = 0,
2746
+ }) {
2747
+ const visibleHeights = visibleOptionHeights.filter((height) => {
2748
+ return Number.isFinite(height) && height > 0;
2749
+ });
2750
+ const naturalListHeight =
2751
+ visibleHeights
2752
+ .slice(0, Math.max(0, maxVisibleOptions))
2753
+ .reduce((sum, height) => {
2754
+ return sum + height;
2755
+ }, 0) +
2756
+ padding +
2757
+ margin;
2758
+ const fullListHeight =
2759
+ visibleHeights.reduce((sum, height) => {
2760
+ return sum + height;
2761
+ }, 0) +
2762
+ padding +
2763
+ margin;
2764
+ const maxHeight = resolveSelectListMaxHeight({
2765
+ availableHeight,
2766
+ });
2767
+ const desiredHeight = Math.min(
2768
+ maxHeight,
2769
+ fullListHeight > 0 ? naturalListHeight : 0,
2770
+ );
2771
+
2772
+ return {
2773
+ desiredHeight,
2774
+ fullHeight: fullListHeight,
2775
+ maxHeight,
2776
+ overflowY: fullListHeight > desiredHeight ? "auto" : "hidden",
2777
+ };
2778
+ }
2779
+
2780
+ function resolveSelectListMaxHeight(geometry) {
2781
+ if (!geometry || !Number.isFinite(geometry.availableHeight)) {
2782
+ return SELECT_MAX_POPPER_HEIGHT;
2556
2783
  }
2784
+
2785
+ return Math.max(
2786
+ 0,
2787
+ Math.min(geometry.availableHeight, SELECT_MAX_POPPER_HEIGHT),
2788
+ );
2557
2789
  }
2558
2790
 
2559
- /**
2560
- * @private
2561
- */
2562
- function getVisibleHeightLimit(startEl) {
2563
- let el = startEl;
2564
- const gcs = getGlobal().getComputedStyle;
2791
+ function getViewportMetrics() {
2792
+ const globalObject = getGlobal();
2793
+ const documentElement = globalObject.document?.documentElement;
2794
+ const viewport = globalObject.visualViewport;
2795
+ const metrics = resolveSelectViewportMetrics({
2796
+ layoutWidth: Math.max(
2797
+ documentElement?.clientWidth || 0,
2798
+ globalObject.innerWidth || 0,
2799
+ ),
2800
+ layoutHeight: Math.max(
2801
+ documentElement?.clientHeight || 0,
2802
+ globalObject.innerHeight || 0,
2803
+ ),
2804
+ visualWidth: viewport?.width || 0,
2805
+ visualHeight: viewport?.height || 0,
2806
+ offsetLeft: viewport?.offsetLeft || 0,
2807
+ offsetTop: viewport?.offsetTop || 0,
2808
+ padding: SELECT_VIEWPORT_PADDING,
2809
+ });
2565
2810
 
2566
- while (el) {
2567
- const style = gcs(el);
2568
- const overflowY = style.overflowY;
2811
+ return {
2812
+ width: metrics.width,
2813
+ height: metrics.height,
2814
+ left: metrics.left,
2815
+ top: metrics.top,
2816
+ padding: metrics.padding,
2817
+ };
2818
+ }
2569
2819
 
2570
- const isScrollable = ["auto", "scroll", "hidden"].includes(overflowY);
2820
+ function resolveSelectViewportMetrics({
2821
+ layoutWidth = 0,
2822
+ layoutHeight = 0,
2823
+ visualWidth = 0,
2824
+ visualHeight = 0,
2825
+ offsetLeft = 0,
2826
+ offsetTop = 0,
2827
+ padding = SELECT_VIEWPORT_PADDING,
2828
+ }) {
2829
+ return {
2830
+ width: Math.max(layoutWidth, visualWidth),
2831
+ height: Math.max(layoutHeight, visualHeight),
2832
+ left: offsetLeft,
2833
+ top: offsetTop,
2834
+ padding,
2835
+ };
2836
+ }
2571
2837
 
2572
- if (isScrollable && el.clientHeight > 0) {
2573
- return el.clientHeight;
2574
- }
2838
+ function resolveSelectVisibleRect({
2839
+ viewportMetrics,
2840
+ boundaryRect = null,
2841
+ }) {
2842
+ const viewportLeft = (viewportMetrics?.left || 0) + (viewportMetrics?.padding || 0);
2843
+ const viewportTop = (viewportMetrics?.top || 0) + (viewportMetrics?.padding || 0);
2844
+ const viewportRight =
2845
+ (viewportMetrics?.left || 0) +
2846
+ (viewportMetrics?.width || 0) -
2847
+ (viewportMetrics?.padding || 0);
2848
+ const viewportBottom =
2849
+ (viewportMetrics?.top || 0) +
2850
+ (viewportMetrics?.height || 0) -
2851
+ (viewportMetrics?.padding || 0);
2852
+
2853
+ const left = boundaryRect
2854
+ ? Math.max(viewportLeft, boundaryRect.left)
2855
+ : viewportLeft;
2856
+ const top = boundaryRect
2857
+ ? Math.max(viewportTop, boundaryRect.top)
2858
+ : viewportTop;
2859
+ const right = boundaryRect
2860
+ ? Math.min(viewportRight, boundaryRect.right)
2861
+ : viewportRight;
2862
+ const bottom = boundaryRect
2863
+ ? Math.min(viewportBottom, boundaryRect.bottom)
2864
+ : viewportBottom;
2575
2865
 
2576
- const root = el.getRootNode?.();
2577
- if (root instanceof ShadowRoot && root.host) {
2578
- el = root.host;
2579
- } else {
2580
- el = el.parentElement;
2581
- }
2866
+ return {
2867
+ left,
2868
+ top,
2869
+ right,
2870
+ bottom,
2871
+ width: Math.max(0, right - left),
2872
+ height: Math.max(0, bottom - top),
2873
+ };
2874
+ }
2875
+
2876
+ function getSelectPopperGeometry() {
2877
+ const viewport = getViewportMetrics();
2878
+ const boundaryElement = resolveClippingBoundaryElement(
2879
+ this[controlElementSymbol],
2880
+ this[popperElementSymbol],
2881
+ );
2882
+ const controlRect = this[controlElementSymbol].getBoundingClientRect();
2883
+ const boundaryRect =
2884
+ boundaryElement instanceof HTMLElement
2885
+ ? boundaryElement.getBoundingClientRect()
2886
+ : null;
2887
+ const visibleRect = resolveSelectVisibleRect({
2888
+ viewportMetrics: viewport,
2889
+ boundaryRect,
2890
+ });
2891
+ const spaceAbove = Math.max(
2892
+ 0,
2893
+ controlRect.top - visibleRect.top,
2894
+ );
2895
+ const spaceBelow = Math.max(
2896
+ 0,
2897
+ visibleRect.bottom - controlRect.bottom,
2898
+ );
2899
+ const availableHeight = Math.max(spaceAbove, spaceBelow, 0);
2900
+
2901
+ return {
2902
+ spaceAbove,
2903
+ spaceBelow,
2904
+ availableHeight,
2905
+ availableWidth: visibleRect.width,
2906
+ boundaryElement,
2907
+ };
2908
+ }
2909
+
2910
+ function getSelectPopperPositionOptions() {
2911
+ const popperOptions = Object.assign({}, this.getOption("popper", {}));
2912
+ const middleware = popperOptions.middleware;
2913
+ const usesLegacyDefaultMiddleware =
2914
+ isArray(middleware) &&
2915
+ middleware.length === 2 &&
2916
+ middleware[0] === "flip" &&
2917
+ middleware[1] === "offset:1";
2918
+
2919
+ if (
2920
+ !isArray(middleware) ||
2921
+ middleware.length === 0 ||
2922
+ usesLegacyDefaultMiddleware
2923
+ ) {
2924
+ popperOptions.middleware = getDefaultSelectPopperPositionProfile().middleware;
2582
2925
  }
2583
2926
 
2584
- return window.innerHeight;
2927
+ if (
2928
+ !isString(popperOptions.placement) ||
2929
+ popperOptions.placement === "bottom"
2930
+ ) {
2931
+ popperOptions.placement =
2932
+ getDefaultSelectPopperPositionProfile().placement;
2933
+ }
2934
+
2935
+ return popperOptions;
2936
+ }
2937
+
2938
+ function getDefaultSelectPopperPositionProfile() {
2939
+ return {
2940
+ placement: "bottom-start",
2941
+ middleware: ["flip", "offset:4", "shift:crossAxis", "size"],
2942
+ };
2943
+ }
2944
+
2945
+ function resetSelectPopperDimensionStyles() {
2946
+ if (!(this[popperElementSymbol] instanceof HTMLElement)) {
2947
+ return;
2948
+ }
2949
+
2950
+ delete this[popperElementSymbol].dataset.monsterPreferredWidth;
2951
+ delete this[popperElementSymbol].dataset.monsterPreferredMaxWidth;
2952
+ this[popperElementSymbol].style.removeProperty("width");
2953
+ this[popperElementSymbol].style.removeProperty("minWidth");
2954
+ this[popperElementSymbol].style.removeProperty("maxWidth");
2955
+ this[popperElementSymbol].style.removeProperty("maxHeight");
2956
+
2957
+ const content = this[popperElementSymbol].querySelector('[part="content"]');
2958
+ if (content instanceof HTMLElement) {
2959
+ content.style.removeProperty("maxHeight");
2960
+ }
2961
+
2962
+ if (this[optionsElementSymbol] instanceof HTMLElement) {
2963
+ this[optionsElementSymbol].style.removeProperty("height");
2964
+ this[optionsElementSymbol].style.removeProperty("maxHeight");
2965
+ }
2585
2966
  }
2586
2967
 
2587
2968
  /**
@@ -3743,6 +4124,7 @@ function fetchData(url) {
3743
4124
  * @private
3744
4125
  */
3745
4126
  function hide() {
4127
+ resetSelectPopperDimensionStyles.call(this);
3746
4128
  closePositionedPopper(this[popperElementSymbol]);
3747
4129
  setStatusOrRemoveBadges.call(this, "closed");
3748
4130
  removeAttributeToken(this[controlElementSymbol], "class", "open");
@@ -3811,11 +4193,12 @@ function show() {
3811
4193
  return;
3812
4194
  }
3813
4195
 
4196
+ resetSelectPopperDimensionStyles.call(this);
3814
4197
  this[popperElementSymbol].style.visibility = "hidden";
3815
4198
  openPositionedPopper(
3816
4199
  this[controlElementSymbol],
3817
4200
  this[popperElementSymbol],
3818
- this.getOption("popper", {}),
4201
+ getSelectPopperPositionOptions.call(this),
3819
4202
  );
3820
4203
  setStatusOrRemoveBadges.call(this, "open");
3821
4204
 
@@ -4485,7 +4868,7 @@ function updatePopper() {
4485
4868
  this,
4486
4869
  this[controlElementSymbol],
4487
4870
  this[popperElementSymbol],
4488
- this.getOption("popper", {}),
4871
+ getSelectPopperPositionOptions.call(this),
4489
4872
  );
4490
4873
  requestAnimationFrame(() => {
4491
4874
  refreshSelectPaginationLayout.call(this);