@x-plat/design-system 0.14.13 → 0.14.15

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,22 @@ 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 useCloseWhenTriggerHidden = (enabled, triggerRef, 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) onCloseRef.current();
7865
+ },
7866
+ // 그릇이 없으면 root: null → 뷰포트 기준
7867
+ { root: findScrollParent(trigger), threshold: 0 }
7868
+ );
7869
+ observer.observe(trigger);
7870
+ return () => observer.disconnect();
7871
+ }, [enabled, triggerRef]);
7734
7872
  };
7735
7873
 
7736
7874
  // src/components/Modal/Modal.tsx
@@ -7738,13 +7876,13 @@ var import_jsx_runtime313 = require("react/jsx-runtime");
7738
7876
  var ANIMATION_DURATION_MS = 200;
7739
7877
  var Modal = (props) => {
7740
7878
  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);
7879
+ const [mounted, setMounted] = import_react12.default.useState(false);
7880
+ const [visible, setVisible] = import_react12.default.useState(false);
7881
+ const [settled, setSettled] = import_react12.default.useState(false);
7882
+ const boxRef = import_react12.default.useRef(null);
7745
7883
  useEscapeKey(isOpen, onClose);
7746
7884
  useFocusTrap(boxRef, isOpen && mounted, { trap: true });
7747
- import_react11.default.useEffect(() => {
7885
+ import_react12.default.useEffect(() => {
7748
7886
  if (isOpen) {
7749
7887
  setMounted(true);
7750
7888
  const show = setTimeout(() => setVisible(true), 1);
@@ -7788,9 +7926,9 @@ Modal.displayName = "Modal";
7788
7926
  var Modal_default = Modal;
7789
7927
 
7790
7928
  // src/components/DatePicker/SingleDatePicker/index.tsx
7791
- var import_react12 = __toESM(require("react"), 1);
7929
+ var import_react13 = __toESM(require("react"), 1);
7792
7930
  var import_jsx_runtime314 = require("react/jsx-runtime");
7793
- var DayCell2 = import_react12.default.memo(
7931
+ var DayCell2 = import_react13.default.memo(
7794
7932
  ({
7795
7933
  day,
7796
7934
  disabled,
@@ -7839,33 +7977,33 @@ var SingleDatePicker = (props) => {
7839
7977
  required,
7840
7978
  validations
7841
7979
  } = props;
7842
- const labelId = import_react12.default.useId();
7980
+ const labelId = import_react13.default.useId();
7843
7981
  const initialYear = value?.getFullYear();
7844
7982
  const initialMonth = value?.getMonth();
7845
7983
  const { year, month, days, goToPrevMonth, goToNextMonth, setYear, setMonth } = useCalendar(
7846
7984
  initialYear,
7847
7985
  initialMonth
7848
7986
  );
7849
- const [pickerMode, setPickerMode] = import_react12.default.useState("days");
7850
- const [yearRangeStart, setYearRangeStart] = import_react12.default.useState(
7987
+ const [pickerMode, setPickerMode] = import_react13.default.useState("days");
7988
+ const [yearRangeStart, setYearRangeStart] = import_react13.default.useState(
7851
7989
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
7852
7990
  );
7853
- const minTime = import_react12.default.useMemo(
7991
+ const minTime = import_react13.default.useMemo(
7854
7992
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
7855
7993
  [minDate]
7856
7994
  );
7857
- const maxTime = import_react12.default.useMemo(
7995
+ const maxTime = import_react13.default.useMemo(
7858
7996
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
7859
7997
  [maxDate]
7860
7998
  );
7861
- const highlightSet = import_react12.default.useMemo(() => {
7999
+ const highlightSet = import_react13.default.useMemo(() => {
7862
8000
  const set = /* @__PURE__ */ new Set();
7863
8001
  for (const h of highlightDates) {
7864
8002
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
7865
8003
  }
7866
8004
  return set;
7867
8005
  }, [highlightDates]);
7868
- const handleSelect = import_react12.default.useCallback(
8006
+ const handleSelect = import_react13.default.useCallback(
7869
8007
  (date) => {
7870
8008
  onChange?.(date);
7871
8009
  },
@@ -8008,8 +8146,8 @@ var InputDatePicker = (props) => {
8008
8146
  required,
8009
8147
  validations
8010
8148
  } = props;
8011
- const [isOpen, setIsOpen] = import_react13.default.useState(false);
8012
- const [tempDate, setTempDate] = import_react13.default.useState(value ?? /* @__PURE__ */ new Date());
8149
+ const [isOpen, setIsOpen] = import_react14.default.useState(false);
8150
+ const [tempDate, setTempDate] = import_react14.default.useState(value ?? /* @__PURE__ */ new Date());
8013
8151
  const handleOpen = () => {
8014
8152
  if (disabled) return;
8015
8153
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -8061,18 +8199,18 @@ InputDatePicker.displayName = "InputDatePicker";
8061
8199
  var InputDatePicker_default = InputDatePicker;
8062
8200
 
8063
8201
  // src/components/DatePicker/PopupPicker/index.tsx
8064
- var import_react17 = __toESM(require("react"), 1);
8202
+ var import_react18 = __toESM(require("react"), 1);
8065
8203
 
8066
8204
  // src/components/DatePicker/RangePicker/index.tsx
8067
- var import_react16 = __toESM(require("react"), 1);
8205
+ var import_react17 = __toESM(require("react"), 1);
8068
8206
 
8069
8207
  // src/components/Tab/Tab.tsx
8070
- var import_react15 = __toESM(require("react"), 1);
8208
+ var import_react16 = __toESM(require("react"), 1);
8071
8209
 
8072
8210
  // src/components/Tab/TabItem.tsx
8073
- var import_react14 = __toESM(require("react"), 1);
8211
+ var import_react15 = __toESM(require("react"), 1);
8074
8212
  var import_jsx_runtime316 = require("react/jsx-runtime");
8075
- var TabItem = import_react14.default.forwardRef((props, ref) => {
8213
+ var TabItem = import_react15.default.forwardRef((props, ref) => {
8076
8214
  const { isActive: isActive2, title, onClick } = props;
8077
8215
  return /* @__PURE__ */ (0, import_jsx_runtime316.jsx)(
8078
8216
  "button",
@@ -8096,11 +8234,11 @@ var import_jsx_runtime317 = require("react/jsx-runtime");
8096
8234
  var Tab = (props) => {
8097
8235
  const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
8098
8236
  const shape = variant ?? type ?? "default";
8099
- const [underlineStyle, setUnderlineStyle] = import_react15.default.useState({
8237
+ const [underlineStyle, setUnderlineStyle] = import_react16.default.useState({
8100
8238
  left: 0,
8101
8239
  width: 0
8102
8240
  });
8103
- const itemRefs = import_react15.default.useRef([]);
8241
+ const itemRefs = import_react16.default.useRef([]);
8104
8242
  const handleKeyDown = (e) => {
8105
8243
  const last = tabs.length - 1;
8106
8244
  let next = null;
@@ -8116,7 +8254,7 @@ var Tab = (props) => {
8116
8254
  const handleChangeActiveTab = (tabItem, tabIdx) => {
8117
8255
  onChange(tabItem, tabIdx);
8118
8256
  };
8119
- import_react15.default.useEffect(() => {
8257
+ import_react16.default.useEffect(() => {
8120
8258
  const el = itemRefs.current[activeIndex];
8121
8259
  if (el) {
8122
8260
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
@@ -8172,8 +8310,8 @@ var RangePicker = (props) => {
8172
8310
  required,
8173
8311
  validations
8174
8312
  } = props;
8175
- const labelId = import_react16.default.useId();
8176
- const [activeTab, setActiveTab] = import_react16.default.useState("start");
8313
+ const labelId = import_react17.default.useId();
8314
+ const [activeTab, setActiveTab] = import_react17.default.useState("start");
8177
8315
  const handleStartChange = (date) => {
8178
8316
  if (!date) return;
8179
8317
  const newStart = date > endDate ? endDate : date;
@@ -8267,7 +8405,7 @@ var RangePicker_default = RangePicker;
8267
8405
  var import_jsx_runtime319 = require("react/jsx-runtime");
8268
8406
  var PopupPicker = (props) => {
8269
8407
  const { component, type, locale } = props;
8270
- const [isOpen, setIsOpen] = import_react17.default.useState(false);
8408
+ const [isOpen, setIsOpen] = import_react18.default.useState(false);
8271
8409
  const handleClick = () => setIsOpen(true);
8272
8410
  const handleClose = () => setIsOpen(false);
8273
8411
  const handleSingleChange = (date) => {
@@ -8276,7 +8414,7 @@ var PopupPicker = (props) => {
8276
8414
  handleClose();
8277
8415
  };
8278
8416
  return /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: "lib-xplat-popup-datepicker", children: [
8279
- import_react17.default.cloneElement(component, { onClick: handleClick }),
8417
+ import_react18.default.cloneElement(component, { onClick: handleClick }),
8280
8418
  /* @__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
8419
  /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: "popup-datepicker-content", children: [
8282
8420
  type === "single" && /* @__PURE__ */ (0, import_jsx_runtime319.jsx)(
@@ -8335,18 +8473,18 @@ Divider.displayName = "Divider";
8335
8473
  var Divider_default = Divider;
8336
8474
 
8337
8475
  // src/components/Drawer/Drawer.tsx
8338
- var import_react18 = __toESM(require("react"), 1);
8476
+ var import_react19 = __toESM(require("react"), 1);
8339
8477
  var import_react_dom2 = require("react-dom");
8340
8478
  var import_jsx_runtime321 = require("react/jsx-runtime");
8341
8479
  var ANIMATION_DURATION_MS2 = 250;
8342
8480
  var Drawer = (props) => {
8343
8481
  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);
8482
+ const [mounted, setMounted] = import_react19.default.useState(false);
8483
+ const [visible, setVisible] = import_react19.default.useState(false);
8484
+ const panelRef = import_react19.default.useRef(null);
8347
8485
  useEscapeKey(isOpen, onClose);
8348
8486
  useFocusTrap(panelRef, isOpen && mounted, { trap: true });
8349
- import_react18.default.useEffect(() => {
8487
+ import_react19.default.useEffect(() => {
8350
8488
  if (isOpen) {
8351
8489
  setMounted(true);
8352
8490
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -8402,141 +8540,6 @@ var Portal = ({ children }) => {
8402
8540
  Portal.displayName = "Portal";
8403
8541
  var Portal_default = Portal;
8404
8542
 
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 computePlacement = (triggerRect, popW, popH, clip) => {
8415
- const roomBelow = clip.bottom - triggerRect.bottom;
8416
- const roomAbove = triggerRect.top - clip.top;
8417
- let direction;
8418
- let top;
8419
- let maxHeight = null;
8420
- if (popH <= roomBelow) {
8421
- direction = "bottom";
8422
- top = triggerRect.bottom;
8423
- } else if (popH <= roomAbove) {
8424
- direction = "top";
8425
- top = triggerRect.top - popH;
8426
- } else {
8427
- const room = Math.max(roomBelow, roomAbove, 0);
8428
- if (roomBelow >= roomAbove) {
8429
- direction = "bottom";
8430
- top = triggerRect.bottom;
8431
- } else {
8432
- direction = "top";
8433
- top = triggerRect.top - room;
8434
- }
8435
- maxHeight = room;
8436
- }
8437
- let left = triggerRect.left;
8438
- if (left + popW > clip.right - 8) {
8439
- left = triggerRect.right - popW;
8440
- }
8441
- if (left < clip.left + 8) left = clip.left + 8;
8442
- const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
8443
- return {
8444
- direction,
8445
- top,
8446
- left,
8447
- maxHeight,
8448
- over: {
8449
- top: Math.max(0, clip.top - top),
8450
- right: Math.max(0, left + popW - clip.right),
8451
- bottom: Math.max(0, top + drawnH - clip.bottom),
8452
- left: Math.max(0, clip.left - left)
8453
- }
8454
- };
8455
- };
8456
- var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8457
- const directionRef = import_react19.default.useRef("bottom");
8458
- const sizeRef = import_react19.default.useRef(null);
8459
- const scrollParentRef = import_react19.default.useRef(null);
8460
- const placedRef = import_react19.default.useRef(false);
8461
- const calculatePosition = import_react19.default.useCallback((remeasure = false) => {
8462
- const pop = popRef.current;
8463
- if (!triggerRef.current || !pop) return;
8464
- if (remeasure || !sizeRef.current) {
8465
- sizeRef.current = {
8466
- w: pop.offsetWidth,
8467
- h: Math.max(pop.offsetHeight, pop.scrollHeight)
8468
- };
8469
- }
8470
- const { w: popW, h: popH } = sizeRef.current;
8471
- const triggerRect = triggerRef.current.getBoundingClientRect();
8472
- if (popH === 0 || popW === 0) {
8473
- sizeRef.current = null;
8474
- return;
8475
- }
8476
- const parentRect = scrollParentRef.current?.getBoundingClientRect();
8477
- const clip = {
8478
- top: Math.max(parentRect?.top ?? 0, 0),
8479
- bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
8480
- left: Math.max(parentRect?.left ?? 0, 0),
8481
- right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
8482
- };
8483
- const first = !placedRef.current;
8484
- if (first) pop.style.transition = "none";
8485
- const { direction: next, top, left, over, maxHeight } = computePlacement(
8486
- triggerRect,
8487
- popW,
8488
- popH,
8489
- clip
8490
- );
8491
- pop.style.top = `${top + window.scrollY}px`;
8492
- pop.style.left = `${left + window.scrollX}px`;
8493
- pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
8494
- 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";
8495
- directionRef.current = next;
8496
- pop.classList.toggle("top", next === "top");
8497
- pop.classList.toggle("bottom", next === "bottom");
8498
- if (first) {
8499
- void pop.offsetHeight;
8500
- pop.style.transition = "";
8501
- placedRef.current = true;
8502
- }
8503
- }, [triggerRef, popRef]);
8504
- import_react19.default.useLayoutEffect(() => {
8505
- if (!enabled) {
8506
- sizeRef.current = null;
8507
- scrollParentRef.current = null;
8508
- placedRef.current = false;
8509
- return;
8510
- }
8511
- if (triggerRef.current) {
8512
- scrollParentRef.current = findScrollParent(triggerRef.current);
8513
- }
8514
- calculatePosition(true);
8515
- const raf = requestAnimationFrame(() => calculatePosition(true));
8516
- return () => cancelAnimationFrame(raf);
8517
- }, [calculatePosition, enabled, triggerRef]);
8518
- import_react19.default.useEffect(() => {
8519
- if (!enabled || !popRef.current) return;
8520
- const observer = new ResizeObserver(() => {
8521
- calculatePosition(true);
8522
- });
8523
- observer.observe(popRef.current);
8524
- return () => observer.disconnect();
8525
- }, [calculatePosition, enabled, popRef]);
8526
- import_react19.default.useEffect(() => {
8527
- if (!enabled) return;
8528
- const onScroll = () => calculatePosition();
8529
- const onResize = () => calculatePosition(true);
8530
- window.addEventListener("resize", onResize, { passive: true });
8531
- window.addEventListener("scroll", onScroll, { passive: true, capture: true });
8532
- return () => {
8533
- window.removeEventListener("resize", onResize);
8534
- window.removeEventListener("scroll", onScroll, true);
8535
- };
8536
- }, [calculatePosition, enabled]);
8537
- };
8538
- var useAutoPosition_default = useAutoPosition;
8539
-
8540
8543
  // src/tokens/hooks/useClickOutside.ts
8541
8544
  var import_react20 = __toESM(require("react"), 1);
8542
8545
  var useClickOutside = (refs, handler, enabled = true) => {
@@ -8573,7 +8576,7 @@ var Dropdown = (props) => {
8573
8576
  const menuRef = import_react21.default.useRef(null);
8574
8577
  useAutoPosition_default(triggerRef, menuRef, mounted);
8575
8578
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
8576
- useCloseOnContainerScroll(isOpen, menuRef, () => setIsOpen(false));
8579
+ useCloseWhenTriggerHidden(isOpen, triggerRef, () => setIsOpen(false));
8577
8580
  useEscapeKey(isOpen, () => {
8578
8581
  setIsOpen(false);
8579
8582
  triggerRef.current?.focus({ preventScroll: true });
@@ -10504,7 +10507,7 @@ var PopOver = (props) => {
10504
10507
  const [localOpen, setLocalOpen] = import_react27.default.useState(false);
10505
10508
  const [eventTrigger, setEventTrigger] = import_react27.default.useState(false);
10506
10509
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
10507
- useCloseOnContainerScroll(isOpen, popRef, onClose);
10510
+ useCloseWhenTriggerHidden(isOpen, triggerRef, onClose);
10508
10511
  useEscapeKey(isOpen, () => {
10509
10512
  onClose();
10510
10513
  triggerRef.current?.focus({ preventScroll: true });
@@ -10784,7 +10787,7 @@ var SelectRoot = (props) => {
10784
10787
  }, []);
10785
10788
  const toggle = import_react31.default.useCallback(() => setOpen((prev) => !prev), []);
10786
10789
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
10787
- useCloseOnContainerScroll(isOpen, contentRef, close);
10790
+ useCloseWhenTriggerHidden(isOpen, triggerRef, close);
10788
10791
  useEscapeKey(isOpen, () => {
10789
10792
  close();
10790
10793
  triggerRef.current?.focus({ preventScroll: true });
@@ -11725,7 +11728,7 @@ var TimePicker = (props) => {
11725
11728
  }, [step, min, max]);
11726
11729
  const close = import_react40.default.useCallback(() => setOpen(false), []);
11727
11730
  useClickOutside_default([triggerRef, contentRef], close, isOpen);
11728
- useCloseOnContainerScroll(isOpen, contentRef, close);
11731
+ useCloseWhenTriggerHidden(isOpen, triggerRef, close);
11729
11732
  useEscapeKey(isOpen, () => {
11730
11733
  close();
11731
11734
  triggerRef.current?.focus({ preventScroll: true });
package/dist/index.css CHANGED
@@ -3282,11 +3282,11 @@
3282
3282
  box-shadow: var(--semantic-shadow-md);
3283
3283
  padding: var(--spacing-space-1) 0;
3284
3284
  opacity: 0;
3285
- transform: translateY(-4px);
3285
+ transform: translateY(4px);
3286
3286
  transition: opacity 0.15s ease, transform 0.15s ease;
3287
3287
  }
3288
3288
  .lib-xplat-dropdown-menu.bottom {
3289
- transform: translateY(4px);
3289
+ transform: translateY(-4px);
3290
3290
  }
3291
3291
  .lib-xplat-dropdown-menu.visible {
3292
3292
  opacity: 1;
@@ -4513,7 +4513,7 @@
4513
4513
  transition: transform 0.2s ease, opacity 0.2s ease;
4514
4514
  }
4515
4515
  .lib-xplat-select-content.bottom {
4516
- transform: translateY(8px);
4516
+ transform: translateY(-4px);
4517
4517
  }
4518
4518
  .lib-xplat-select-content.bottom.visible {
4519
4519
  opacity: 1;
@@ -4521,12 +4521,12 @@
4521
4521
  }
4522
4522
  .lib-xplat-select-content.bottom.exit {
4523
4523
  opacity: 0;
4524
- transform: translateY(8px);
4524
+ transform: translateY(-4px);
4525
4525
  }
4526
4526
  .lib-xplat-select-content {
4527
4527
  }
4528
4528
  .lib-xplat-select-content.top {
4529
- transform: translateY(-8px);
4529
+ transform: translateY(4px);
4530
4530
  }
4531
4531
  .lib-xplat-select-content.top.visible {
4532
4532
  opacity: 1;
@@ -4534,7 +4534,7 @@
4534
4534
  }
4535
4535
  .lib-xplat-select-content.top.exit {
4536
4536
  opacity: 0;
4537
- transform: translateY(-8px);
4537
+ transform: translateY(4px);
4538
4538
  }
4539
4539
  .lib-xplat-select-content.sm .select-item {
4540
4540
  padding: var(--spacing-space-2) var(--spacing-space-2);