@x-plat/design-system 0.14.11 → 0.14.13

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.
@@ -60,6 +60,7 @@ var computePlacement = (triggerRect, popW, popH, clip) => {
60
60
  const roomAbove = triggerRect.top - clip.top;
61
61
  let direction;
62
62
  let top;
63
+ let maxHeight = null;
63
64
  if (popH <= roomBelow) {
64
65
  direction = "bottom";
65
66
  top = triggerRect.bottom;
@@ -67,38 +68,48 @@ var computePlacement = (triggerRect, popW, popH, clip) => {
67
68
  direction = "top";
68
69
  top = triggerRect.top - popH;
69
70
  } else {
70
- direction = roomBelow >= roomAbove ? "bottom" : "top";
71
- top = direction === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
72
- top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
73
- top = Math.max(top, clip.top);
71
+ const room = Math.max(roomBelow, roomAbove, 0);
72
+ if (roomBelow >= roomAbove) {
73
+ direction = "bottom";
74
+ top = triggerRect.bottom;
75
+ } else {
76
+ direction = "top";
77
+ top = triggerRect.top - room;
78
+ }
79
+ maxHeight = room;
74
80
  }
75
81
  let left = triggerRect.left;
76
82
  if (left + popW > clip.right - 8) {
77
83
  left = triggerRect.right - popW;
78
84
  }
79
85
  if (left < clip.left + 8) left = clip.left + 8;
86
+ const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
80
87
  return {
81
88
  direction,
82
89
  top,
83
90
  left,
91
+ maxHeight,
84
92
  over: {
85
93
  top: Math.max(0, clip.top - top),
86
94
  right: Math.max(0, left + popW - clip.right),
87
- bottom: Math.max(0, top + popH - clip.bottom),
95
+ bottom: Math.max(0, top + drawnH - clip.bottom),
88
96
  left: Math.max(0, clip.left - left)
89
97
  }
90
98
  };
91
99
  };
92
100
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
93
- const [direction, setDirection] = import_react.default.useState("bottom");
94
101
  const directionRef = import_react.default.useRef("bottom");
95
102
  const sizeRef = import_react.default.useRef(null);
96
103
  const scrollParentRef = import_react.default.useRef(null);
104
+ const placedRef = import_react.default.useRef(false);
97
105
  const calculatePosition = import_react.default.useCallback((remeasure = false) => {
98
106
  const pop = popRef.current;
99
107
  if (!triggerRef.current || !pop) return;
100
108
  if (remeasure || !sizeRef.current) {
101
- sizeRef.current = { w: pop.offsetWidth, h: pop.offsetHeight };
109
+ sizeRef.current = {
110
+ w: pop.offsetWidth,
111
+ h: Math.max(pop.offsetHeight, pop.scrollHeight)
112
+ };
102
113
  }
103
114
  const { w: popW, h: popH } = sizeRef.current;
104
115
  const triggerRect = triggerRef.current.getBoundingClientRect();
@@ -113,7 +124,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
113
124
  left: Math.max(parentRect?.left ?? 0, 0),
114
125
  right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
115
126
  };
116
- const { direction: next, top, left, over } = computePlacement(
127
+ const first = !placedRef.current;
128
+ if (first) pop.style.transition = "none";
129
+ const { direction: next, top, left, over, maxHeight } = computePlacement(
117
130
  triggerRect,
118
131
  popW,
119
132
  popH,
@@ -121,16 +134,22 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
121
134
  );
122
135
  pop.style.top = `${top + window.scrollY}px`;
123
136
  pop.style.left = `${left + window.scrollX}px`;
137
+ pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
124
138
  pop.style.clipPath = over.top || over.right || over.bottom || over.left ? `inset(${over.top}px ${over.right}px ${over.bottom}px ${over.left}px)` : "none";
125
- if (next !== directionRef.current) {
126
- directionRef.current = next;
127
- setDirection(next);
139
+ directionRef.current = next;
140
+ pop.classList.toggle("top", next === "top");
141
+ pop.classList.toggle("bottom", next === "bottom");
142
+ if (first) {
143
+ void pop.offsetHeight;
144
+ pop.style.transition = "";
145
+ placedRef.current = true;
128
146
  }
129
147
  }, [triggerRef, popRef]);
130
148
  import_react.default.useLayoutEffect(() => {
131
149
  if (!enabled) {
132
150
  sizeRef.current = null;
133
151
  scrollParentRef.current = null;
152
+ placedRef.current = false;
134
153
  return;
135
154
  }
136
155
  if (triggerRef.current) {
@@ -159,7 +178,6 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
159
178
  window.removeEventListener("scroll", onScroll, true);
160
179
  };
161
180
  }, [calculatePosition, enabled]);
162
- return { direction };
163
181
  };
164
182
  var useAutoPosition_default = useAutoPosition;
165
183
 
@@ -254,7 +272,7 @@ var Dropdown = (props) => {
254
272
  const [visible, setVisible] = import_react4.default.useState(false);
255
273
  const triggerRef = import_react4.default.useRef(null);
256
274
  const menuRef = import_react4.default.useRef(null);
257
- const { direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
275
+ useAutoPosition_default(triggerRef, menuRef, mounted);
258
276
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
259
277
  useCloseOnContainerScroll(isOpen, menuRef, () => setIsOpen(false));
260
278
  useEscapeKey(isOpen, () => {
@@ -290,7 +308,7 @@ var Dropdown = (props) => {
290
308
  "div",
291
309
  {
292
310
  ref: menuRef,
293
- className: clsx_default("lib-xplat-dropdown-menu", direction, { visible }),
311
+ className: clsx_default("lib-xplat-dropdown-menu", { visible }),
294
312
  role: "menu",
295
313
  children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
296
314
  "button",
@@ -24,6 +24,7 @@ var computePlacement = (triggerRect, popW, popH, clip) => {
24
24
  const roomAbove = triggerRect.top - clip.top;
25
25
  let direction;
26
26
  let top;
27
+ let maxHeight = null;
27
28
  if (popH <= roomBelow) {
28
29
  direction = "bottom";
29
30
  top = triggerRect.bottom;
@@ -31,38 +32,48 @@ var computePlacement = (triggerRect, popW, popH, clip) => {
31
32
  direction = "top";
32
33
  top = triggerRect.top - popH;
33
34
  } else {
34
- direction = roomBelow >= roomAbove ? "bottom" : "top";
35
- top = direction === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
36
- top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
37
- top = Math.max(top, clip.top);
35
+ const room = Math.max(roomBelow, roomAbove, 0);
36
+ if (roomBelow >= roomAbove) {
37
+ direction = "bottom";
38
+ top = triggerRect.bottom;
39
+ } else {
40
+ direction = "top";
41
+ top = triggerRect.top - room;
42
+ }
43
+ maxHeight = room;
38
44
  }
39
45
  let left = triggerRect.left;
40
46
  if (left + popW > clip.right - 8) {
41
47
  left = triggerRect.right - popW;
42
48
  }
43
49
  if (left < clip.left + 8) left = clip.left + 8;
50
+ const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
44
51
  return {
45
52
  direction,
46
53
  top,
47
54
  left,
55
+ maxHeight,
48
56
  over: {
49
57
  top: Math.max(0, clip.top - top),
50
58
  right: Math.max(0, left + popW - clip.right),
51
- bottom: Math.max(0, top + popH - clip.bottom),
59
+ bottom: Math.max(0, top + drawnH - clip.bottom),
52
60
  left: Math.max(0, clip.left - left)
53
61
  }
54
62
  };
55
63
  };
56
64
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
57
- const [direction, setDirection] = React.useState("bottom");
58
65
  const directionRef = React.useRef("bottom");
59
66
  const sizeRef = React.useRef(null);
60
67
  const scrollParentRef = React.useRef(null);
68
+ const placedRef = React.useRef(false);
61
69
  const calculatePosition = React.useCallback((remeasure = false) => {
62
70
  const pop = popRef.current;
63
71
  if (!triggerRef.current || !pop) return;
64
72
  if (remeasure || !sizeRef.current) {
65
- sizeRef.current = { w: pop.offsetWidth, h: pop.offsetHeight };
73
+ sizeRef.current = {
74
+ w: pop.offsetWidth,
75
+ h: Math.max(pop.offsetHeight, pop.scrollHeight)
76
+ };
66
77
  }
67
78
  const { w: popW, h: popH } = sizeRef.current;
68
79
  const triggerRect = triggerRef.current.getBoundingClientRect();
@@ -77,7 +88,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
77
88
  left: Math.max(parentRect?.left ?? 0, 0),
78
89
  right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
79
90
  };
80
- const { direction: next, top, left, over } = computePlacement(
91
+ const first = !placedRef.current;
92
+ if (first) pop.style.transition = "none";
93
+ const { direction: next, top, left, over, maxHeight } = computePlacement(
81
94
  triggerRect,
82
95
  popW,
83
96
  popH,
@@ -85,16 +98,22 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
85
98
  );
86
99
  pop.style.top = `${top + window.scrollY}px`;
87
100
  pop.style.left = `${left + window.scrollX}px`;
101
+ pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
88
102
  pop.style.clipPath = over.top || over.right || over.bottom || over.left ? `inset(${over.top}px ${over.right}px ${over.bottom}px ${over.left}px)` : "none";
89
- if (next !== directionRef.current) {
90
- directionRef.current = next;
91
- setDirection(next);
103
+ directionRef.current = next;
104
+ pop.classList.toggle("top", next === "top");
105
+ pop.classList.toggle("bottom", next === "bottom");
106
+ if (first) {
107
+ void pop.offsetHeight;
108
+ pop.style.transition = "";
109
+ placedRef.current = true;
92
110
  }
93
111
  }, [triggerRef, popRef]);
94
112
  React.useLayoutEffect(() => {
95
113
  if (!enabled) {
96
114
  sizeRef.current = null;
97
115
  scrollParentRef.current = null;
116
+ placedRef.current = false;
98
117
  return;
99
118
  }
100
119
  if (triggerRef.current) {
@@ -123,7 +142,6 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
123
142
  window.removeEventListener("scroll", onScroll, true);
124
143
  };
125
144
  }, [calculatePosition, enabled]);
126
- return { direction };
127
145
  };
128
146
  var useAutoPosition_default = useAutoPosition;
129
147
 
@@ -218,7 +236,7 @@ var Dropdown = (props) => {
218
236
  const [visible, setVisible] = React4.useState(false);
219
237
  const triggerRef = React4.useRef(null);
220
238
  const menuRef = React4.useRef(null);
221
- const { direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
239
+ useAutoPosition_default(triggerRef, menuRef, mounted);
222
240
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
223
241
  useCloseOnContainerScroll(isOpen, menuRef, () => setIsOpen(false));
224
242
  useEscapeKey(isOpen, () => {
@@ -254,7 +272,7 @@ var Dropdown = (props) => {
254
272
  "div",
255
273
  {
256
274
  ref: menuRef,
257
- className: clsx_default("lib-xplat-dropdown-menu", direction, { visible }),
275
+ className: clsx_default("lib-xplat-dropdown-menu", { visible }),
258
276
  role: "menu",
259
277
  children: items.map((item) => /* @__PURE__ */ jsx(
260
278
  "button",
@@ -60,6 +60,7 @@ var computePlacement = (triggerRect, popW, popH, clip) => {
60
60
  const roomAbove = triggerRect.top - clip.top;
61
61
  let direction;
62
62
  let top;
63
+ let maxHeight = null;
63
64
  if (popH <= roomBelow) {
64
65
  direction = "bottom";
65
66
  top = triggerRect.bottom;
@@ -67,38 +68,48 @@ var computePlacement = (triggerRect, popW, popH, clip) => {
67
68
  direction = "top";
68
69
  top = triggerRect.top - popH;
69
70
  } else {
70
- direction = roomBelow >= roomAbove ? "bottom" : "top";
71
- top = direction === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
72
- top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
73
- top = Math.max(top, clip.top);
71
+ const room = Math.max(roomBelow, roomAbove, 0);
72
+ if (roomBelow >= roomAbove) {
73
+ direction = "bottom";
74
+ top = triggerRect.bottom;
75
+ } else {
76
+ direction = "top";
77
+ top = triggerRect.top - room;
78
+ }
79
+ maxHeight = room;
74
80
  }
75
81
  let left = triggerRect.left;
76
82
  if (left + popW > clip.right - 8) {
77
83
  left = triggerRect.right - popW;
78
84
  }
79
85
  if (left < clip.left + 8) left = clip.left + 8;
86
+ const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
80
87
  return {
81
88
  direction,
82
89
  top,
83
90
  left,
91
+ maxHeight,
84
92
  over: {
85
93
  top: Math.max(0, clip.top - top),
86
94
  right: Math.max(0, left + popW - clip.right),
87
- bottom: Math.max(0, top + popH - clip.bottom),
95
+ bottom: Math.max(0, top + drawnH - clip.bottom),
88
96
  left: Math.max(0, clip.left - left)
89
97
  }
90
98
  };
91
99
  };
92
100
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
93
- const [direction, setDirection] = import_react.default.useState("bottom");
94
101
  const directionRef = import_react.default.useRef("bottom");
95
102
  const sizeRef = import_react.default.useRef(null);
96
103
  const scrollParentRef = import_react.default.useRef(null);
104
+ const placedRef = import_react.default.useRef(false);
97
105
  const calculatePosition = import_react.default.useCallback((remeasure = false) => {
98
106
  const pop = popRef.current;
99
107
  if (!triggerRef.current || !pop) return;
100
108
  if (remeasure || !sizeRef.current) {
101
- sizeRef.current = { w: pop.offsetWidth, h: pop.offsetHeight };
109
+ sizeRef.current = {
110
+ w: pop.offsetWidth,
111
+ h: Math.max(pop.offsetHeight, pop.scrollHeight)
112
+ };
102
113
  }
103
114
  const { w: popW, h: popH } = sizeRef.current;
104
115
  const triggerRect = triggerRef.current.getBoundingClientRect();
@@ -113,7 +124,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
113
124
  left: Math.max(parentRect?.left ?? 0, 0),
114
125
  right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
115
126
  };
116
- const { direction: next, top, left, over } = computePlacement(
127
+ const first = !placedRef.current;
128
+ if (first) pop.style.transition = "none";
129
+ const { direction: next, top, left, over, maxHeight } = computePlacement(
117
130
  triggerRect,
118
131
  popW,
119
132
  popH,
@@ -121,16 +134,22 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
121
134
  );
122
135
  pop.style.top = `${top + window.scrollY}px`;
123
136
  pop.style.left = `${left + window.scrollX}px`;
137
+ pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
124
138
  pop.style.clipPath = over.top || over.right || over.bottom || over.left ? `inset(${over.top}px ${over.right}px ${over.bottom}px ${over.left}px)` : "none";
125
- if (next !== directionRef.current) {
126
- directionRef.current = next;
127
- setDirection(next);
139
+ directionRef.current = next;
140
+ pop.classList.toggle("top", next === "top");
141
+ pop.classList.toggle("bottom", next === "bottom");
142
+ if (first) {
143
+ void pop.offsetHeight;
144
+ pop.style.transition = "";
145
+ placedRef.current = true;
128
146
  }
129
147
  }, [triggerRef, popRef]);
130
148
  import_react.default.useLayoutEffect(() => {
131
149
  if (!enabled) {
132
150
  sizeRef.current = null;
133
151
  scrollParentRef.current = null;
152
+ placedRef.current = false;
134
153
  return;
135
154
  }
136
155
  if (triggerRef.current) {
@@ -159,7 +178,6 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
159
178
  window.removeEventListener("scroll", onScroll, true);
160
179
  };
161
180
  }, [calculatePosition, enabled]);
162
- return { direction };
163
181
  };
164
182
  var useAutoPosition_default = useAutoPosition;
165
183
 
@@ -259,7 +277,7 @@ var PopOver = (props) => {
259
277
  onClose();
260
278
  triggerRef.current?.focus({ preventScroll: true });
261
279
  });
262
- const position = useAutoPosition_default(triggerRef, popRef, localOpen);
280
+ useAutoPosition_default(triggerRef, popRef, localOpen);
263
281
  import_react4.default.useEffect(() => {
264
282
  if (isOpen) {
265
283
  setLocalOpen(isOpen);
@@ -288,7 +306,6 @@ var PopOver = (props) => {
288
306
  {
289
307
  className: clsx_default(
290
308
  "lib-xplat-pop-over-content",
291
- position.direction,
292
309
  eventTrigger && "visible"
293
310
  ),
294
311
  ref: popRef,
@@ -24,6 +24,7 @@ var computePlacement = (triggerRect, popW, popH, clip) => {
24
24
  const roomAbove = triggerRect.top - clip.top;
25
25
  let direction;
26
26
  let top;
27
+ let maxHeight = null;
27
28
  if (popH <= roomBelow) {
28
29
  direction = "bottom";
29
30
  top = triggerRect.bottom;
@@ -31,38 +32,48 @@ var computePlacement = (triggerRect, popW, popH, clip) => {
31
32
  direction = "top";
32
33
  top = triggerRect.top - popH;
33
34
  } else {
34
- direction = roomBelow >= roomAbove ? "bottom" : "top";
35
- top = direction === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
36
- top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
37
- top = Math.max(top, clip.top);
35
+ const room = Math.max(roomBelow, roomAbove, 0);
36
+ if (roomBelow >= roomAbove) {
37
+ direction = "bottom";
38
+ top = triggerRect.bottom;
39
+ } else {
40
+ direction = "top";
41
+ top = triggerRect.top - room;
42
+ }
43
+ maxHeight = room;
38
44
  }
39
45
  let left = triggerRect.left;
40
46
  if (left + popW > clip.right - 8) {
41
47
  left = triggerRect.right - popW;
42
48
  }
43
49
  if (left < clip.left + 8) left = clip.left + 8;
50
+ const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
44
51
  return {
45
52
  direction,
46
53
  top,
47
54
  left,
55
+ maxHeight,
48
56
  over: {
49
57
  top: Math.max(0, clip.top - top),
50
58
  right: Math.max(0, left + popW - clip.right),
51
- bottom: Math.max(0, top + popH - clip.bottom),
59
+ bottom: Math.max(0, top + drawnH - clip.bottom),
52
60
  left: Math.max(0, clip.left - left)
53
61
  }
54
62
  };
55
63
  };
56
64
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
57
- const [direction, setDirection] = React.useState("bottom");
58
65
  const directionRef = React.useRef("bottom");
59
66
  const sizeRef = React.useRef(null);
60
67
  const scrollParentRef = React.useRef(null);
68
+ const placedRef = React.useRef(false);
61
69
  const calculatePosition = React.useCallback((remeasure = false) => {
62
70
  const pop = popRef.current;
63
71
  if (!triggerRef.current || !pop) return;
64
72
  if (remeasure || !sizeRef.current) {
65
- sizeRef.current = { w: pop.offsetWidth, h: pop.offsetHeight };
73
+ sizeRef.current = {
74
+ w: pop.offsetWidth,
75
+ h: Math.max(pop.offsetHeight, pop.scrollHeight)
76
+ };
66
77
  }
67
78
  const { w: popW, h: popH } = sizeRef.current;
68
79
  const triggerRect = triggerRef.current.getBoundingClientRect();
@@ -77,7 +88,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
77
88
  left: Math.max(parentRect?.left ?? 0, 0),
78
89
  right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
79
90
  };
80
- const { direction: next, top, left, over } = computePlacement(
91
+ const first = !placedRef.current;
92
+ if (first) pop.style.transition = "none";
93
+ const { direction: next, top, left, over, maxHeight } = computePlacement(
81
94
  triggerRect,
82
95
  popW,
83
96
  popH,
@@ -85,16 +98,22 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
85
98
  );
86
99
  pop.style.top = `${top + window.scrollY}px`;
87
100
  pop.style.left = `${left + window.scrollX}px`;
101
+ pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
88
102
  pop.style.clipPath = over.top || over.right || over.bottom || over.left ? `inset(${over.top}px ${over.right}px ${over.bottom}px ${over.left}px)` : "none";
89
- if (next !== directionRef.current) {
90
- directionRef.current = next;
91
- setDirection(next);
103
+ directionRef.current = next;
104
+ pop.classList.toggle("top", next === "top");
105
+ pop.classList.toggle("bottom", next === "bottom");
106
+ if (first) {
107
+ void pop.offsetHeight;
108
+ pop.style.transition = "";
109
+ placedRef.current = true;
92
110
  }
93
111
  }, [triggerRef, popRef]);
94
112
  React.useLayoutEffect(() => {
95
113
  if (!enabled) {
96
114
  sizeRef.current = null;
97
115
  scrollParentRef.current = null;
116
+ placedRef.current = false;
98
117
  return;
99
118
  }
100
119
  if (triggerRef.current) {
@@ -123,7 +142,6 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
123
142
  window.removeEventListener("scroll", onScroll, true);
124
143
  };
125
144
  }, [calculatePosition, enabled]);
126
- return { direction };
127
145
  };
128
146
  var useAutoPosition_default = useAutoPosition;
129
147
 
@@ -223,7 +241,7 @@ var PopOver = (props) => {
223
241
  onClose();
224
242
  triggerRef.current?.focus({ preventScroll: true });
225
243
  });
226
- const position = useAutoPosition_default(triggerRef, popRef, localOpen);
244
+ useAutoPosition_default(triggerRef, popRef, localOpen);
227
245
  React4.useEffect(() => {
228
246
  if (isOpen) {
229
247
  setLocalOpen(isOpen);
@@ -252,7 +270,6 @@ var PopOver = (props) => {
252
270
  {
253
271
  className: clsx_default(
254
272
  "lib-xplat-pop-over-content",
255
- position.direction,
256
273
  eventTrigger && "visible"
257
274
  ),
258
275
  ref: popRef,
@@ -61,6 +61,7 @@ var computePlacement = (triggerRect, popW, popH, clip) => {
61
61
  const roomAbove = triggerRect.top - clip.top;
62
62
  let direction;
63
63
  let top;
64
+ let maxHeight = null;
64
65
  if (popH <= roomBelow) {
65
66
  direction = "bottom";
66
67
  top = triggerRect.bottom;
@@ -68,38 +69,48 @@ var computePlacement = (triggerRect, popW, popH, clip) => {
68
69
  direction = "top";
69
70
  top = triggerRect.top - popH;
70
71
  } else {
71
- direction = roomBelow >= roomAbove ? "bottom" : "top";
72
- top = direction === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
73
- top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
74
- top = Math.max(top, clip.top);
72
+ const room = Math.max(roomBelow, roomAbove, 0);
73
+ if (roomBelow >= roomAbove) {
74
+ direction = "bottom";
75
+ top = triggerRect.bottom;
76
+ } else {
77
+ direction = "top";
78
+ top = triggerRect.top - room;
79
+ }
80
+ maxHeight = room;
75
81
  }
76
82
  let left = triggerRect.left;
77
83
  if (left + popW > clip.right - 8) {
78
84
  left = triggerRect.right - popW;
79
85
  }
80
86
  if (left < clip.left + 8) left = clip.left + 8;
87
+ const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
81
88
  return {
82
89
  direction,
83
90
  top,
84
91
  left,
92
+ maxHeight,
85
93
  over: {
86
94
  top: Math.max(0, clip.top - top),
87
95
  right: Math.max(0, left + popW - clip.right),
88
- bottom: Math.max(0, top + popH - clip.bottom),
96
+ bottom: Math.max(0, top + drawnH - clip.bottom),
89
97
  left: Math.max(0, clip.left - left)
90
98
  }
91
99
  };
92
100
  };
93
101
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
94
- const [direction, setDirection] = import_react.default.useState("bottom");
95
102
  const directionRef = import_react.default.useRef("bottom");
96
103
  const sizeRef = import_react.default.useRef(null);
97
104
  const scrollParentRef = import_react.default.useRef(null);
105
+ const placedRef = import_react.default.useRef(false);
98
106
  const calculatePosition = import_react.default.useCallback((remeasure = false) => {
99
107
  const pop = popRef.current;
100
108
  if (!triggerRef.current || !pop) return;
101
109
  if (remeasure || !sizeRef.current) {
102
- sizeRef.current = { w: pop.offsetWidth, h: pop.offsetHeight };
110
+ sizeRef.current = {
111
+ w: pop.offsetWidth,
112
+ h: Math.max(pop.offsetHeight, pop.scrollHeight)
113
+ };
103
114
  }
104
115
  const { w: popW, h: popH } = sizeRef.current;
105
116
  const triggerRect = triggerRef.current.getBoundingClientRect();
@@ -114,7 +125,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
114
125
  left: Math.max(parentRect?.left ?? 0, 0),
115
126
  right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
116
127
  };
117
- const { direction: next, top, left, over } = computePlacement(
128
+ const first = !placedRef.current;
129
+ if (first) pop.style.transition = "none";
130
+ const { direction: next, top, left, over, maxHeight } = computePlacement(
118
131
  triggerRect,
119
132
  popW,
120
133
  popH,
@@ -122,16 +135,22 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
122
135
  );
123
136
  pop.style.top = `${top + window.scrollY}px`;
124
137
  pop.style.left = `${left + window.scrollX}px`;
138
+ pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
125
139
  pop.style.clipPath = over.top || over.right || over.bottom || over.left ? `inset(${over.top}px ${over.right}px ${over.bottom}px ${over.left}px)` : "none";
126
- if (next !== directionRef.current) {
127
- directionRef.current = next;
128
- setDirection(next);
140
+ directionRef.current = next;
141
+ pop.classList.toggle("top", next === "top");
142
+ pop.classList.toggle("bottom", next === "bottom");
143
+ if (first) {
144
+ void pop.offsetHeight;
145
+ pop.style.transition = "";
146
+ placedRef.current = true;
129
147
  }
130
148
  }, [triggerRef, popRef]);
131
149
  import_react.default.useLayoutEffect(() => {
132
150
  if (!enabled) {
133
151
  sizeRef.current = null;
134
152
  scrollParentRef.current = null;
153
+ placedRef.current = false;
135
154
  return;
136
155
  }
137
156
  if (triggerRef.current) {
@@ -160,7 +179,6 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
160
179
  window.removeEventListener("scroll", onScroll, true);
161
180
  };
162
181
  }, [calculatePosition, enabled]);
163
- return { direction };
164
182
  };
165
183
  var useAutoPosition_default = useAutoPosition;
166
184
 
@@ -1390,7 +1408,7 @@ var SelectRoot = (props) => {
1390
1408
  close();
1391
1409
  triggerRef.current?.focus({ preventScroll: true });
1392
1410
  });
1393
- const position = useAutoPosition_default(triggerRef, contentRef, mounted);
1411
+ useAutoPosition_default(triggerRef, contentRef, mounted);
1394
1412
  const setSelected = import_react6.default.useCallback(
1395
1413
  (label2, itemValue) => {
1396
1414
  if (!isControlled) {
@@ -1483,7 +1501,7 @@ var SelectRoot = (props) => {
1483
1501
  mounted && /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime297.jsxs)(
1484
1502
  "div",
1485
1503
  {
1486
- className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
1504
+ className: clsx_default("lib-xplat-select-content", size, stateClass),
1487
1505
  ref: contentRef,
1488
1506
  style: { width: triggerRef.current?.offsetWidth },
1489
1507
  role: "listbox",
@@ -212,7 +212,7 @@
212
212
  transition: transform 0.2s ease, opacity 0.2s ease;
213
213
  }
214
214
  .lib-xplat-select-content.bottom {
215
- transform: translateY(-8px);
215
+ transform: translateY(8px);
216
216
  }
217
217
  .lib-xplat-select-content.bottom.visible {
218
218
  opacity: 1;
@@ -220,10 +220,12 @@
220
220
  }
221
221
  .lib-xplat-select-content.bottom.exit {
222
222
  opacity: 0;
223
- transform: translateY(-8px);
223
+ transform: translateY(8px);
224
+ }
225
+ .lib-xplat-select-content {
224
226
  }
225
227
  .lib-xplat-select-content.top {
226
- transform: translateY(8px);
228
+ transform: translateY(-8px);
227
229
  }
228
230
  .lib-xplat-select-content.top.visible {
229
231
  opacity: 1;
@@ -231,7 +233,7 @@
231
233
  }
232
234
  .lib-xplat-select-content.top.exit {
233
235
  opacity: 0;
234
- transform: translateY(8px);
236
+ transform: translateY(-8px);
235
237
  }
236
238
  .lib-xplat-select-content.sm .select-item {
237
239
  padding: var(--spacing-space-2) var(--spacing-space-2);