@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.
@@ -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;
@@ -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(
@@ -414,13 +450,13 @@ var TimePicker = (props) => {
414
450
  required,
415
451
  validations
416
452
  } = props;
417
- const fieldId = React4.useId();
418
- const triggerRef = React4.useRef(null);
419
- const contentRef = React4.useRef(null);
420
- const [isOpen, setOpen] = React4.useState(false);
421
- const [mounted, setMounted] = React4.useState(false);
422
- const [visible, setVisible] = React4.useState(false);
423
- 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(() => {
424
460
  const safeStep = step > 0 && step <= 720 ? step : 30;
425
461
  const lo = toMinutes(min) ?? 0;
426
462
  const hi = toMinutes(max) ?? 24 * 60 - 1;
@@ -428,18 +464,19 @@ var TimePicker = (props) => {
428
464
  for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
429
465
  return out;
430
466
  }, [step, min, max]);
431
- const close = React4.useCallback(() => setOpen(false), []);
467
+ const close = React5.useCallback(() => setOpen(false), []);
432
468
  useClickOutside_default([triggerRef, contentRef], close, isOpen);
433
469
  useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
434
470
  useEscapeKey(isOpen, () => {
435
471
  close();
436
472
  triggerRef.current?.focus({ preventScroll: true });
437
473
  });
474
+ const host = useOverlayHost_default(triggerRef, mounted);
438
475
  useAutoPosition_default(triggerRef, contentRef, mounted);
439
- React4.useEffect(() => {
476
+ React5.useEffect(() => {
440
477
  if (disabled && isOpen) setOpen(false);
441
478
  }, [disabled, isOpen]);
442
- React4.useEffect(() => {
479
+ React5.useEffect(() => {
443
480
  if (isOpen) {
444
481
  setMounted(true);
445
482
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -477,7 +514,7 @@ var TimePicker = (props) => {
477
514
  children: /* @__PURE__ */ jsx5("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
478
515
  }
479
516
  ),
480
- mounted && /* @__PURE__ */ jsx5(Portal_default, { children: /* @__PURE__ */ jsx5(
517
+ mounted && /* @__PURE__ */ jsx5(Portal_default, { container: host, children: /* @__PURE__ */ jsx5(
481
518
  "div",
482
519
  {
483
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;