@x-plat/design-system 0.14.19 → 0.15.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.
@@ -36,13 +36,13 @@ __export(Select_exports, {
36
36
  module.exports = __toCommonJS(Select_exports);
37
37
 
38
38
  // src/components/Select/Select.tsx
39
- var import_react6 = __toESM(require("react"), 1);
39
+ var import_react7 = __toESM(require("react"), 1);
40
40
 
41
41
  // src/tokens/hooks/Portal.tsx
42
42
  var import_react_dom = __toESM(require("react-dom"), 1);
43
- var Portal = ({ children }) => {
43
+ var Portal = ({ children, container }) => {
44
44
  if (typeof document === "undefined") return null;
45
- return import_react_dom.default.createPortal(children, document.body);
45
+ return import_react_dom.default.createPortal(children, container ?? document.body);
46
46
  };
47
47
  Portal.displayName = "Portal";
48
48
  var Portal_default = Portal;
@@ -51,8 +51,10 @@ var Portal_default = Portal;
51
51
  var import_react = __toESM(require("react"), 1);
52
52
  var findScrollParent = (el) => {
53
53
  for (let p = el.parentElement; p; p = p.parentElement) {
54
- const { overflowY, overflowX } = getComputedStyle(p);
55
- if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
54
+ if (p.dataset.xplatOverlayEscape !== void 0) continue;
55
+ const { overflowY } = getComputedStyle(p);
56
+ if (!/(auto|scroll)/.test(overflowY)) continue;
57
+ if (p.scrollHeight > p.clientHeight) return p;
56
58
  }
57
59
  return null;
58
60
  };
@@ -148,8 +150,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
148
150
  );
149
151
  if (frozenMaxRef.current === void 0) frozenMaxRef.current = suggested;
150
152
  const maxHeight = frozenMaxRef.current;
151
- pop.style.top = `${top + window.scrollY}px`;
152
- pop.style.left = `${left + window.scrollX}px`;
153
+ const hostRect = (pop.offsetParent ?? pop.parentElement)?.getBoundingClientRect();
154
+ pop.style.top = `${top - (hostRect?.top ?? 0)}px`;
155
+ pop.style.left = `${left - (hostRect?.left ?? 0)}px`;
153
156
  pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
154
157
  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";
155
158
  directionRef.current = next;
@@ -224,8 +227,34 @@ var useClickOutside = (refs, handler, enabled = true) => {
224
227
  };
225
228
  var useClickOutside_default = useClickOutside;
226
229
 
227
- // src/tokens/hooks/useOverlayKeyboard.ts
230
+ // src/tokens/hooks/useOverlayHost.ts
228
231
  var import_react3 = __toESM(require("react"), 1);
232
+ var useOverlayHost = (triggerRef, enabled) => {
233
+ const [host, setHost] = import_react3.default.useState(null);
234
+ import_react3.default.useLayoutEffect(() => {
235
+ if (!enabled || !triggerRef.current) {
236
+ setHost(null);
237
+ return;
238
+ }
239
+ const el = document.createElement("div");
240
+ el.dataset.xplatOverlayHost = "";
241
+ el.style.position = "relative";
242
+ el.style.width = "0";
243
+ el.style.height = "0";
244
+ const parent = findScrollParent(triggerRef.current) ?? document.body;
245
+ parent.appendChild(el);
246
+ setHost(el);
247
+ return () => {
248
+ el.remove();
249
+ setHost(null);
250
+ };
251
+ }, [enabled, triggerRef]);
252
+ return host;
253
+ };
254
+ var useOverlayHost_default = useOverlayHost;
255
+
256
+ // src/tokens/hooks/useOverlayKeyboard.ts
257
+ var import_react4 = __toESM(require("react"), 1);
229
258
  var FOCUSABLE = [
230
259
  "a[href]",
231
260
  "button:not([disabled])",
@@ -235,7 +264,7 @@ var FOCUSABLE = [
235
264
  "[tabindex]:not([tabindex='-1'])"
236
265
  ].join(",");
237
266
  var useEscapeKey = (enabled, onEscape) => {
238
- import_react3.default.useEffect(() => {
267
+ import_react4.default.useEffect(() => {
239
268
  if (!enabled) return;
240
269
  const onKey = (e) => {
241
270
  if (e.key !== "Escape") return;
@@ -248,9 +277,9 @@ var useEscapeKey = (enabled, onEscape) => {
248
277
  }, [enabled, onEscape]);
249
278
  };
250
279
  var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
251
- const onCloseRef = import_react3.default.useRef(onClose);
280
+ const onCloseRef = import_react4.default.useRef(onClose);
252
281
  onCloseRef.current = onClose;
253
- import_react3.default.useEffect(() => {
282
+ import_react4.default.useEffect(() => {
254
283
  const trigger = triggerRef.current;
255
284
  if (!enabled || !trigger) return;
256
285
  const observer = new IntersectionObserver(
@@ -1314,16 +1343,16 @@ Field.displayName = "Field";
1314
1343
  var hasError = (validations) => !!validations?.some((v) => v.status === "error");
1315
1344
 
1316
1345
  // src/components/Select/context.ts
1317
- var import_react4 = __toESM(require("react"), 1);
1318
- var SelectContext = import_react4.default.createContext(null);
1346
+ var import_react5 = __toESM(require("react"), 1);
1347
+ var SelectContext = import_react5.default.createContext(null);
1319
1348
  var context_default = SelectContext;
1320
1349
 
1321
1350
  // src/components/Select/SelectItem.tsx
1322
- var import_react5 = __toESM(require("react"), 1);
1351
+ var import_react6 = __toESM(require("react"), 1);
1323
1352
  var import_jsx_runtime296 = require("react/jsx-runtime");
1324
1353
  var SelectItem = (props) => {
1325
1354
  const { children, value, onClick, disabled = false } = props;
1326
- const ctx = import_react5.default.useContext(context_default);
1355
+ const ctx = import_react6.default.useContext(context_default);
1327
1356
  const handleClick = (e) => {
1328
1357
  e.preventDefault();
1329
1358
  e.stopPropagation();
@@ -1373,29 +1402,29 @@ var SelectRoot = (props) => {
1373
1402
  required,
1374
1403
  size = "md"
1375
1404
  } = props;
1376
- const fieldId = import_react6.default.useId();
1377
- const itemChildren = import_react6.default.Children.toArray(children).filter(
1378
- (child) => import_react6.default.isValidElement(child) && child.type === SelectItem_default
1405
+ const fieldId = import_react7.default.useId();
1406
+ const itemChildren = import_react7.default.Children.toArray(children).filter(
1407
+ (child) => import_react7.default.isValidElement(child) && child.type === SelectItem_default
1379
1408
  );
1380
1409
  const isControlled = valueProp !== void 0;
1381
- const [isOpen, setOpen] = import_react6.default.useState(false);
1382
- const [uncontrolledLabel, setUncontrolledLabel] = import_react6.default.useState(null);
1383
- const [uncontrolledValue, setUncontrolledValue] = import_react6.default.useState(void 0);
1384
- const controlledLabel = import_react6.default.useMemo(() => {
1410
+ const [isOpen, setOpen] = import_react7.default.useState(false);
1411
+ const [uncontrolledLabel, setUncontrolledLabel] = import_react7.default.useState(null);
1412
+ const [uncontrolledValue, setUncontrolledValue] = import_react7.default.useState(void 0);
1413
+ const controlledLabel = import_react7.default.useMemo(() => {
1385
1414
  if (!isControlled) return null;
1386
1415
  const match = itemChildren.find((child) => child.props.value === valueProp);
1387
1416
  return match ? match.props.children : null;
1388
1417
  }, [isControlled, valueProp, itemChildren]);
1389
1418
  const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
1390
1419
  const selectedValue = isControlled ? valueProp : uncontrolledValue;
1391
- const triggerRef = import_react6.default.useRef(null);
1392
- const contentRef = import_react6.default.useRef(null);
1393
- const [mounted, setMounted] = import_react6.default.useState(false);
1394
- const [visible, setVisible] = import_react6.default.useState(false);
1395
- import_react6.default.useEffect(() => {
1420
+ const triggerRef = import_react7.default.useRef(null);
1421
+ const contentRef = import_react7.default.useRef(null);
1422
+ const [mounted, setMounted] = import_react7.default.useState(false);
1423
+ const [visible, setVisible] = import_react7.default.useState(false);
1424
+ import_react7.default.useEffect(() => {
1396
1425
  if (disabled && isOpen) setOpen(false);
1397
1426
  }, [disabled, isOpen]);
1398
- import_react6.default.useEffect(() => {
1427
+ import_react7.default.useEffect(() => {
1399
1428
  if (isOpen) {
1400
1429
  setMounted(true);
1401
1430
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -1405,33 +1434,34 @@ var SelectRoot = (props) => {
1405
1434
  const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS);
1406
1435
  return () => clearTimeout(t);
1407
1436
  }, [isOpen]);
1408
- const [query, setQuery] = import_react6.default.useState("");
1437
+ const [query, setQuery] = import_react7.default.useState("");
1409
1438
  const textOf = (node) => {
1410
1439
  if (node === null || node === void 0 || typeof node === "boolean") return "";
1411
1440
  if (typeof node === "string" || typeof node === "number") return String(node);
1412
1441
  if (Array.isArray(node)) return node.map(textOf).join("");
1413
- if (import_react6.default.isValidElement(node)) return textOf(node.props.children);
1442
+ if (import_react7.default.isValidElement(node)) return textOf(node.props.children);
1414
1443
  return "";
1415
1444
  };
1416
- const visibleItems = import_react6.default.useMemo(() => {
1445
+ const visibleItems = import_react7.default.useMemo(() => {
1417
1446
  if (!searchable || !query.trim()) return itemChildren;
1418
1447
  const q = query.trim().toLowerCase();
1419
1448
  return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
1420
1449
  }, [searchable, query, itemChildren]);
1421
- const open = import_react6.default.useCallback(() => setOpen(true), []);
1422
- const close = import_react6.default.useCallback(() => {
1450
+ const open = import_react7.default.useCallback(() => setOpen(true), []);
1451
+ const close = import_react7.default.useCallback(() => {
1423
1452
  setOpen(false);
1424
1453
  setQuery("");
1425
1454
  }, []);
1426
- const toggle = import_react6.default.useCallback(() => setOpen((prev) => !prev), []);
1455
+ const toggle = import_react7.default.useCallback(() => setOpen((prev) => !prev), []);
1427
1456
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
1428
1457
  useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
1429
1458
  useEscapeKey(isOpen, () => {
1430
1459
  close();
1431
1460
  triggerRef.current?.focus({ preventScroll: true });
1432
1461
  });
1462
+ const host = useOverlayHost_default(triggerRef, mounted);
1433
1463
  useAutoPosition_default(triggerRef, contentRef, mounted);
1434
- const setSelected = import_react6.default.useCallback(
1464
+ const setSelected = import_react7.default.useCallback(
1435
1465
  (label2, itemValue) => {
1436
1466
  if (!isControlled) {
1437
1467
  setUncontrolledLabel(label2);
@@ -1441,7 +1471,7 @@ var SelectRoot = (props) => {
1441
1471
  },
1442
1472
  [isControlled, onChange]
1443
1473
  );
1444
- const ctxValue = import_react6.default.useMemo(
1474
+ const ctxValue = import_react7.default.useMemo(
1445
1475
  () => ({
1446
1476
  isOpen,
1447
1477
  mounted,
@@ -1520,7 +1550,7 @@ var SelectRoot = (props) => {
1520
1550
  ]
1521
1551
  }
1522
1552
  ),
1523
- mounted && /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime297.jsxs)(
1553
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(Portal_default, { container: host, children: /* @__PURE__ */ (0, import_jsx_runtime297.jsxs)(
1524
1554
  "div",
1525
1555
  {
1526
1556
  className: clsx_default("lib-xplat-select-content", size, stateClass),
@@ -1,11 +1,11 @@
1
1
  // src/components/Select/Select.tsx
2
- import React6 from "react";
2
+ import React7 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;
@@ -14,8 +14,10 @@ var Portal_default = Portal;
14
14
  import React from "react";
15
15
  var findScrollParent = (el) => {
16
16
  for (let p = el.parentElement; p; p = p.parentElement) {
17
- const { overflowY, overflowX } = getComputedStyle(p);
18
- if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
17
+ if (p.dataset.xplatOverlayEscape !== void 0) continue;
18
+ const { overflowY } = getComputedStyle(p);
19
+ if (!/(auto|scroll)/.test(overflowY)) continue;
20
+ if (p.scrollHeight > p.clientHeight) return p;
19
21
  }
20
22
  return null;
21
23
  };
@@ -111,8 +113,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
111
113
  );
112
114
  if (frozenMaxRef.current === void 0) frozenMaxRef.current = suggested;
113
115
  const maxHeight = frozenMaxRef.current;
114
- pop.style.top = `${top + window.scrollY}px`;
115
- pop.style.left = `${left + window.scrollX}px`;
116
+ const hostRect = (pop.offsetParent ?? pop.parentElement)?.getBoundingClientRect();
117
+ pop.style.top = `${top - (hostRect?.top ?? 0)}px`;
118
+ pop.style.left = `${left - (hostRect?.left ?? 0)}px`;
116
119
  pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
117
120
  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";
118
121
  directionRef.current = next;
@@ -187,8 +190,34 @@ var useClickOutside = (refs, handler, enabled = true) => {
187
190
  };
188
191
  var useClickOutside_default = useClickOutside;
189
192
 
190
- // src/tokens/hooks/useOverlayKeyboard.ts
193
+ // src/tokens/hooks/useOverlayHost.ts
191
194
  import React3 from "react";
195
+ var useOverlayHost = (triggerRef, enabled) => {
196
+ const [host, setHost] = React3.useState(null);
197
+ React3.useLayoutEffect(() => {
198
+ if (!enabled || !triggerRef.current) {
199
+ setHost(null);
200
+ return;
201
+ }
202
+ const el = document.createElement("div");
203
+ el.dataset.xplatOverlayHost = "";
204
+ el.style.position = "relative";
205
+ el.style.width = "0";
206
+ el.style.height = "0";
207
+ const parent = findScrollParent(triggerRef.current) ?? document.body;
208
+ parent.appendChild(el);
209
+ setHost(el);
210
+ return () => {
211
+ el.remove();
212
+ setHost(null);
213
+ };
214
+ }, [enabled, triggerRef]);
215
+ return host;
216
+ };
217
+ var useOverlayHost_default = useOverlayHost;
218
+
219
+ // src/tokens/hooks/useOverlayKeyboard.ts
220
+ import React4 from "react";
192
221
  var FOCUSABLE = [
193
222
  "a[href]",
194
223
  "button:not([disabled])",
@@ -198,7 +227,7 @@ var FOCUSABLE = [
198
227
  "[tabindex]:not([tabindex='-1'])"
199
228
  ].join(",");
200
229
  var useEscapeKey = (enabled, onEscape) => {
201
- React3.useEffect(() => {
230
+ React4.useEffect(() => {
202
231
  if (!enabled) return;
203
232
  const onKey = (e) => {
204
233
  if (e.key !== "Escape") return;
@@ -211,9 +240,9 @@ var useEscapeKey = (enabled, onEscape) => {
211
240
  }, [enabled, onEscape]);
212
241
  };
213
242
  var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
214
- const onCloseRef = React3.useRef(onClose);
243
+ const onCloseRef = React4.useRef(onClose);
215
244
  onCloseRef.current = onClose;
216
- React3.useEffect(() => {
245
+ React4.useEffect(() => {
217
246
  const trigger = triggerRef.current;
218
247
  if (!enabled || !trigger) return;
219
248
  const observer = new IntersectionObserver(
@@ -1277,16 +1306,16 @@ Field.displayName = "Field";
1277
1306
  var hasError = (validations) => !!validations?.some((v) => v.status === "error");
1278
1307
 
1279
1308
  // src/components/Select/context.ts
1280
- import React4 from "react";
1281
- var SelectContext = React4.createContext(null);
1309
+ import React5 from "react";
1310
+ var SelectContext = React5.createContext(null);
1282
1311
  var context_default = SelectContext;
1283
1312
 
1284
1313
  // src/components/Select/SelectItem.tsx
1285
- import React5 from "react";
1314
+ import React6 from "react";
1286
1315
  import { jsx as jsx296 } from "react/jsx-runtime";
1287
1316
  var SelectItem = (props) => {
1288
1317
  const { children, value, onClick, disabled = false } = props;
1289
- const ctx = React5.useContext(context_default);
1318
+ const ctx = React6.useContext(context_default);
1290
1319
  const handleClick = (e) => {
1291
1320
  e.preventDefault();
1292
1321
  e.stopPropagation();
@@ -1336,29 +1365,29 @@ var SelectRoot = (props) => {
1336
1365
  required,
1337
1366
  size = "md"
1338
1367
  } = props;
1339
- const fieldId = React6.useId();
1340
- const itemChildren = React6.Children.toArray(children).filter(
1341
- (child) => React6.isValidElement(child) && child.type === SelectItem_default
1368
+ const fieldId = React7.useId();
1369
+ const itemChildren = React7.Children.toArray(children).filter(
1370
+ (child) => React7.isValidElement(child) && child.type === SelectItem_default
1342
1371
  );
1343
1372
  const isControlled = valueProp !== void 0;
1344
- const [isOpen, setOpen] = React6.useState(false);
1345
- const [uncontrolledLabel, setUncontrolledLabel] = React6.useState(null);
1346
- const [uncontrolledValue, setUncontrolledValue] = React6.useState(void 0);
1347
- const controlledLabel = React6.useMemo(() => {
1373
+ const [isOpen, setOpen] = React7.useState(false);
1374
+ const [uncontrolledLabel, setUncontrolledLabel] = React7.useState(null);
1375
+ const [uncontrolledValue, setUncontrolledValue] = React7.useState(void 0);
1376
+ const controlledLabel = React7.useMemo(() => {
1348
1377
  if (!isControlled) return null;
1349
1378
  const match = itemChildren.find((child) => child.props.value === valueProp);
1350
1379
  return match ? match.props.children : null;
1351
1380
  }, [isControlled, valueProp, itemChildren]);
1352
1381
  const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
1353
1382
  const selectedValue = isControlled ? valueProp : uncontrolledValue;
1354
- const triggerRef = React6.useRef(null);
1355
- const contentRef = React6.useRef(null);
1356
- const [mounted, setMounted] = React6.useState(false);
1357
- const [visible, setVisible] = React6.useState(false);
1358
- React6.useEffect(() => {
1383
+ const triggerRef = React7.useRef(null);
1384
+ const contentRef = React7.useRef(null);
1385
+ const [mounted, setMounted] = React7.useState(false);
1386
+ const [visible, setVisible] = React7.useState(false);
1387
+ React7.useEffect(() => {
1359
1388
  if (disabled && isOpen) setOpen(false);
1360
1389
  }, [disabled, isOpen]);
1361
- React6.useEffect(() => {
1390
+ React7.useEffect(() => {
1362
1391
  if (isOpen) {
1363
1392
  setMounted(true);
1364
1393
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -1368,33 +1397,34 @@ var SelectRoot = (props) => {
1368
1397
  const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS);
1369
1398
  return () => clearTimeout(t);
1370
1399
  }, [isOpen]);
1371
- const [query, setQuery] = React6.useState("");
1400
+ const [query, setQuery] = React7.useState("");
1372
1401
  const textOf = (node) => {
1373
1402
  if (node === null || node === void 0 || typeof node === "boolean") return "";
1374
1403
  if (typeof node === "string" || typeof node === "number") return String(node);
1375
1404
  if (Array.isArray(node)) return node.map(textOf).join("");
1376
- if (React6.isValidElement(node)) return textOf(node.props.children);
1405
+ if (React7.isValidElement(node)) return textOf(node.props.children);
1377
1406
  return "";
1378
1407
  };
1379
- const visibleItems = React6.useMemo(() => {
1408
+ const visibleItems = React7.useMemo(() => {
1380
1409
  if (!searchable || !query.trim()) return itemChildren;
1381
1410
  const q = query.trim().toLowerCase();
1382
1411
  return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
1383
1412
  }, [searchable, query, itemChildren]);
1384
- const open = React6.useCallback(() => setOpen(true), []);
1385
- const close = React6.useCallback(() => {
1413
+ const open = React7.useCallback(() => setOpen(true), []);
1414
+ const close = React7.useCallback(() => {
1386
1415
  setOpen(false);
1387
1416
  setQuery("");
1388
1417
  }, []);
1389
- const toggle = React6.useCallback(() => setOpen((prev) => !prev), []);
1418
+ const toggle = React7.useCallback(() => setOpen((prev) => !prev), []);
1390
1419
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
1391
1420
  useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
1392
1421
  useEscapeKey(isOpen, () => {
1393
1422
  close();
1394
1423
  triggerRef.current?.focus({ preventScroll: true });
1395
1424
  });
1425
+ const host = useOverlayHost_default(triggerRef, mounted);
1396
1426
  useAutoPosition_default(triggerRef, contentRef, mounted);
1397
- const setSelected = React6.useCallback(
1427
+ const setSelected = React7.useCallback(
1398
1428
  (label2, itemValue) => {
1399
1429
  if (!isControlled) {
1400
1430
  setUncontrolledLabel(label2);
@@ -1404,7 +1434,7 @@ var SelectRoot = (props) => {
1404
1434
  },
1405
1435
  [isControlled, onChange]
1406
1436
  );
1407
- const ctxValue = React6.useMemo(
1437
+ const ctxValue = React7.useMemo(
1408
1438
  () => ({
1409
1439
  isOpen,
1410
1440
  mounted,
@@ -1483,7 +1513,7 @@ var SelectRoot = (props) => {
1483
1513
  ]
1484
1514
  }
1485
1515
  ),
1486
- mounted && /* @__PURE__ */ jsx297(Portal_default, { children: /* @__PURE__ */ jsxs190(
1516
+ mounted && /* @__PURE__ */ jsx297(Portal_default, { container: host, children: /* @__PURE__ */ jsxs190(
1487
1517
  "div",
1488
1518
  {
1489
1519
  className: clsx_default("lib-xplat-select-content", size, stateClass),
@@ -59,18 +59,25 @@ var Table = (props) => {
59
59
  headerSticky = false,
60
60
  stickyShadow = true
61
61
  } = props;
62
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
63
- TableContext_default.Provider,
62
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
63
+ "div",
64
64
  {
65
- value: {
66
- rowBorderUse,
67
- colBorderUse,
68
- headerSticky,
69
- stickyShadow
70
- },
71
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { className: "lib-xplat-table", children })
65
+ className: `lib-xplat-table-wrapper ${size}`,
66
+ "data-xplat-overlay-escape": "",
67
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
68
+ TableContext_default.Provider,
69
+ {
70
+ value: {
71
+ rowBorderUse,
72
+ colBorderUse,
73
+ headerSticky,
74
+ stickyShadow
75
+ },
76
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("table", { className: "lib-xplat-table", children })
77
+ }
78
+ )
72
79
  }
73
- ) });
80
+ );
74
81
  };
75
82
  Table.displayName = "Table";
76
83
  var Table_default = Table;
@@ -19,18 +19,25 @@ var Table = (props) => {
19
19
  headerSticky = false,
20
20
  stickyShadow = true
21
21
  } = props;
22
- return /* @__PURE__ */ jsx("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx(
23
- TableContext_default.Provider,
22
+ return /* @__PURE__ */ jsx(
23
+ "div",
24
24
  {
25
- value: {
26
- rowBorderUse,
27
- colBorderUse,
28
- headerSticky,
29
- stickyShadow
30
- },
31
- children: /* @__PURE__ */ jsx("table", { className: "lib-xplat-table", children })
25
+ className: `lib-xplat-table-wrapper ${size}`,
26
+ "data-xplat-overlay-escape": "",
27
+ children: /* @__PURE__ */ jsx(
28
+ TableContext_default.Provider,
29
+ {
30
+ value: {
31
+ rowBorderUse,
32
+ colBorderUse,
33
+ headerSticky,
34
+ stickyShadow
35
+ },
36
+ children: /* @__PURE__ */ jsx("table", { className: "lib-xplat-table", children })
37
+ }
38
+ )
32
39
  }
33
- ) });
40
+ );
34
41
  };
35
42
  Table.displayName = "Table";
36
43
  var Table_default = Table;
@@ -35,13 +35,13 @@ __export(TimePicker_exports, {
35
35
  module.exports = __toCommonJS(TimePicker_exports);
36
36
 
37
37
  // src/components/TimePicker/TimePicker.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;
@@ -50,8 +50,10 @@ var Portal_default = Portal;
50
50
  var import_react = __toESM(require("react"), 1);
51
51
  var findScrollParent = (el) => {
52
52
  for (let p = el.parentElement; p; p = p.parentElement) {
53
- const { overflowY, overflowX } = getComputedStyle(p);
54
- if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
53
+ if (p.dataset.xplatOverlayEscape !== void 0) continue;
54
+ const { overflowY } = getComputedStyle(p);
55
+ if (!/(auto|scroll)/.test(overflowY)) continue;
56
+ if (p.scrollHeight > p.clientHeight) return p;
55
57
  }
56
58
  return null;
57
59
  };
@@ -147,8 +149,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
147
149
  );
148
150
  if (frozenMaxRef.current === void 0) frozenMaxRef.current = suggested;
149
151
  const maxHeight = frozenMaxRef.current;
150
- pop.style.top = `${top + window.scrollY}px`;
151
- pop.style.left = `${left + window.scrollX}px`;
152
+ const hostRect = (pop.offsetParent ?? pop.parentElement)?.getBoundingClientRect();
153
+ pop.style.top = `${top - (hostRect?.top ?? 0)}px`;
154
+ pop.style.left = `${left - (hostRect?.left ?? 0)}px`;
152
155
  pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
153
156
  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";
154
157
  directionRef.current = next;
@@ -223,8 +226,34 @@ var useClickOutside = (refs, handler, enabled = true) => {
223
226
  };
224
227
  var useClickOutside_default = useClickOutside;
225
228
 
226
- // src/tokens/hooks/useOverlayKeyboard.ts
229
+ // src/tokens/hooks/useOverlayHost.ts
227
230
  var import_react3 = __toESM(require("react"), 1);
231
+ var useOverlayHost = (triggerRef, enabled) => {
232
+ const [host, setHost] = import_react3.default.useState(null);
233
+ import_react3.default.useLayoutEffect(() => {
234
+ if (!enabled || !triggerRef.current) {
235
+ setHost(null);
236
+ return;
237
+ }
238
+ const el = document.createElement("div");
239
+ el.dataset.xplatOverlayHost = "";
240
+ el.style.position = "relative";
241
+ el.style.width = "0";
242
+ el.style.height = "0";
243
+ const parent = findScrollParent(triggerRef.current) ?? document.body;
244
+ parent.appendChild(el);
245
+ setHost(el);
246
+ return () => {
247
+ el.remove();
248
+ setHost(null);
249
+ };
250
+ }, [enabled, triggerRef]);
251
+ return host;
252
+ };
253
+ var useOverlayHost_default = useOverlayHost;
254
+
255
+ // src/tokens/hooks/useOverlayKeyboard.ts
256
+ var import_react4 = __toESM(require("react"), 1);
228
257
  var FOCUSABLE = [
229
258
  "a[href]",
230
259
  "button:not([disabled])",
@@ -234,7 +263,7 @@ var FOCUSABLE = [
234
263
  "[tabindex]:not([tabindex='-1'])"
235
264
  ].join(",");
236
265
  var useEscapeKey = (enabled, onEscape) => {
237
- import_react3.default.useEffect(() => {
266
+ import_react4.default.useEffect(() => {
238
267
  if (!enabled) return;
239
268
  const onKey = (e) => {
240
269
  if (e.key !== "Escape") return;
@@ -247,9 +276,9 @@ var useEscapeKey = (enabled, onEscape) => {
247
276
  }, [enabled, onEscape]);
248
277
  };
249
278
  var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
250
- const onCloseRef = import_react3.default.useRef(onClose);
279
+ const onCloseRef = import_react4.default.useRef(onClose);
251
280
  onCloseRef.current = onClose;
252
- import_react3.default.useEffect(() => {
281
+ import_react4.default.useEffect(() => {
253
282
  const trigger = triggerRef.current;
254
283
  if (!enabled || !trigger) return;
255
284
  const observer = new IntersectionObserver(
@@ -459,13 +488,13 @@ var TimePicker = (props) => {
459
488
  required,
460
489
  validations
461
490
  } = props;
462
- const fieldId = import_react4.default.useId();
463
- const triggerRef = import_react4.default.useRef(null);
464
- const contentRef = import_react4.default.useRef(null);
465
- const [isOpen, setOpen] = import_react4.default.useState(false);
466
- const [mounted, setMounted] = import_react4.default.useState(false);
467
- const [visible, setVisible] = import_react4.default.useState(false);
468
- const options = import_react4.default.useMemo(() => {
491
+ const fieldId = import_react5.default.useId();
492
+ const triggerRef = import_react5.default.useRef(null);
493
+ const contentRef = import_react5.default.useRef(null);
494
+ const [isOpen, setOpen] = import_react5.default.useState(false);
495
+ const [mounted, setMounted] = import_react5.default.useState(false);
496
+ const [visible, setVisible] = import_react5.default.useState(false);
497
+ const options = import_react5.default.useMemo(() => {
469
498
  const safeStep = step > 0 && step <= 720 ? step : 30;
470
499
  const lo = toMinutes(min) ?? 0;
471
500
  const hi = toMinutes(max) ?? 24 * 60 - 1;
@@ -473,18 +502,19 @@ var TimePicker = (props) => {
473
502
  for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
474
503
  return out;
475
504
  }, [step, min, max]);
476
- const close = import_react4.default.useCallback(() => setOpen(false), []);
505
+ const close = import_react5.default.useCallback(() => setOpen(false), []);
477
506
  useClickOutside_default([triggerRef, contentRef], close, isOpen);
478
507
  useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
479
508
  useEscapeKey(isOpen, () => {
480
509
  close();
481
510
  triggerRef.current?.focus({ preventScroll: true });
482
511
  });
512
+ const host = useOverlayHost_default(triggerRef, mounted);
483
513
  useAutoPosition_default(triggerRef, contentRef, mounted);
484
- import_react4.default.useEffect(() => {
514
+ import_react5.default.useEffect(() => {
485
515
  if (disabled && isOpen) setOpen(false);
486
516
  }, [disabled, isOpen]);
487
- import_react4.default.useEffect(() => {
517
+ import_react5.default.useEffect(() => {
488
518
  if (isOpen) {
489
519
  setMounted(true);
490
520
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -522,7 +552,7 @@ var TimePicker = (props) => {
522
552
  children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
523
553
  }
524
554
  ),
525
- mounted && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
555
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Portal_default, { container: host, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
526
556
  "div",
527
557
  {
528
558
  ref: contentRef,