@x-plat/design-system 0.14.19 → 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.
@@ -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;
@@ -111,8 +111,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
111
111
  );
112
112
  if (frozenMaxRef.current === void 0) frozenMaxRef.current = suggested;
113
113
  const maxHeight = frozenMaxRef.current;
114
- pop.style.top = `${top + window.scrollY}px`;
115
- 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`;
116
117
  pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
117
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";
118
119
  directionRef.current = next;
@@ -187,8 +188,34 @@ var useClickOutside = (refs, handler, enabled = true) => {
187
188
  };
188
189
  var useClickOutside_default = useClickOutside;
189
190
 
190
- // src/tokens/hooks/useOverlayKeyboard.ts
191
+ // src/tokens/hooks/useOverlayHost.ts
191
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";
192
219
  var FOCUSABLE = [
193
220
  "a[href]",
194
221
  "button:not([disabled])",
@@ -198,7 +225,7 @@ var FOCUSABLE = [
198
225
  "[tabindex]:not([tabindex='-1'])"
199
226
  ].join(",");
200
227
  var useEscapeKey = (enabled, onEscape) => {
201
- React3.useEffect(() => {
228
+ React4.useEffect(() => {
202
229
  if (!enabled) return;
203
230
  const onKey = (e) => {
204
231
  if (e.key !== "Escape") return;
@@ -211,9 +238,9 @@ var useEscapeKey = (enabled, onEscape) => {
211
238
  }, [enabled, onEscape]);
212
239
  };
213
240
  var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
214
- const onCloseRef = React3.useRef(onClose);
241
+ const onCloseRef = React4.useRef(onClose);
215
242
  onCloseRef.current = onClose;
216
- React3.useEffect(() => {
243
+ React4.useEffect(() => {
217
244
  const trigger = triggerRef.current;
218
245
  if (!enabled || !trigger) return;
219
246
  const observer = new IntersectionObserver(
@@ -423,13 +450,13 @@ var TimePicker = (props) => {
423
450
  required,
424
451
  validations
425
452
  } = 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(() => {
453
+ const fieldId = React5.useId();
454
+ const triggerRef = React5.useRef(null);
455
+ const contentRef = React5.useRef(null);
456
+ const [isOpen, setOpen] = React5.useState(false);
457
+ const [mounted, setMounted] = React5.useState(false);
458
+ const [visible, setVisible] = React5.useState(false);
459
+ const options = React5.useMemo(() => {
433
460
  const safeStep = step > 0 && step <= 720 ? step : 30;
434
461
  const lo = toMinutes(min) ?? 0;
435
462
  const hi = toMinutes(max) ?? 24 * 60 - 1;
@@ -437,18 +464,19 @@ var TimePicker = (props) => {
437
464
  for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
438
465
  return out;
439
466
  }, [step, min, max]);
440
- const close = React4.useCallback(() => setOpen(false), []);
467
+ const close = React5.useCallback(() => setOpen(false), []);
441
468
  useClickOutside_default([triggerRef, contentRef], close, isOpen);
442
469
  useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
443
470
  useEscapeKey(isOpen, () => {
444
471
  close();
445
472
  triggerRef.current?.focus({ preventScroll: true });
446
473
  });
474
+ const host = useOverlayHost_default(triggerRef, mounted);
447
475
  useAutoPosition_default(triggerRef, contentRef, mounted);
448
- React4.useEffect(() => {
476
+ React5.useEffect(() => {
449
477
  if (disabled && isOpen) setOpen(false);
450
478
  }, [disabled, isOpen]);
451
- React4.useEffect(() => {
479
+ React5.useEffect(() => {
452
480
  if (isOpen) {
453
481
  setMounted(true);
454
482
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -486,7 +514,7 @@ var TimePicker = (props) => {
486
514
  children: /* @__PURE__ */ jsx5("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
487
515
  }
488
516
  ),
489
- mounted && /* @__PURE__ */ jsx5(Portal_default, { children: /* @__PURE__ */ jsx5(
517
+ mounted && /* @__PURE__ */ jsx5(Portal_default, { container: host, children: /* @__PURE__ */ jsx5(
490
518
  "div",
491
519
  {
492
520
  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;