@x-plat/design-system 0.14.14 → 0.14.16

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.
package/dist/index.cjs CHANGED
@@ -7465,7 +7465,7 @@ Chip.displayName = "Chip";
7465
7465
  var Chip_default = Chip;
7466
7466
 
7467
7467
  // src/components/DatePicker/InputDatePicker/index.tsx
7468
- var import_react13 = __toESM(require("react"), 1);
7468
+ var import_react14 = __toESM(require("react"), 1);
7469
7469
 
7470
7470
  // src/components/Input/Input.tsx
7471
7471
  var import_react8 = __toESM(require("react"), 1);
@@ -7638,11 +7638,149 @@ PasswordInput.displayName = "PasswordInput";
7638
7638
  var PasswordInput_default = PasswordInput;
7639
7639
 
7640
7640
  // src/components/Modal/Modal.tsx
7641
- var import_react11 = __toESM(require("react"), 1);
7641
+ var import_react12 = __toESM(require("react"), 1);
7642
7642
  var import_react_dom = require("react-dom");
7643
7643
 
7644
7644
  // src/tokens/hooks/useOverlayKeyboard.ts
7645
+ var import_react11 = __toESM(require("react"), 1);
7646
+
7647
+ // src/tokens/hooks/useAutoPosition.ts
7645
7648
  var import_react10 = __toESM(require("react"), 1);
7649
+ var findScrollParent = (el) => {
7650
+ for (let p = el.parentElement; p; p = p.parentElement) {
7651
+ const { overflowY, overflowX } = getComputedStyle(p);
7652
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
7653
+ }
7654
+ return null;
7655
+ };
7656
+ var TRIGGER_GAP = 8;
7657
+ var computePlacement = (triggerRect, popW, popH, clip) => {
7658
+ const roomBelow = clip.bottom - triggerRect.bottom - TRIGGER_GAP;
7659
+ const roomAbove = triggerRect.top - clip.top - TRIGGER_GAP;
7660
+ let direction;
7661
+ let top;
7662
+ let maxHeight = null;
7663
+ if (popH <= roomBelow) {
7664
+ direction = "bottom";
7665
+ top = triggerRect.bottom + TRIGGER_GAP;
7666
+ } else if (popH <= roomAbove) {
7667
+ direction = "top";
7668
+ top = triggerRect.top - TRIGGER_GAP - popH;
7669
+ } else {
7670
+ const room = Math.max(roomBelow, roomAbove, 0);
7671
+ if (roomBelow >= roomAbove) {
7672
+ direction = "bottom";
7673
+ top = triggerRect.bottom + TRIGGER_GAP;
7674
+ } else {
7675
+ direction = "top";
7676
+ top = triggerRect.top - TRIGGER_GAP - room;
7677
+ }
7678
+ maxHeight = room;
7679
+ }
7680
+ let left = triggerRect.left;
7681
+ if (left + popW > clip.right - 8) {
7682
+ left = triggerRect.right - popW;
7683
+ }
7684
+ if (left < clip.left + 8) left = clip.left + 8;
7685
+ const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
7686
+ return {
7687
+ direction,
7688
+ top,
7689
+ left,
7690
+ maxHeight,
7691
+ over: {
7692
+ top: Math.max(0, clip.top - top),
7693
+ right: Math.max(0, left + popW - clip.right),
7694
+ bottom: Math.max(0, top + drawnH - clip.bottom),
7695
+ left: Math.max(0, clip.left - left)
7696
+ }
7697
+ };
7698
+ };
7699
+ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7700
+ const directionRef = import_react10.default.useRef("bottom");
7701
+ const sizeRef = import_react10.default.useRef(null);
7702
+ const scrollParentRef = import_react10.default.useRef(null);
7703
+ const placedRef = import_react10.default.useRef(false);
7704
+ const calculatePosition = import_react10.default.useCallback((remeasure = false) => {
7705
+ const pop = popRef.current;
7706
+ if (!triggerRef.current || !pop) return;
7707
+ if (remeasure || !sizeRef.current) {
7708
+ sizeRef.current = {
7709
+ w: pop.offsetWidth,
7710
+ h: Math.max(pop.offsetHeight, pop.scrollHeight)
7711
+ };
7712
+ }
7713
+ const { w: popW, h: popH } = sizeRef.current;
7714
+ const triggerRect = triggerRef.current.getBoundingClientRect();
7715
+ if (popH === 0 || popW === 0) {
7716
+ sizeRef.current = null;
7717
+ return;
7718
+ }
7719
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
7720
+ const clip = {
7721
+ top: Math.max(parentRect?.top ?? 0, 0),
7722
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
7723
+ left: Math.max(parentRect?.left ?? 0, 0),
7724
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
7725
+ };
7726
+ const first = !placedRef.current;
7727
+ if (first) pop.style.transition = "none";
7728
+ const { direction: next, top, left, over, maxHeight } = computePlacement(
7729
+ triggerRect,
7730
+ popW,
7731
+ popH,
7732
+ clip
7733
+ );
7734
+ pop.style.top = `${top + window.scrollY}px`;
7735
+ pop.style.left = `${left + window.scrollX}px`;
7736
+ pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
7737
+ 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";
7738
+ directionRef.current = next;
7739
+ pop.classList.toggle("top", next === "top");
7740
+ pop.classList.toggle("bottom", next === "bottom");
7741
+ if (first) {
7742
+ void pop.offsetHeight;
7743
+ pop.style.transition = "";
7744
+ placedRef.current = true;
7745
+ }
7746
+ }, [triggerRef, popRef]);
7747
+ import_react10.default.useLayoutEffect(() => {
7748
+ if (!enabled) {
7749
+ sizeRef.current = null;
7750
+ scrollParentRef.current = null;
7751
+ placedRef.current = false;
7752
+ return;
7753
+ }
7754
+ if (triggerRef.current) {
7755
+ scrollParentRef.current = findScrollParent(triggerRef.current);
7756
+ }
7757
+ calculatePosition(true);
7758
+ const raf = requestAnimationFrame(() => calculatePosition(true));
7759
+ return () => cancelAnimationFrame(raf);
7760
+ }, [calculatePosition, enabled, triggerRef]);
7761
+ import_react10.default.useEffect(() => {
7762
+ if (!enabled || !popRef.current) return;
7763
+ const observer = new ResizeObserver(() => {
7764
+ calculatePosition(true);
7765
+ });
7766
+ observer.observe(popRef.current);
7767
+ return () => observer.disconnect();
7768
+ }, [calculatePosition, enabled, popRef]);
7769
+ import_react10.default.useEffect(() => {
7770
+ if (!enabled) return;
7771
+ const onScroll = () => calculatePosition();
7772
+ const onResize = () => calculatePosition(true);
7773
+ window.addEventListener("resize", onResize, { passive: true });
7774
+ window.addEventListener("scroll", onScroll, { passive: true, capture: true });
7775
+ return () => {
7776
+ window.removeEventListener("resize", onResize);
7777
+ window.removeEventListener("scroll", onScroll, true);
7778
+ };
7779
+ }, [calculatePosition, enabled]);
7780
+ };
7781
+ var useAutoPosition_default = useAutoPosition;
7782
+
7783
+ // src/tokens/hooks/useOverlayKeyboard.ts
7646
7784
  var FOCUSABLE = [
7647
7785
  "a[href]",
7648
7786
  "button:not([disabled])",
@@ -7656,7 +7794,7 @@ var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
7656
7794
  (n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
7657
7795
  );
7658
7796
  var useEscapeKey = (enabled, onEscape) => {
7659
- import_react10.default.useEffect(() => {
7797
+ import_react11.default.useEffect(() => {
7660
7798
  if (!enabled) return;
7661
7799
  const onKey = (e) => {
7662
7800
  if (e.key !== "Escape") return;
@@ -7670,8 +7808,8 @@ var useEscapeKey = (enabled, onEscape) => {
7670
7808
  };
7671
7809
  var useFocusTrap = (containerRef, enabled, options = {}) => {
7672
7810
  const { trap = false, initialFocus } = options;
7673
- const restoreRef = import_react10.default.useRef(null);
7674
- import_react10.default.useEffect(() => {
7811
+ const restoreRef = import_react11.default.useRef(null);
7812
+ import_react11.default.useEffect(() => {
7675
7813
  if (!enabled) return;
7676
7814
  restoreRef.current = document.activeElement;
7677
7815
  const raf = requestAnimationFrame(() => {
@@ -7689,7 +7827,7 @@ var useFocusTrap = (containerRef, enabled, options = {}) => {
7689
7827
  if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
7690
7828
  };
7691
7829
  }, [enabled, containerRef, initialFocus]);
7692
- import_react10.default.useEffect(() => {
7830
+ import_react11.default.useEffect(() => {
7693
7831
  if (!enabled || !trap) return;
7694
7832
  const onKey = (e) => {
7695
7833
  if (e.key !== "Tab") return;
@@ -7715,22 +7853,25 @@ var useFocusTrap = (containerRef, enabled, options = {}) => {
7715
7853
  return () => document.removeEventListener("keydown", onKey);
7716
7854
  }, [enabled, trap, containerRef]);
7717
7855
  };
7718
- var useCloseOnContainerScroll = (enabled, popRef, onClose) => {
7719
- const onCloseRef = import_react10.default.useRef(onClose);
7856
+ var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
7857
+ const onCloseRef = import_react11.default.useRef(onClose);
7720
7858
  onCloseRef.current = onClose;
7721
- import_react10.default.useEffect(() => {
7722
- if (!enabled) return;
7723
- const onScroll = (e) => {
7724
- const target = e.target;
7725
- if (target === document || target === document.documentElement || target === document.body) {
7726
- return;
7727
- }
7728
- if (target instanceof Node && popRef.current?.contains(target)) return;
7729
- onCloseRef.current();
7730
- };
7731
- window.addEventListener("scroll", onScroll, { passive: true, capture: true });
7732
- return () => window.removeEventListener("scroll", onScroll, true);
7733
- }, [enabled, popRef]);
7859
+ import_react11.default.useEffect(() => {
7860
+ const trigger = triggerRef.current;
7861
+ if (!enabled || !trigger) return;
7862
+ const observer = new IntersectionObserver(
7863
+ ([entry]) => {
7864
+ if (entry.isIntersecting) return;
7865
+ if (!popRef.current?.contains(document.activeElement)) return;
7866
+ onCloseRef.current();
7867
+ trigger.focus({ preventScroll: true });
7868
+ },
7869
+ // 그릇이 없으면 root: null → 뷰포트 기준
7870
+ { root: findScrollParent(trigger), threshold: 0 }
7871
+ );
7872
+ observer.observe(trigger);
7873
+ return () => observer.disconnect();
7874
+ }, [enabled, triggerRef, popRef]);
7734
7875
  };
7735
7876
 
7736
7877
  // src/components/Modal/Modal.tsx
@@ -7738,13 +7879,13 @@ var import_jsx_runtime313 = require("react/jsx-runtime");
7738
7879
  var ANIMATION_DURATION_MS = 200;
7739
7880
  var Modal = (props) => {
7740
7881
  const { isOpen, onClose, children } = props;
7741
- const [mounted, setMounted] = import_react11.default.useState(false);
7742
- const [visible, setVisible] = import_react11.default.useState(false);
7743
- const [settled, setSettled] = import_react11.default.useState(false);
7744
- const boxRef = import_react11.default.useRef(null);
7882
+ const [mounted, setMounted] = import_react12.default.useState(false);
7883
+ const [visible, setVisible] = import_react12.default.useState(false);
7884
+ const [settled, setSettled] = import_react12.default.useState(false);
7885
+ const boxRef = import_react12.default.useRef(null);
7745
7886
  useEscapeKey(isOpen, onClose);
7746
7887
  useFocusTrap(boxRef, isOpen && mounted, { trap: true });
7747
- import_react11.default.useEffect(() => {
7888
+ import_react12.default.useEffect(() => {
7748
7889
  if (isOpen) {
7749
7890
  setMounted(true);
7750
7891
  const show = setTimeout(() => setVisible(true), 1);
@@ -7788,9 +7929,9 @@ Modal.displayName = "Modal";
7788
7929
  var Modal_default = Modal;
7789
7930
 
7790
7931
  // src/components/DatePicker/SingleDatePicker/index.tsx
7791
- var import_react12 = __toESM(require("react"), 1);
7932
+ var import_react13 = __toESM(require("react"), 1);
7792
7933
  var import_jsx_runtime314 = require("react/jsx-runtime");
7793
- var DayCell2 = import_react12.default.memo(
7934
+ var DayCell2 = import_react13.default.memo(
7794
7935
  ({
7795
7936
  day,
7796
7937
  disabled,
@@ -7839,33 +7980,33 @@ var SingleDatePicker = (props) => {
7839
7980
  required,
7840
7981
  validations
7841
7982
  } = props;
7842
- const labelId = import_react12.default.useId();
7983
+ const labelId = import_react13.default.useId();
7843
7984
  const initialYear = value?.getFullYear();
7844
7985
  const initialMonth = value?.getMonth();
7845
7986
  const { year, month, days, goToPrevMonth, goToNextMonth, setYear, setMonth } = useCalendar(
7846
7987
  initialYear,
7847
7988
  initialMonth
7848
7989
  );
7849
- const [pickerMode, setPickerMode] = import_react12.default.useState("days");
7850
- const [yearRangeStart, setYearRangeStart] = import_react12.default.useState(
7990
+ const [pickerMode, setPickerMode] = import_react13.default.useState("days");
7991
+ const [yearRangeStart, setYearRangeStart] = import_react13.default.useState(
7851
7992
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
7852
7993
  );
7853
- const minTime = import_react12.default.useMemo(
7994
+ const minTime = import_react13.default.useMemo(
7854
7995
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
7855
7996
  [minDate]
7856
7997
  );
7857
- const maxTime = import_react12.default.useMemo(
7998
+ const maxTime = import_react13.default.useMemo(
7858
7999
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
7859
8000
  [maxDate]
7860
8001
  );
7861
- const highlightSet = import_react12.default.useMemo(() => {
8002
+ const highlightSet = import_react13.default.useMemo(() => {
7862
8003
  const set = /* @__PURE__ */ new Set();
7863
8004
  for (const h of highlightDates) {
7864
8005
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
7865
8006
  }
7866
8007
  return set;
7867
8008
  }, [highlightDates]);
7868
- const handleSelect = import_react12.default.useCallback(
8009
+ const handleSelect = import_react13.default.useCallback(
7869
8010
  (date) => {
7870
8011
  onChange?.(date);
7871
8012
  },
@@ -8008,8 +8149,8 @@ var InputDatePicker = (props) => {
8008
8149
  required,
8009
8150
  validations
8010
8151
  } = props;
8011
- const [isOpen, setIsOpen] = import_react13.default.useState(false);
8012
- const [tempDate, setTempDate] = import_react13.default.useState(value ?? /* @__PURE__ */ new Date());
8152
+ const [isOpen, setIsOpen] = import_react14.default.useState(false);
8153
+ const [tempDate, setTempDate] = import_react14.default.useState(value ?? /* @__PURE__ */ new Date());
8013
8154
  const handleOpen = () => {
8014
8155
  if (disabled) return;
8015
8156
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -8061,18 +8202,18 @@ InputDatePicker.displayName = "InputDatePicker";
8061
8202
  var InputDatePicker_default = InputDatePicker;
8062
8203
 
8063
8204
  // src/components/DatePicker/PopupPicker/index.tsx
8064
- var import_react17 = __toESM(require("react"), 1);
8205
+ var import_react18 = __toESM(require("react"), 1);
8065
8206
 
8066
8207
  // src/components/DatePicker/RangePicker/index.tsx
8067
- var import_react16 = __toESM(require("react"), 1);
8208
+ var import_react17 = __toESM(require("react"), 1);
8068
8209
 
8069
8210
  // src/components/Tab/Tab.tsx
8070
- var import_react15 = __toESM(require("react"), 1);
8211
+ var import_react16 = __toESM(require("react"), 1);
8071
8212
 
8072
8213
  // src/components/Tab/TabItem.tsx
8073
- var import_react14 = __toESM(require("react"), 1);
8214
+ var import_react15 = __toESM(require("react"), 1);
8074
8215
  var import_jsx_runtime316 = require("react/jsx-runtime");
8075
- var TabItem = import_react14.default.forwardRef((props, ref) => {
8216
+ var TabItem = import_react15.default.forwardRef((props, ref) => {
8076
8217
  const { isActive: isActive2, title, onClick } = props;
8077
8218
  return /* @__PURE__ */ (0, import_jsx_runtime316.jsx)(
8078
8219
  "button",
@@ -8096,11 +8237,11 @@ var import_jsx_runtime317 = require("react/jsx-runtime");
8096
8237
  var Tab = (props) => {
8097
8238
  const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
8098
8239
  const shape = variant ?? type ?? "default";
8099
- const [underlineStyle, setUnderlineStyle] = import_react15.default.useState({
8240
+ const [underlineStyle, setUnderlineStyle] = import_react16.default.useState({
8100
8241
  left: 0,
8101
8242
  width: 0
8102
8243
  });
8103
- const itemRefs = import_react15.default.useRef([]);
8244
+ const itemRefs = import_react16.default.useRef([]);
8104
8245
  const handleKeyDown = (e) => {
8105
8246
  const last = tabs.length - 1;
8106
8247
  let next = null;
@@ -8116,7 +8257,7 @@ var Tab = (props) => {
8116
8257
  const handleChangeActiveTab = (tabItem, tabIdx) => {
8117
8258
  onChange(tabItem, tabIdx);
8118
8259
  };
8119
- import_react15.default.useEffect(() => {
8260
+ import_react16.default.useEffect(() => {
8120
8261
  const el = itemRefs.current[activeIndex];
8121
8262
  if (el) {
8122
8263
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
@@ -8172,8 +8313,8 @@ var RangePicker = (props) => {
8172
8313
  required,
8173
8314
  validations
8174
8315
  } = props;
8175
- const labelId = import_react16.default.useId();
8176
- const [activeTab, setActiveTab] = import_react16.default.useState("start");
8316
+ const labelId = import_react17.default.useId();
8317
+ const [activeTab, setActiveTab] = import_react17.default.useState("start");
8177
8318
  const handleStartChange = (date) => {
8178
8319
  if (!date) return;
8179
8320
  const newStart = date > endDate ? endDate : date;
@@ -8267,7 +8408,7 @@ var RangePicker_default = RangePicker;
8267
8408
  var import_jsx_runtime319 = require("react/jsx-runtime");
8268
8409
  var PopupPicker = (props) => {
8269
8410
  const { component, type, locale } = props;
8270
- const [isOpen, setIsOpen] = import_react17.default.useState(false);
8411
+ const [isOpen, setIsOpen] = import_react18.default.useState(false);
8271
8412
  const handleClick = () => setIsOpen(true);
8272
8413
  const handleClose = () => setIsOpen(false);
8273
8414
  const handleSingleChange = (date) => {
@@ -8276,7 +8417,7 @@ var PopupPicker = (props) => {
8276
8417
  handleClose();
8277
8418
  };
8278
8419
  return /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: "lib-xplat-popup-datepicker", children: [
8279
- import_react17.default.cloneElement(component, { onClick: handleClick }),
8420
+ import_react18.default.cloneElement(component, { onClick: handleClick }),
8280
8421
  /* @__PURE__ */ (0, import_jsx_runtime319.jsx)(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
8281
8422
  /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: "popup-datepicker-content", children: [
8282
8423
  type === "single" && /* @__PURE__ */ (0, import_jsx_runtime319.jsx)(
@@ -8335,18 +8476,18 @@ Divider.displayName = "Divider";
8335
8476
  var Divider_default = Divider;
8336
8477
 
8337
8478
  // src/components/Drawer/Drawer.tsx
8338
- var import_react18 = __toESM(require("react"), 1);
8479
+ var import_react19 = __toESM(require("react"), 1);
8339
8480
  var import_react_dom2 = require("react-dom");
8340
8481
  var import_jsx_runtime321 = require("react/jsx-runtime");
8341
8482
  var ANIMATION_DURATION_MS2 = 250;
8342
8483
  var Drawer = (props) => {
8343
8484
  const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
8344
- const [mounted, setMounted] = import_react18.default.useState(false);
8345
- const [visible, setVisible] = import_react18.default.useState(false);
8346
- const panelRef = import_react18.default.useRef(null);
8485
+ const [mounted, setMounted] = import_react19.default.useState(false);
8486
+ const [visible, setVisible] = import_react19.default.useState(false);
8487
+ const panelRef = import_react19.default.useRef(null);
8347
8488
  useEscapeKey(isOpen, onClose);
8348
8489
  useFocusTrap(panelRef, isOpen && mounted, { trap: true });
8349
- import_react18.default.useEffect(() => {
8490
+ import_react19.default.useEffect(() => {
8350
8491
  if (isOpen) {
8351
8492
  setMounted(true);
8352
8493
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -8402,142 +8543,6 @@ var Portal = ({ children }) => {
8402
8543
  Portal.displayName = "Portal";
8403
8544
  var Portal_default = Portal;
8404
8545
 
8405
- // src/tokens/hooks/useAutoPosition.ts
8406
- var import_react19 = __toESM(require("react"), 1);
8407
- var findScrollParent = (el) => {
8408
- for (let p = el.parentElement; p; p = p.parentElement) {
8409
- const { overflowY, overflowX } = getComputedStyle(p);
8410
- if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
8411
- }
8412
- return null;
8413
- };
8414
- var TRIGGER_GAP = 8;
8415
- var computePlacement = (triggerRect, popW, popH, clip) => {
8416
- const roomBelow = clip.bottom - triggerRect.bottom - TRIGGER_GAP;
8417
- const roomAbove = triggerRect.top - clip.top - TRIGGER_GAP;
8418
- let direction;
8419
- let top;
8420
- let maxHeight = null;
8421
- if (popH <= roomBelow) {
8422
- direction = "bottom";
8423
- top = triggerRect.bottom + TRIGGER_GAP;
8424
- } else if (popH <= roomAbove) {
8425
- direction = "top";
8426
- top = triggerRect.top - TRIGGER_GAP - popH;
8427
- } else {
8428
- const room = Math.max(roomBelow, roomAbove, 0);
8429
- if (roomBelow >= roomAbove) {
8430
- direction = "bottom";
8431
- top = triggerRect.bottom + TRIGGER_GAP;
8432
- } else {
8433
- direction = "top";
8434
- top = triggerRect.top - TRIGGER_GAP - room;
8435
- }
8436
- maxHeight = room;
8437
- }
8438
- let left = triggerRect.left;
8439
- if (left + popW > clip.right - 8) {
8440
- left = triggerRect.right - popW;
8441
- }
8442
- if (left < clip.left + 8) left = clip.left + 8;
8443
- const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
8444
- return {
8445
- direction,
8446
- top,
8447
- left,
8448
- maxHeight,
8449
- over: {
8450
- top: Math.max(0, clip.top - top),
8451
- right: Math.max(0, left + popW - clip.right),
8452
- bottom: Math.max(0, top + drawnH - clip.bottom),
8453
- left: Math.max(0, clip.left - left)
8454
- }
8455
- };
8456
- };
8457
- var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8458
- const directionRef = import_react19.default.useRef("bottom");
8459
- const sizeRef = import_react19.default.useRef(null);
8460
- const scrollParentRef = import_react19.default.useRef(null);
8461
- const placedRef = import_react19.default.useRef(false);
8462
- const calculatePosition = import_react19.default.useCallback((remeasure = false) => {
8463
- const pop = popRef.current;
8464
- if (!triggerRef.current || !pop) return;
8465
- if (remeasure || !sizeRef.current) {
8466
- sizeRef.current = {
8467
- w: pop.offsetWidth,
8468
- h: Math.max(pop.offsetHeight, pop.scrollHeight)
8469
- };
8470
- }
8471
- const { w: popW, h: popH } = sizeRef.current;
8472
- const triggerRect = triggerRef.current.getBoundingClientRect();
8473
- if (popH === 0 || popW === 0) {
8474
- sizeRef.current = null;
8475
- return;
8476
- }
8477
- const parentRect = scrollParentRef.current?.getBoundingClientRect();
8478
- const clip = {
8479
- top: Math.max(parentRect?.top ?? 0, 0),
8480
- bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
8481
- left: Math.max(parentRect?.left ?? 0, 0),
8482
- right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
8483
- };
8484
- const first = !placedRef.current;
8485
- if (first) pop.style.transition = "none";
8486
- const { direction: next, top, left, over, maxHeight } = computePlacement(
8487
- triggerRect,
8488
- popW,
8489
- popH,
8490
- clip
8491
- );
8492
- pop.style.top = `${top + window.scrollY}px`;
8493
- pop.style.left = `${left + window.scrollX}px`;
8494
- pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
8495
- 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";
8496
- directionRef.current = next;
8497
- pop.classList.toggle("top", next === "top");
8498
- pop.classList.toggle("bottom", next === "bottom");
8499
- if (first) {
8500
- void pop.offsetHeight;
8501
- pop.style.transition = "";
8502
- placedRef.current = true;
8503
- }
8504
- }, [triggerRef, popRef]);
8505
- import_react19.default.useLayoutEffect(() => {
8506
- if (!enabled) {
8507
- sizeRef.current = null;
8508
- scrollParentRef.current = null;
8509
- placedRef.current = false;
8510
- return;
8511
- }
8512
- if (triggerRef.current) {
8513
- scrollParentRef.current = findScrollParent(triggerRef.current);
8514
- }
8515
- calculatePosition(true);
8516
- const raf = requestAnimationFrame(() => calculatePosition(true));
8517
- return () => cancelAnimationFrame(raf);
8518
- }, [calculatePosition, enabled, triggerRef]);
8519
- import_react19.default.useEffect(() => {
8520
- if (!enabled || !popRef.current) return;
8521
- const observer = new ResizeObserver(() => {
8522
- calculatePosition(true);
8523
- });
8524
- observer.observe(popRef.current);
8525
- return () => observer.disconnect();
8526
- }, [calculatePosition, enabled, popRef]);
8527
- import_react19.default.useEffect(() => {
8528
- if (!enabled) return;
8529
- const onScroll = () => calculatePosition();
8530
- const onResize = () => calculatePosition(true);
8531
- window.addEventListener("resize", onResize, { passive: true });
8532
- window.addEventListener("scroll", onScroll, { passive: true, capture: true });
8533
- return () => {
8534
- window.removeEventListener("resize", onResize);
8535
- window.removeEventListener("scroll", onScroll, true);
8536
- };
8537
- }, [calculatePosition, enabled]);
8538
- };
8539
- var useAutoPosition_default = useAutoPosition;
8540
-
8541
8546
  // src/tokens/hooks/useClickOutside.ts
8542
8547
  var import_react20 = __toESM(require("react"), 1);
8543
8548
  var useClickOutside = (refs, handler, enabled = true) => {
@@ -8574,7 +8579,7 @@ var Dropdown = (props) => {
8574
8579
  const menuRef = import_react21.default.useRef(null);
8575
8580
  useAutoPosition_default(triggerRef, menuRef, mounted);
8576
8581
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
8577
- useCloseOnContainerScroll(isOpen, menuRef, () => setIsOpen(false));
8582
+ useCloseWhenFocusHidden(isOpen, triggerRef, menuRef, () => setIsOpen(false));
8578
8583
  useEscapeKey(isOpen, () => {
8579
8584
  setIsOpen(false);
8580
8585
  triggerRef.current?.focus({ preventScroll: true });
@@ -10505,7 +10510,7 @@ var PopOver = (props) => {
10505
10510
  const [localOpen, setLocalOpen] = import_react27.default.useState(false);
10506
10511
  const [eventTrigger, setEventTrigger] = import_react27.default.useState(false);
10507
10512
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
10508
- useCloseOnContainerScroll(isOpen, popRef, onClose);
10513
+ useCloseWhenFocusHidden(isOpen, triggerRef, popRef, onClose);
10509
10514
  useEscapeKey(isOpen, () => {
10510
10515
  onClose();
10511
10516
  triggerRef.current?.focus({ preventScroll: true });
@@ -10785,7 +10790,7 @@ var SelectRoot = (props) => {
10785
10790
  }, []);
10786
10791
  const toggle = import_react31.default.useCallback(() => setOpen((prev) => !prev), []);
10787
10792
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
10788
- useCloseOnContainerScroll(isOpen, contentRef, close);
10793
+ useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
10789
10794
  useEscapeKey(isOpen, () => {
10790
10795
  close();
10791
10796
  triggerRef.current?.focus({ preventScroll: true });
@@ -11726,7 +11731,7 @@ var TimePicker = (props) => {
11726
11731
  }, [step, min, max]);
11727
11732
  const close = import_react40.default.useCallback(() => setOpen(false), []);
11728
11733
  useClickOutside_default([triggerRef, contentRef], close, isOpen);
11729
- useCloseOnContainerScroll(isOpen, contentRef, close);
11734
+ useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
11730
11735
  useEscapeKey(isOpen, () => {
11731
11736
  close();
11732
11737
  triggerRef.current?.focus({ preventScroll: true });