@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.
@@ -1,11 +1,11 @@
1
1
  // src/components/TimePicker/TimePicker.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;
@@ -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(
@@ -423,13 +452,13 @@ var TimePicker = (props) => {
423
452
  required,
424
453
  validations
425
454
  } = props;
426
- const fieldId = React4.useId();
427
- const triggerRef = React4.useRef(null);
428
- const contentRef = React4.useRef(null);
429
- const [isOpen, setOpen] = React4.useState(false);
430
- const [mounted, setMounted] = React4.useState(false);
431
- const [visible, setVisible] = React4.useState(false);
432
- const options = React4.useMemo(() => {
455
+ const fieldId = React5.useId();
456
+ const triggerRef = React5.useRef(null);
457
+ const contentRef = React5.useRef(null);
458
+ const [isOpen, setOpen] = React5.useState(false);
459
+ const [mounted, setMounted] = React5.useState(false);
460
+ const [visible, setVisible] = React5.useState(false);
461
+ const options = React5.useMemo(() => {
433
462
  const safeStep = step > 0 && step <= 720 ? step : 30;
434
463
  const lo = toMinutes(min) ?? 0;
435
464
  const hi = toMinutes(max) ?? 24 * 60 - 1;
@@ -437,18 +466,19 @@ var TimePicker = (props) => {
437
466
  for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
438
467
  return out;
439
468
  }, [step, min, max]);
440
- const close = React4.useCallback(() => setOpen(false), []);
469
+ const close = React5.useCallback(() => setOpen(false), []);
441
470
  useClickOutside_default([triggerRef, contentRef], close, isOpen);
442
471
  useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
443
472
  useEscapeKey(isOpen, () => {
444
473
  close();
445
474
  triggerRef.current?.focus({ preventScroll: true });
446
475
  });
476
+ const host = useOverlayHost_default(triggerRef, mounted);
447
477
  useAutoPosition_default(triggerRef, contentRef, mounted);
448
- React4.useEffect(() => {
478
+ React5.useEffect(() => {
449
479
  if (disabled && isOpen) setOpen(false);
450
480
  }, [disabled, isOpen]);
451
- React4.useEffect(() => {
481
+ React5.useEffect(() => {
452
482
  if (isOpen) {
453
483
  setMounted(true);
454
484
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -486,7 +516,7 @@ var TimePicker = (props) => {
486
516
  children: /* @__PURE__ */ jsx5("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
487
517
  }
488
518
  ),
489
- mounted && /* @__PURE__ */ jsx5(Portal_default, { children: /* @__PURE__ */ jsx5(
519
+ mounted && /* @__PURE__ */ jsx5(Portal_default, { container: host, children: /* @__PURE__ */ jsx5(
490
520
  "div",
491
521
  {
492
522
  ref: contentRef,
@@ -39,9 +39,9 @@ var import_react = __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;
@@ -3,9 +3,9 @@ import React 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;