@x-plat/design-system 0.14.18 → 0.15.0

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.
@@ -35,13 +35,13 @@ __export(Dropdown_exports, {
35
35
  module.exports = __toCommonJS(Dropdown_exports);
36
36
 
37
37
  // src/components/Dropdown/Dropdown.tsx
38
- var import_react4 = __toESM(require("react"), 1);
38
+ var import_react5 = __toESM(require("react"), 1);
39
39
 
40
40
  // src/tokens/hooks/Portal.tsx
41
41
  var import_react_dom = __toESM(require("react-dom"), 1);
42
- var Portal = ({ children }) => {
42
+ var Portal = ({ children, container }) => {
43
43
  if (typeof document === "undefined") return null;
44
- return import_react_dom.default.createPortal(children, document.body);
44
+ return import_react_dom.default.createPortal(children, container ?? document.body);
45
45
  };
46
46
  Portal.displayName = "Portal";
47
47
  var Portal_default = Portal;
@@ -104,10 +104,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
104
104
  const scrollParentRef = import_react.default.useRef(null);
105
105
  const placedRef = import_react.default.useRef(false);
106
106
  const frozenMaxRef = import_react.default.useRef(void 0);
107
+ const cssCapRef = import_react.default.useRef(void 0);
107
108
  const calculatePosition = import_react.default.useCallback((remeasure = false) => {
108
109
  const pop = popRef.current;
109
110
  if (!triggerRef.current || !pop) return;
110
111
  if (remeasure) frozenMaxRef.current = void 0;
112
+ if (cssCapRef.current === void 0) {
113
+ pop.style.maxHeight = "";
114
+ const raw = getComputedStyle(pop).maxHeight;
115
+ cssCapRef.current = raw === "none" ? null : Number.parseFloat(raw) || null;
116
+ }
111
117
  if (remeasure || !sizeRef.current) {
112
118
  sizeRef.current = {
113
119
  w: pop.offsetWidth,
@@ -129,8 +135,10 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
129
135
  };
130
136
  const first = !placedRef.current;
131
137
  if (first) pop.style.transition = "none";
138
+ const cap = cssCapRef.current;
139
+ const desiredH = cap == null ? popH : Math.min(popH, cap);
132
140
  const frozen = frozenMaxRef.current;
133
- const effectiveH = frozen == null ? popH : Math.min(popH, frozen);
141
+ const effectiveH = frozen == null ? desiredH : Math.min(desiredH, frozen);
134
142
  const { direction: next, top, left, over, maxHeight: suggested } = computePlacement(
135
143
  triggerRect,
136
144
  popW,
@@ -139,8 +147,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
139
147
  );
140
148
  if (frozenMaxRef.current === void 0) frozenMaxRef.current = suggested;
141
149
  const maxHeight = frozenMaxRef.current;
142
- pop.style.top = `${top + window.scrollY}px`;
143
- pop.style.left = `${left + window.scrollX}px`;
150
+ const hostRect = (pop.offsetParent ?? pop.parentElement)?.getBoundingClientRect();
151
+ pop.style.top = `${top - (hostRect?.top ?? 0)}px`;
152
+ pop.style.left = `${left - (hostRect?.left ?? 0)}px`;
144
153
  pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
145
154
  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";
146
155
  directionRef.current = next;
@@ -158,6 +167,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
158
167
  scrollParentRef.current = null;
159
168
  placedRef.current = false;
160
169
  frozenMaxRef.current = void 0;
170
+ cssCapRef.current = void 0;
161
171
  return;
162
172
  }
163
173
  if (triggerRef.current) {
@@ -214,8 +224,34 @@ var useClickOutside = (refs, handler, enabled = true) => {
214
224
  };
215
225
  var useClickOutside_default = useClickOutside;
216
226
 
217
- // src/tokens/hooks/useOverlayKeyboard.ts
227
+ // src/tokens/hooks/useOverlayHost.ts
218
228
  var import_react3 = __toESM(require("react"), 1);
229
+ var useOverlayHost = (triggerRef, enabled) => {
230
+ const [host, setHost] = import_react3.default.useState(null);
231
+ import_react3.default.useLayoutEffect(() => {
232
+ if (!enabled || !triggerRef.current) {
233
+ setHost(null);
234
+ return;
235
+ }
236
+ const el = document.createElement("div");
237
+ el.dataset.xplatOverlayHost = "";
238
+ el.style.position = "relative";
239
+ el.style.width = "0";
240
+ el.style.height = "0";
241
+ const parent = findScrollParent(triggerRef.current) ?? document.body;
242
+ parent.appendChild(el);
243
+ setHost(el);
244
+ return () => {
245
+ el.remove();
246
+ setHost(null);
247
+ };
248
+ }, [enabled, triggerRef]);
249
+ return host;
250
+ };
251
+ var useOverlayHost_default = useOverlayHost;
252
+
253
+ // src/tokens/hooks/useOverlayKeyboard.ts
254
+ var import_react4 = __toESM(require("react"), 1);
219
255
  var FOCUSABLE = [
220
256
  "a[href]",
221
257
  "button:not([disabled])",
@@ -225,7 +261,7 @@ var FOCUSABLE = [
225
261
  "[tabindex]:not([tabindex='-1'])"
226
262
  ].join(",");
227
263
  var useEscapeKey = (enabled, onEscape) => {
228
- import_react3.default.useEffect(() => {
264
+ import_react4.default.useEffect(() => {
229
265
  if (!enabled) return;
230
266
  const onKey = (e) => {
231
267
  if (e.key !== "Escape") return;
@@ -238,9 +274,9 @@ var useEscapeKey = (enabled, onEscape) => {
238
274
  }, [enabled, onEscape]);
239
275
  };
240
276
  var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
241
- const onCloseRef = import_react3.default.useRef(onClose);
277
+ const onCloseRef = import_react4.default.useRef(onClose);
242
278
  onCloseRef.current = onClose;
243
- import_react3.default.useEffect(() => {
279
+ import_react4.default.useEffect(() => {
244
280
  const trigger = triggerRef.current;
245
281
  if (!enabled || !trigger) return;
246
282
  const observer = new IntersectionObserver(
@@ -278,11 +314,12 @@ var clsx_default = clsx;
278
314
  var import_jsx_runtime = require("react/jsx-runtime");
279
315
  var Dropdown = (props) => {
280
316
  const { items, children } = props;
281
- const [isOpen, setIsOpen] = import_react4.default.useState(false);
282
- const [mounted, setMounted] = import_react4.default.useState(false);
283
- const [visible, setVisible] = import_react4.default.useState(false);
284
- const triggerRef = import_react4.default.useRef(null);
285
- const menuRef = import_react4.default.useRef(null);
317
+ const [isOpen, setIsOpen] = import_react5.default.useState(false);
318
+ const [mounted, setMounted] = import_react5.default.useState(false);
319
+ const [visible, setVisible] = import_react5.default.useState(false);
320
+ const triggerRef = import_react5.default.useRef(null);
321
+ const menuRef = import_react5.default.useRef(null);
322
+ const host = useOverlayHost_default(triggerRef, mounted);
286
323
  useAutoPosition_default(triggerRef, menuRef, mounted);
287
324
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
288
325
  useCloseWhenFocusHidden(isOpen, triggerRef, menuRef, () => setIsOpen(false));
@@ -290,7 +327,7 @@ var Dropdown = (props) => {
290
327
  setIsOpen(false);
291
328
  triggerRef.current?.focus({ preventScroll: true });
292
329
  });
293
- import_react4.default.useEffect(() => {
330
+ import_react5.default.useEffect(() => {
294
331
  if (isOpen) {
295
332
  setMounted(true);
296
333
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -315,7 +352,7 @@ var Dropdown = (props) => {
315
352
  children
316
353
  }
317
354
  ),
318
- mounted && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
355
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Portal_default, { container: host, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
319
356
  "div",
320
357
  {
321
358
  ref: menuRef,
@@ -1,11 +1,11 @@
1
1
  // src/components/Dropdown/Dropdown.tsx
2
- import React4 from "react";
2
+ import React5 from "react";
3
3
 
4
4
  // src/tokens/hooks/Portal.tsx
5
5
  import ReactDOM from "react-dom";
6
- var Portal = ({ children }) => {
6
+ var Portal = ({ children, container }) => {
7
7
  if (typeof document === "undefined") return null;
8
- return ReactDOM.createPortal(children, document.body);
8
+ return ReactDOM.createPortal(children, container ?? document.body);
9
9
  };
10
10
  Portal.displayName = "Portal";
11
11
  var Portal_default = Portal;
@@ -68,10 +68,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
68
68
  const scrollParentRef = React.useRef(null);
69
69
  const placedRef = React.useRef(false);
70
70
  const frozenMaxRef = React.useRef(void 0);
71
+ const cssCapRef = React.useRef(void 0);
71
72
  const calculatePosition = React.useCallback((remeasure = false) => {
72
73
  const pop = popRef.current;
73
74
  if (!triggerRef.current || !pop) return;
74
75
  if (remeasure) frozenMaxRef.current = void 0;
76
+ if (cssCapRef.current === void 0) {
77
+ pop.style.maxHeight = "";
78
+ const raw = getComputedStyle(pop).maxHeight;
79
+ cssCapRef.current = raw === "none" ? null : Number.parseFloat(raw) || null;
80
+ }
75
81
  if (remeasure || !sizeRef.current) {
76
82
  sizeRef.current = {
77
83
  w: pop.offsetWidth,
@@ -93,8 +99,10 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
93
99
  };
94
100
  const first = !placedRef.current;
95
101
  if (first) pop.style.transition = "none";
102
+ const cap = cssCapRef.current;
103
+ const desiredH = cap == null ? popH : Math.min(popH, cap);
96
104
  const frozen = frozenMaxRef.current;
97
- const effectiveH = frozen == null ? popH : Math.min(popH, frozen);
105
+ const effectiveH = frozen == null ? desiredH : Math.min(desiredH, frozen);
98
106
  const { direction: next, top, left, over, maxHeight: suggested } = computePlacement(
99
107
  triggerRect,
100
108
  popW,
@@ -103,8 +111,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
103
111
  );
104
112
  if (frozenMaxRef.current === void 0) frozenMaxRef.current = suggested;
105
113
  const maxHeight = frozenMaxRef.current;
106
- pop.style.top = `${top + window.scrollY}px`;
107
- pop.style.left = `${left + window.scrollX}px`;
114
+ const hostRect = (pop.offsetParent ?? pop.parentElement)?.getBoundingClientRect();
115
+ pop.style.top = `${top - (hostRect?.top ?? 0)}px`;
116
+ pop.style.left = `${left - (hostRect?.left ?? 0)}px`;
108
117
  pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
109
118
  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";
110
119
  directionRef.current = next;
@@ -122,6 +131,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
122
131
  scrollParentRef.current = null;
123
132
  placedRef.current = false;
124
133
  frozenMaxRef.current = void 0;
134
+ cssCapRef.current = void 0;
125
135
  return;
126
136
  }
127
137
  if (triggerRef.current) {
@@ -178,8 +188,34 @@ var useClickOutside = (refs, handler, enabled = true) => {
178
188
  };
179
189
  var useClickOutside_default = useClickOutside;
180
190
 
181
- // src/tokens/hooks/useOverlayKeyboard.ts
191
+ // src/tokens/hooks/useOverlayHost.ts
182
192
  import React3 from "react";
193
+ var useOverlayHost = (triggerRef, enabled) => {
194
+ const [host, setHost] = React3.useState(null);
195
+ React3.useLayoutEffect(() => {
196
+ if (!enabled || !triggerRef.current) {
197
+ setHost(null);
198
+ return;
199
+ }
200
+ const el = document.createElement("div");
201
+ el.dataset.xplatOverlayHost = "";
202
+ el.style.position = "relative";
203
+ el.style.width = "0";
204
+ el.style.height = "0";
205
+ const parent = findScrollParent(triggerRef.current) ?? document.body;
206
+ parent.appendChild(el);
207
+ setHost(el);
208
+ return () => {
209
+ el.remove();
210
+ setHost(null);
211
+ };
212
+ }, [enabled, triggerRef]);
213
+ return host;
214
+ };
215
+ var useOverlayHost_default = useOverlayHost;
216
+
217
+ // src/tokens/hooks/useOverlayKeyboard.ts
218
+ import React4 from "react";
183
219
  var FOCUSABLE = [
184
220
  "a[href]",
185
221
  "button:not([disabled])",
@@ -189,7 +225,7 @@ var FOCUSABLE = [
189
225
  "[tabindex]:not([tabindex='-1'])"
190
226
  ].join(",");
191
227
  var useEscapeKey = (enabled, onEscape) => {
192
- React3.useEffect(() => {
228
+ React4.useEffect(() => {
193
229
  if (!enabled) return;
194
230
  const onKey = (e) => {
195
231
  if (e.key !== "Escape") return;
@@ -202,9 +238,9 @@ var useEscapeKey = (enabled, onEscape) => {
202
238
  }, [enabled, onEscape]);
203
239
  };
204
240
  var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
205
- const onCloseRef = React3.useRef(onClose);
241
+ const onCloseRef = React4.useRef(onClose);
206
242
  onCloseRef.current = onClose;
207
- React3.useEffect(() => {
243
+ React4.useEffect(() => {
208
244
  const trigger = triggerRef.current;
209
245
  if (!enabled || !trigger) return;
210
246
  const observer = new IntersectionObserver(
@@ -242,11 +278,12 @@ var clsx_default = clsx;
242
278
  import { jsx, jsxs } from "react/jsx-runtime";
243
279
  var Dropdown = (props) => {
244
280
  const { items, children } = props;
245
- const [isOpen, setIsOpen] = React4.useState(false);
246
- const [mounted, setMounted] = React4.useState(false);
247
- const [visible, setVisible] = React4.useState(false);
248
- const triggerRef = React4.useRef(null);
249
- const menuRef = React4.useRef(null);
281
+ const [isOpen, setIsOpen] = React5.useState(false);
282
+ const [mounted, setMounted] = React5.useState(false);
283
+ const [visible, setVisible] = React5.useState(false);
284
+ const triggerRef = React5.useRef(null);
285
+ const menuRef = React5.useRef(null);
286
+ const host = useOverlayHost_default(triggerRef, mounted);
250
287
  useAutoPosition_default(triggerRef, menuRef, mounted);
251
288
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
252
289
  useCloseWhenFocusHidden(isOpen, triggerRef, menuRef, () => setIsOpen(false));
@@ -254,7 +291,7 @@ var Dropdown = (props) => {
254
291
  setIsOpen(false);
255
292
  triggerRef.current?.focus({ preventScroll: true });
256
293
  });
257
- React4.useEffect(() => {
294
+ React5.useEffect(() => {
258
295
  if (isOpen) {
259
296
  setMounted(true);
260
297
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -279,7 +316,7 @@ var Dropdown = (props) => {
279
316
  children
280
317
  }
281
318
  ),
282
- mounted && /* @__PURE__ */ jsx(Portal_default, { children: /* @__PURE__ */ jsx(
319
+ mounted && /* @__PURE__ */ jsx(Portal_default, { container: host, children: /* @__PURE__ */ jsx(
283
320
  "div",
284
321
  {
285
322
  ref: menuRef,
@@ -35,13 +35,13 @@ __export(PopOver_exports, {
35
35
  module.exports = __toCommonJS(PopOver_exports);
36
36
 
37
37
  // src/components/PopOver/PopOver.tsx
38
- var import_react4 = __toESM(require("react"), 1);
38
+ var import_react5 = __toESM(require("react"), 1);
39
39
 
40
40
  // src/tokens/hooks/Portal.tsx
41
41
  var import_react_dom = __toESM(require("react-dom"), 1);
42
- var Portal = ({ children }) => {
42
+ var Portal = ({ children, container }) => {
43
43
  if (typeof document === "undefined") return null;
44
- return import_react_dom.default.createPortal(children, document.body);
44
+ return import_react_dom.default.createPortal(children, container ?? document.body);
45
45
  };
46
46
  Portal.displayName = "Portal";
47
47
  var Portal_default = Portal;
@@ -104,10 +104,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
104
104
  const scrollParentRef = import_react.default.useRef(null);
105
105
  const placedRef = import_react.default.useRef(false);
106
106
  const frozenMaxRef = import_react.default.useRef(void 0);
107
+ const cssCapRef = import_react.default.useRef(void 0);
107
108
  const calculatePosition = import_react.default.useCallback((remeasure = false) => {
108
109
  const pop = popRef.current;
109
110
  if (!triggerRef.current || !pop) return;
110
111
  if (remeasure) frozenMaxRef.current = void 0;
112
+ if (cssCapRef.current === void 0) {
113
+ pop.style.maxHeight = "";
114
+ const raw = getComputedStyle(pop).maxHeight;
115
+ cssCapRef.current = raw === "none" ? null : Number.parseFloat(raw) || null;
116
+ }
111
117
  if (remeasure || !sizeRef.current) {
112
118
  sizeRef.current = {
113
119
  w: pop.offsetWidth,
@@ -129,8 +135,10 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
129
135
  };
130
136
  const first = !placedRef.current;
131
137
  if (first) pop.style.transition = "none";
138
+ const cap = cssCapRef.current;
139
+ const desiredH = cap == null ? popH : Math.min(popH, cap);
132
140
  const frozen = frozenMaxRef.current;
133
- const effectiveH = frozen == null ? popH : Math.min(popH, frozen);
141
+ const effectiveH = frozen == null ? desiredH : Math.min(desiredH, frozen);
134
142
  const { direction: next, top, left, over, maxHeight: suggested } = computePlacement(
135
143
  triggerRect,
136
144
  popW,
@@ -139,8 +147,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
139
147
  );
140
148
  if (frozenMaxRef.current === void 0) frozenMaxRef.current = suggested;
141
149
  const maxHeight = frozenMaxRef.current;
142
- pop.style.top = `${top + window.scrollY}px`;
143
- pop.style.left = `${left + window.scrollX}px`;
150
+ const hostRect = (pop.offsetParent ?? pop.parentElement)?.getBoundingClientRect();
151
+ pop.style.top = `${top - (hostRect?.top ?? 0)}px`;
152
+ pop.style.left = `${left - (hostRect?.left ?? 0)}px`;
144
153
  pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
145
154
  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";
146
155
  directionRef.current = next;
@@ -158,6 +167,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
158
167
  scrollParentRef.current = null;
159
168
  placedRef.current = false;
160
169
  frozenMaxRef.current = void 0;
170
+ cssCapRef.current = void 0;
161
171
  return;
162
172
  }
163
173
  if (triggerRef.current) {
@@ -214,8 +224,34 @@ var useClickOutside = (refs, handler, enabled = true) => {
214
224
  };
215
225
  var useClickOutside_default = useClickOutside;
216
226
 
217
- // src/tokens/hooks/useOverlayKeyboard.ts
227
+ // src/tokens/hooks/useOverlayHost.ts
218
228
  var import_react3 = __toESM(require("react"), 1);
229
+ var useOverlayHost = (triggerRef, enabled) => {
230
+ const [host, setHost] = import_react3.default.useState(null);
231
+ import_react3.default.useLayoutEffect(() => {
232
+ if (!enabled || !triggerRef.current) {
233
+ setHost(null);
234
+ return;
235
+ }
236
+ const el = document.createElement("div");
237
+ el.dataset.xplatOverlayHost = "";
238
+ el.style.position = "relative";
239
+ el.style.width = "0";
240
+ el.style.height = "0";
241
+ const parent = findScrollParent(triggerRef.current) ?? document.body;
242
+ parent.appendChild(el);
243
+ setHost(el);
244
+ return () => {
245
+ el.remove();
246
+ setHost(null);
247
+ };
248
+ }, [enabled, triggerRef]);
249
+ return host;
250
+ };
251
+ var useOverlayHost_default = useOverlayHost;
252
+
253
+ // src/tokens/hooks/useOverlayKeyboard.ts
254
+ var import_react4 = __toESM(require("react"), 1);
219
255
  var FOCUSABLE = [
220
256
  "a[href]",
221
257
  "button:not([disabled])",
@@ -225,7 +261,7 @@ var FOCUSABLE = [
225
261
  "[tabindex]:not([tabindex='-1'])"
226
262
  ].join(",");
227
263
  var useEscapeKey = (enabled, onEscape) => {
228
- import_react3.default.useEffect(() => {
264
+ import_react4.default.useEffect(() => {
229
265
  if (!enabled) return;
230
266
  const onKey = (e) => {
231
267
  if (e.key !== "Escape") return;
@@ -238,9 +274,9 @@ var useEscapeKey = (enabled, onEscape) => {
238
274
  }, [enabled, onEscape]);
239
275
  };
240
276
  var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
241
- const onCloseRef = import_react3.default.useRef(onClose);
277
+ const onCloseRef = import_react4.default.useRef(onClose);
242
278
  onCloseRef.current = onClose;
243
- import_react3.default.useEffect(() => {
279
+ import_react4.default.useEffect(() => {
244
280
  const trigger = triggerRef.current;
245
281
  if (!enabled || !trigger) return;
246
282
  const observer = new IntersectionObserver(
@@ -278,18 +314,19 @@ var clsx_default = clsx;
278
314
  var import_jsx_runtime = require("react/jsx-runtime");
279
315
  var PopOver = (props) => {
280
316
  const { children, isOpen, onClose, PopOverEl } = props;
281
- const popRef = import_react4.default.useRef(null);
282
- const triggerRef = import_react4.default.useRef(null);
283
- const [localOpen, setLocalOpen] = import_react4.default.useState(false);
284
- const [eventTrigger, setEventTrigger] = import_react4.default.useState(false);
317
+ const popRef = import_react5.default.useRef(null);
318
+ const triggerRef = import_react5.default.useRef(null);
319
+ const [localOpen, setLocalOpen] = import_react5.default.useState(false);
320
+ const [eventTrigger, setEventTrigger] = import_react5.default.useState(false);
285
321
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
286
322
  useCloseWhenFocusHidden(isOpen, triggerRef, popRef, onClose);
287
323
  useEscapeKey(isOpen, () => {
288
324
  onClose();
289
325
  triggerRef.current?.focus({ preventScroll: true });
290
326
  });
327
+ const host = useOverlayHost_default(triggerRef, localOpen);
291
328
  useAutoPosition_default(triggerRef, popRef, localOpen);
292
- import_react4.default.useEffect(() => {
329
+ import_react5.default.useEffect(() => {
293
330
  if (isOpen) {
294
331
  setLocalOpen(isOpen);
295
332
  setTimeout(() => {
@@ -312,7 +349,7 @@ var PopOver = (props) => {
312
349
  },
313
350
  children: [
314
351
  children,
315
- localOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
352
+ localOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Portal_default, { container: host, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
316
353
  "div",
317
354
  {
318
355
  className: clsx_default(
@@ -1,11 +1,11 @@
1
1
  // src/components/PopOver/PopOver.tsx
2
- import React4 from "react";
2
+ import React5 from "react";
3
3
 
4
4
  // src/tokens/hooks/Portal.tsx
5
5
  import ReactDOM from "react-dom";
6
- var Portal = ({ children }) => {
6
+ var Portal = ({ children, container }) => {
7
7
  if (typeof document === "undefined") return null;
8
- return ReactDOM.createPortal(children, document.body);
8
+ return ReactDOM.createPortal(children, container ?? document.body);
9
9
  };
10
10
  Portal.displayName = "Portal";
11
11
  var Portal_default = Portal;
@@ -68,10 +68,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
68
68
  const scrollParentRef = React.useRef(null);
69
69
  const placedRef = React.useRef(false);
70
70
  const frozenMaxRef = React.useRef(void 0);
71
+ const cssCapRef = React.useRef(void 0);
71
72
  const calculatePosition = React.useCallback((remeasure = false) => {
72
73
  const pop = popRef.current;
73
74
  if (!triggerRef.current || !pop) return;
74
75
  if (remeasure) frozenMaxRef.current = void 0;
76
+ if (cssCapRef.current === void 0) {
77
+ pop.style.maxHeight = "";
78
+ const raw = getComputedStyle(pop).maxHeight;
79
+ cssCapRef.current = raw === "none" ? null : Number.parseFloat(raw) || null;
80
+ }
75
81
  if (remeasure || !sizeRef.current) {
76
82
  sizeRef.current = {
77
83
  w: pop.offsetWidth,
@@ -93,8 +99,10 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
93
99
  };
94
100
  const first = !placedRef.current;
95
101
  if (first) pop.style.transition = "none";
102
+ const cap = cssCapRef.current;
103
+ const desiredH = cap == null ? popH : Math.min(popH, cap);
96
104
  const frozen = frozenMaxRef.current;
97
- const effectiveH = frozen == null ? popH : Math.min(popH, frozen);
105
+ const effectiveH = frozen == null ? desiredH : Math.min(desiredH, frozen);
98
106
  const { direction: next, top, left, over, maxHeight: suggested } = computePlacement(
99
107
  triggerRect,
100
108
  popW,
@@ -103,8 +111,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
103
111
  );
104
112
  if (frozenMaxRef.current === void 0) frozenMaxRef.current = suggested;
105
113
  const maxHeight = frozenMaxRef.current;
106
- pop.style.top = `${top + window.scrollY}px`;
107
- pop.style.left = `${left + window.scrollX}px`;
114
+ const hostRect = (pop.offsetParent ?? pop.parentElement)?.getBoundingClientRect();
115
+ pop.style.top = `${top - (hostRect?.top ?? 0)}px`;
116
+ pop.style.left = `${left - (hostRect?.left ?? 0)}px`;
108
117
  pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
109
118
  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";
110
119
  directionRef.current = next;
@@ -122,6 +131,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
122
131
  scrollParentRef.current = null;
123
132
  placedRef.current = false;
124
133
  frozenMaxRef.current = void 0;
134
+ cssCapRef.current = void 0;
125
135
  return;
126
136
  }
127
137
  if (triggerRef.current) {
@@ -178,8 +188,34 @@ var useClickOutside = (refs, handler, enabled = true) => {
178
188
  };
179
189
  var useClickOutside_default = useClickOutside;
180
190
 
181
- // src/tokens/hooks/useOverlayKeyboard.ts
191
+ // src/tokens/hooks/useOverlayHost.ts
182
192
  import React3 from "react";
193
+ var useOverlayHost = (triggerRef, enabled) => {
194
+ const [host, setHost] = React3.useState(null);
195
+ React3.useLayoutEffect(() => {
196
+ if (!enabled || !triggerRef.current) {
197
+ setHost(null);
198
+ return;
199
+ }
200
+ const el = document.createElement("div");
201
+ el.dataset.xplatOverlayHost = "";
202
+ el.style.position = "relative";
203
+ el.style.width = "0";
204
+ el.style.height = "0";
205
+ const parent = findScrollParent(triggerRef.current) ?? document.body;
206
+ parent.appendChild(el);
207
+ setHost(el);
208
+ return () => {
209
+ el.remove();
210
+ setHost(null);
211
+ };
212
+ }, [enabled, triggerRef]);
213
+ return host;
214
+ };
215
+ var useOverlayHost_default = useOverlayHost;
216
+
217
+ // src/tokens/hooks/useOverlayKeyboard.ts
218
+ import React4 from "react";
183
219
  var FOCUSABLE = [
184
220
  "a[href]",
185
221
  "button:not([disabled])",
@@ -189,7 +225,7 @@ var FOCUSABLE = [
189
225
  "[tabindex]:not([tabindex='-1'])"
190
226
  ].join(",");
191
227
  var useEscapeKey = (enabled, onEscape) => {
192
- React3.useEffect(() => {
228
+ React4.useEffect(() => {
193
229
  if (!enabled) return;
194
230
  const onKey = (e) => {
195
231
  if (e.key !== "Escape") return;
@@ -202,9 +238,9 @@ var useEscapeKey = (enabled, onEscape) => {
202
238
  }, [enabled, onEscape]);
203
239
  };
204
240
  var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
205
- const onCloseRef = React3.useRef(onClose);
241
+ const onCloseRef = React4.useRef(onClose);
206
242
  onCloseRef.current = onClose;
207
- React3.useEffect(() => {
243
+ React4.useEffect(() => {
208
244
  const trigger = triggerRef.current;
209
245
  if (!enabled || !trigger) return;
210
246
  const observer = new IntersectionObserver(
@@ -242,18 +278,19 @@ var clsx_default = clsx;
242
278
  import { jsx, jsxs } from "react/jsx-runtime";
243
279
  var PopOver = (props) => {
244
280
  const { children, isOpen, onClose, PopOverEl } = props;
245
- const popRef = React4.useRef(null);
246
- const triggerRef = React4.useRef(null);
247
- const [localOpen, setLocalOpen] = React4.useState(false);
248
- const [eventTrigger, setEventTrigger] = React4.useState(false);
281
+ const popRef = React5.useRef(null);
282
+ const triggerRef = React5.useRef(null);
283
+ const [localOpen, setLocalOpen] = React5.useState(false);
284
+ const [eventTrigger, setEventTrigger] = React5.useState(false);
249
285
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
250
286
  useCloseWhenFocusHidden(isOpen, triggerRef, popRef, onClose);
251
287
  useEscapeKey(isOpen, () => {
252
288
  onClose();
253
289
  triggerRef.current?.focus({ preventScroll: true });
254
290
  });
291
+ const host = useOverlayHost_default(triggerRef, localOpen);
255
292
  useAutoPosition_default(triggerRef, popRef, localOpen);
256
- React4.useEffect(() => {
293
+ React5.useEffect(() => {
257
294
  if (isOpen) {
258
295
  setLocalOpen(isOpen);
259
296
  setTimeout(() => {
@@ -276,7 +313,7 @@ var PopOver = (props) => {
276
313
  },
277
314
  children: [
278
315
  children,
279
- localOpen && /* @__PURE__ */ jsx(Portal_default, { children: /* @__PURE__ */ jsx(
316
+ localOpen && /* @__PURE__ */ jsx(Portal_default, { container: host, children: /* @__PURE__ */ jsx(
280
317
  "div",
281
318
  {
282
319
  className: clsx_default(