@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.js CHANGED
@@ -7054,7 +7054,7 @@ Chip.displayName = "Chip";
7054
7054
  var Chip_default = Chip;
7055
7055
 
7056
7056
  // src/components/DatePicker/InputDatePicker/index.tsx
7057
- import React13 from "react";
7057
+ import React14 from "react";
7058
7058
 
7059
7059
  // src/components/Input/Input.tsx
7060
7060
  import React8 from "react";
@@ -7227,11 +7227,149 @@ PasswordInput.displayName = "PasswordInput";
7227
7227
  var PasswordInput_default = PasswordInput;
7228
7228
 
7229
7229
  // src/components/Modal/Modal.tsx
7230
- import React11 from "react";
7230
+ import React12 from "react";
7231
7231
  import { createPortal } from "react-dom";
7232
7232
 
7233
7233
  // src/tokens/hooks/useOverlayKeyboard.ts
7234
+ import React11 from "react";
7235
+
7236
+ // src/tokens/hooks/useAutoPosition.ts
7234
7237
  import React10 from "react";
7238
+ var findScrollParent = (el) => {
7239
+ for (let p = el.parentElement; p; p = p.parentElement) {
7240
+ const { overflowY, overflowX } = getComputedStyle(p);
7241
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
7242
+ }
7243
+ return null;
7244
+ };
7245
+ var TRIGGER_GAP = 8;
7246
+ var computePlacement = (triggerRect, popW, popH, clip) => {
7247
+ const roomBelow = clip.bottom - triggerRect.bottom - TRIGGER_GAP;
7248
+ const roomAbove = triggerRect.top - clip.top - TRIGGER_GAP;
7249
+ let direction;
7250
+ let top;
7251
+ let maxHeight = null;
7252
+ if (popH <= roomBelow) {
7253
+ direction = "bottom";
7254
+ top = triggerRect.bottom + TRIGGER_GAP;
7255
+ } else if (popH <= roomAbove) {
7256
+ direction = "top";
7257
+ top = triggerRect.top - TRIGGER_GAP - popH;
7258
+ } else {
7259
+ const room = Math.max(roomBelow, roomAbove, 0);
7260
+ if (roomBelow >= roomAbove) {
7261
+ direction = "bottom";
7262
+ top = triggerRect.bottom + TRIGGER_GAP;
7263
+ } else {
7264
+ direction = "top";
7265
+ top = triggerRect.top - TRIGGER_GAP - room;
7266
+ }
7267
+ maxHeight = room;
7268
+ }
7269
+ let left = triggerRect.left;
7270
+ if (left + popW > clip.right - 8) {
7271
+ left = triggerRect.right - popW;
7272
+ }
7273
+ if (left < clip.left + 8) left = clip.left + 8;
7274
+ const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
7275
+ return {
7276
+ direction,
7277
+ top,
7278
+ left,
7279
+ maxHeight,
7280
+ over: {
7281
+ top: Math.max(0, clip.top - top),
7282
+ right: Math.max(0, left + popW - clip.right),
7283
+ bottom: Math.max(0, top + drawnH - clip.bottom),
7284
+ left: Math.max(0, clip.left - left)
7285
+ }
7286
+ };
7287
+ };
7288
+ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7289
+ const directionRef = React10.useRef("bottom");
7290
+ const sizeRef = React10.useRef(null);
7291
+ const scrollParentRef = React10.useRef(null);
7292
+ const placedRef = React10.useRef(false);
7293
+ const calculatePosition = React10.useCallback((remeasure = false) => {
7294
+ const pop = popRef.current;
7295
+ if (!triggerRef.current || !pop) return;
7296
+ if (remeasure || !sizeRef.current) {
7297
+ sizeRef.current = {
7298
+ w: pop.offsetWidth,
7299
+ h: Math.max(pop.offsetHeight, pop.scrollHeight)
7300
+ };
7301
+ }
7302
+ const { w: popW, h: popH } = sizeRef.current;
7303
+ const triggerRect = triggerRef.current.getBoundingClientRect();
7304
+ if (popH === 0 || popW === 0) {
7305
+ sizeRef.current = null;
7306
+ return;
7307
+ }
7308
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
7309
+ const clip = {
7310
+ top: Math.max(parentRect?.top ?? 0, 0),
7311
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
7312
+ left: Math.max(parentRect?.left ?? 0, 0),
7313
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
7314
+ };
7315
+ const first = !placedRef.current;
7316
+ if (first) pop.style.transition = "none";
7317
+ const { direction: next, top, left, over, maxHeight } = computePlacement(
7318
+ triggerRect,
7319
+ popW,
7320
+ popH,
7321
+ clip
7322
+ );
7323
+ pop.style.top = `${top + window.scrollY}px`;
7324
+ pop.style.left = `${left + window.scrollX}px`;
7325
+ pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
7326
+ 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";
7327
+ directionRef.current = next;
7328
+ pop.classList.toggle("top", next === "top");
7329
+ pop.classList.toggle("bottom", next === "bottom");
7330
+ if (first) {
7331
+ void pop.offsetHeight;
7332
+ pop.style.transition = "";
7333
+ placedRef.current = true;
7334
+ }
7335
+ }, [triggerRef, popRef]);
7336
+ React10.useLayoutEffect(() => {
7337
+ if (!enabled) {
7338
+ sizeRef.current = null;
7339
+ scrollParentRef.current = null;
7340
+ placedRef.current = false;
7341
+ return;
7342
+ }
7343
+ if (triggerRef.current) {
7344
+ scrollParentRef.current = findScrollParent(triggerRef.current);
7345
+ }
7346
+ calculatePosition(true);
7347
+ const raf = requestAnimationFrame(() => calculatePosition(true));
7348
+ return () => cancelAnimationFrame(raf);
7349
+ }, [calculatePosition, enabled, triggerRef]);
7350
+ React10.useEffect(() => {
7351
+ if (!enabled || !popRef.current) return;
7352
+ const observer = new ResizeObserver(() => {
7353
+ calculatePosition(true);
7354
+ });
7355
+ observer.observe(popRef.current);
7356
+ return () => observer.disconnect();
7357
+ }, [calculatePosition, enabled, popRef]);
7358
+ React10.useEffect(() => {
7359
+ if (!enabled) return;
7360
+ const onScroll = () => calculatePosition();
7361
+ const onResize = () => calculatePosition(true);
7362
+ window.addEventListener("resize", onResize, { passive: true });
7363
+ window.addEventListener("scroll", onScroll, { passive: true, capture: true });
7364
+ return () => {
7365
+ window.removeEventListener("resize", onResize);
7366
+ window.removeEventListener("scroll", onScroll, true);
7367
+ };
7368
+ }, [calculatePosition, enabled]);
7369
+ };
7370
+ var useAutoPosition_default = useAutoPosition;
7371
+
7372
+ // src/tokens/hooks/useOverlayKeyboard.ts
7235
7373
  var FOCUSABLE = [
7236
7374
  "a[href]",
7237
7375
  "button:not([disabled])",
@@ -7245,7 +7383,7 @@ var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
7245
7383
  (n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
7246
7384
  );
7247
7385
  var useEscapeKey = (enabled, onEscape) => {
7248
- React10.useEffect(() => {
7386
+ React11.useEffect(() => {
7249
7387
  if (!enabled) return;
7250
7388
  const onKey = (e) => {
7251
7389
  if (e.key !== "Escape") return;
@@ -7259,8 +7397,8 @@ var useEscapeKey = (enabled, onEscape) => {
7259
7397
  };
7260
7398
  var useFocusTrap = (containerRef, enabled, options = {}) => {
7261
7399
  const { trap = false, initialFocus } = options;
7262
- const restoreRef = React10.useRef(null);
7263
- React10.useEffect(() => {
7400
+ const restoreRef = React11.useRef(null);
7401
+ React11.useEffect(() => {
7264
7402
  if (!enabled) return;
7265
7403
  restoreRef.current = document.activeElement;
7266
7404
  const raf = requestAnimationFrame(() => {
@@ -7278,7 +7416,7 @@ var useFocusTrap = (containerRef, enabled, options = {}) => {
7278
7416
  if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
7279
7417
  };
7280
7418
  }, [enabled, containerRef, initialFocus]);
7281
- React10.useEffect(() => {
7419
+ React11.useEffect(() => {
7282
7420
  if (!enabled || !trap) return;
7283
7421
  const onKey = (e) => {
7284
7422
  if (e.key !== "Tab") return;
@@ -7304,22 +7442,25 @@ var useFocusTrap = (containerRef, enabled, options = {}) => {
7304
7442
  return () => document.removeEventListener("keydown", onKey);
7305
7443
  }, [enabled, trap, containerRef]);
7306
7444
  };
7307
- var useCloseOnContainerScroll = (enabled, popRef, onClose) => {
7308
- const onCloseRef = React10.useRef(onClose);
7445
+ var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
7446
+ const onCloseRef = React11.useRef(onClose);
7309
7447
  onCloseRef.current = onClose;
7310
- React10.useEffect(() => {
7311
- if (!enabled) return;
7312
- const onScroll = (e) => {
7313
- const target = e.target;
7314
- if (target === document || target === document.documentElement || target === document.body) {
7315
- return;
7316
- }
7317
- if (target instanceof Node && popRef.current?.contains(target)) return;
7318
- onCloseRef.current();
7319
- };
7320
- window.addEventListener("scroll", onScroll, { passive: true, capture: true });
7321
- return () => window.removeEventListener("scroll", onScroll, true);
7322
- }, [enabled, popRef]);
7448
+ React11.useEffect(() => {
7449
+ const trigger = triggerRef.current;
7450
+ if (!enabled || !trigger) return;
7451
+ const observer = new IntersectionObserver(
7452
+ ([entry]) => {
7453
+ if (entry.isIntersecting) return;
7454
+ if (!popRef.current?.contains(document.activeElement)) return;
7455
+ onCloseRef.current();
7456
+ trigger.focus({ preventScroll: true });
7457
+ },
7458
+ // 그릇이 없으면 root: null → 뷰포트 기준
7459
+ { root: findScrollParent(trigger), threshold: 0 }
7460
+ );
7461
+ observer.observe(trigger);
7462
+ return () => observer.disconnect();
7463
+ }, [enabled, triggerRef, popRef]);
7323
7464
  };
7324
7465
 
7325
7466
  // src/components/Modal/Modal.tsx
@@ -7327,13 +7468,13 @@ import { jsx as jsx313 } from "react/jsx-runtime";
7327
7468
  var ANIMATION_DURATION_MS = 200;
7328
7469
  var Modal = (props) => {
7329
7470
  const { isOpen, onClose, children } = props;
7330
- const [mounted, setMounted] = React11.useState(false);
7331
- const [visible, setVisible] = React11.useState(false);
7332
- const [settled, setSettled] = React11.useState(false);
7333
- const boxRef = React11.useRef(null);
7471
+ const [mounted, setMounted] = React12.useState(false);
7472
+ const [visible, setVisible] = React12.useState(false);
7473
+ const [settled, setSettled] = React12.useState(false);
7474
+ const boxRef = React12.useRef(null);
7334
7475
  useEscapeKey(isOpen, onClose);
7335
7476
  useFocusTrap(boxRef, isOpen && mounted, { trap: true });
7336
- React11.useEffect(() => {
7477
+ React12.useEffect(() => {
7337
7478
  if (isOpen) {
7338
7479
  setMounted(true);
7339
7480
  const show = setTimeout(() => setVisible(true), 1);
@@ -7377,9 +7518,9 @@ Modal.displayName = "Modal";
7377
7518
  var Modal_default = Modal;
7378
7519
 
7379
7520
  // src/components/DatePicker/SingleDatePicker/index.tsx
7380
- import React12 from "react";
7521
+ import React13 from "react";
7381
7522
  import { Fragment as Fragment4, jsx as jsx314, jsxs as jsxs200 } from "react/jsx-runtime";
7382
- var DayCell2 = React12.memo(
7523
+ var DayCell2 = React13.memo(
7383
7524
  ({
7384
7525
  day,
7385
7526
  disabled,
@@ -7428,33 +7569,33 @@ var SingleDatePicker = (props) => {
7428
7569
  required,
7429
7570
  validations
7430
7571
  } = props;
7431
- const labelId = React12.useId();
7572
+ const labelId = React13.useId();
7432
7573
  const initialYear = value?.getFullYear();
7433
7574
  const initialMonth = value?.getMonth();
7434
7575
  const { year, month, days, goToPrevMonth, goToNextMonth, setYear, setMonth } = useCalendar(
7435
7576
  initialYear,
7436
7577
  initialMonth
7437
7578
  );
7438
- const [pickerMode, setPickerMode] = React12.useState("days");
7439
- const [yearRangeStart, setYearRangeStart] = React12.useState(
7579
+ const [pickerMode, setPickerMode] = React13.useState("days");
7580
+ const [yearRangeStart, setYearRangeStart] = React13.useState(
7440
7581
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
7441
7582
  );
7442
- const minTime = React12.useMemo(
7583
+ const minTime = React13.useMemo(
7443
7584
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
7444
7585
  [minDate]
7445
7586
  );
7446
- const maxTime = React12.useMemo(
7587
+ const maxTime = React13.useMemo(
7447
7588
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
7448
7589
  [maxDate]
7449
7590
  );
7450
- const highlightSet = React12.useMemo(() => {
7591
+ const highlightSet = React13.useMemo(() => {
7451
7592
  const set = /* @__PURE__ */ new Set();
7452
7593
  for (const h of highlightDates) {
7453
7594
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
7454
7595
  }
7455
7596
  return set;
7456
7597
  }, [highlightDates]);
7457
- const handleSelect = React12.useCallback(
7598
+ const handleSelect = React13.useCallback(
7458
7599
  (date) => {
7459
7600
  onChange?.(date);
7460
7601
  },
@@ -7597,8 +7738,8 @@ var InputDatePicker = (props) => {
7597
7738
  required,
7598
7739
  validations
7599
7740
  } = props;
7600
- const [isOpen, setIsOpen] = React13.useState(false);
7601
- const [tempDate, setTempDate] = React13.useState(value ?? /* @__PURE__ */ new Date());
7741
+ const [isOpen, setIsOpen] = React14.useState(false);
7742
+ const [tempDate, setTempDate] = React14.useState(value ?? /* @__PURE__ */ new Date());
7602
7743
  const handleOpen = () => {
7603
7744
  if (disabled) return;
7604
7745
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -7650,18 +7791,18 @@ InputDatePicker.displayName = "InputDatePicker";
7650
7791
  var InputDatePicker_default = InputDatePicker;
7651
7792
 
7652
7793
  // src/components/DatePicker/PopupPicker/index.tsx
7653
- import React17 from "react";
7794
+ import React18 from "react";
7654
7795
 
7655
7796
  // src/components/DatePicker/RangePicker/index.tsx
7656
- import React16 from "react";
7797
+ import React17 from "react";
7657
7798
 
7658
7799
  // src/components/Tab/Tab.tsx
7659
- import React15 from "react";
7800
+ import React16 from "react";
7660
7801
 
7661
7802
  // src/components/Tab/TabItem.tsx
7662
- import React14 from "react";
7803
+ import React15 from "react";
7663
7804
  import { jsx as jsx316 } from "react/jsx-runtime";
7664
- var TabItem = React14.forwardRef((props, ref) => {
7805
+ var TabItem = React15.forwardRef((props, ref) => {
7665
7806
  const { isActive: isActive2, title, onClick } = props;
7666
7807
  return /* @__PURE__ */ jsx316(
7667
7808
  "button",
@@ -7685,11 +7826,11 @@ import { jsx as jsx317, jsxs as jsxs202 } from "react/jsx-runtime";
7685
7826
  var Tab = (props) => {
7686
7827
  const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
7687
7828
  const shape = variant ?? type ?? "default";
7688
- const [underlineStyle, setUnderlineStyle] = React15.useState({
7829
+ const [underlineStyle, setUnderlineStyle] = React16.useState({
7689
7830
  left: 0,
7690
7831
  width: 0
7691
7832
  });
7692
- const itemRefs = React15.useRef([]);
7833
+ const itemRefs = React16.useRef([]);
7693
7834
  const handleKeyDown = (e) => {
7694
7835
  const last = tabs.length - 1;
7695
7836
  let next = null;
@@ -7705,7 +7846,7 @@ var Tab = (props) => {
7705
7846
  const handleChangeActiveTab = (tabItem, tabIdx) => {
7706
7847
  onChange(tabItem, tabIdx);
7707
7848
  };
7708
- React15.useEffect(() => {
7849
+ React16.useEffect(() => {
7709
7850
  const el = itemRefs.current[activeIndex];
7710
7851
  if (el) {
7711
7852
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
@@ -7761,8 +7902,8 @@ var RangePicker = (props) => {
7761
7902
  required,
7762
7903
  validations
7763
7904
  } = props;
7764
- const labelId = React16.useId();
7765
- const [activeTab, setActiveTab] = React16.useState("start");
7905
+ const labelId = React17.useId();
7906
+ const [activeTab, setActiveTab] = React17.useState("start");
7766
7907
  const handleStartChange = (date) => {
7767
7908
  if (!date) return;
7768
7909
  const newStart = date > endDate ? endDate : date;
@@ -7856,7 +7997,7 @@ var RangePicker_default = RangePicker;
7856
7997
  import { jsx as jsx319, jsxs as jsxs204 } from "react/jsx-runtime";
7857
7998
  var PopupPicker = (props) => {
7858
7999
  const { component, type, locale } = props;
7859
- const [isOpen, setIsOpen] = React17.useState(false);
8000
+ const [isOpen, setIsOpen] = React18.useState(false);
7860
8001
  const handleClick = () => setIsOpen(true);
7861
8002
  const handleClose = () => setIsOpen(false);
7862
8003
  const handleSingleChange = (date) => {
@@ -7865,7 +8006,7 @@ var PopupPicker = (props) => {
7865
8006
  handleClose();
7866
8007
  };
7867
8008
  return /* @__PURE__ */ jsxs204("div", { className: "lib-xplat-popup-datepicker", children: [
7868
- React17.cloneElement(component, { onClick: handleClick }),
8009
+ React18.cloneElement(component, { onClick: handleClick }),
7869
8010
  /* @__PURE__ */ jsx319(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ jsxs204("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
7870
8011
  /* @__PURE__ */ jsxs204("div", { className: "popup-datepicker-content", children: [
7871
8012
  type === "single" && /* @__PURE__ */ jsx319(
@@ -7924,18 +8065,18 @@ Divider.displayName = "Divider";
7924
8065
  var Divider_default = Divider;
7925
8066
 
7926
8067
  // src/components/Drawer/Drawer.tsx
7927
- import React18 from "react";
8068
+ import React19 from "react";
7928
8069
  import { createPortal as createPortal2 } from "react-dom";
7929
8070
  import { jsx as jsx321, jsxs as jsxs205 } from "react/jsx-runtime";
7930
8071
  var ANIMATION_DURATION_MS2 = 250;
7931
8072
  var Drawer = (props) => {
7932
8073
  const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
7933
- const [mounted, setMounted] = React18.useState(false);
7934
- const [visible, setVisible] = React18.useState(false);
7935
- const panelRef = React18.useRef(null);
8074
+ const [mounted, setMounted] = React19.useState(false);
8075
+ const [visible, setVisible] = React19.useState(false);
8076
+ const panelRef = React19.useRef(null);
7936
8077
  useEscapeKey(isOpen, onClose);
7937
8078
  useFocusTrap(panelRef, isOpen && mounted, { trap: true });
7938
- React18.useEffect(() => {
8079
+ React19.useEffect(() => {
7939
8080
  if (isOpen) {
7940
8081
  setMounted(true);
7941
8082
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -7991,142 +8132,6 @@ var Portal = ({ children }) => {
7991
8132
  Portal.displayName = "Portal";
7992
8133
  var Portal_default = Portal;
7993
8134
 
7994
- // src/tokens/hooks/useAutoPosition.ts
7995
- import React19 from "react";
7996
- var findScrollParent = (el) => {
7997
- for (let p = el.parentElement; p; p = p.parentElement) {
7998
- const { overflowY, overflowX } = getComputedStyle(p);
7999
- if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
8000
- }
8001
- return null;
8002
- };
8003
- var TRIGGER_GAP = 8;
8004
- var computePlacement = (triggerRect, popW, popH, clip) => {
8005
- const roomBelow = clip.bottom - triggerRect.bottom - TRIGGER_GAP;
8006
- const roomAbove = triggerRect.top - clip.top - TRIGGER_GAP;
8007
- let direction;
8008
- let top;
8009
- let maxHeight = null;
8010
- if (popH <= roomBelow) {
8011
- direction = "bottom";
8012
- top = triggerRect.bottom + TRIGGER_GAP;
8013
- } else if (popH <= roomAbove) {
8014
- direction = "top";
8015
- top = triggerRect.top - TRIGGER_GAP - popH;
8016
- } else {
8017
- const room = Math.max(roomBelow, roomAbove, 0);
8018
- if (roomBelow >= roomAbove) {
8019
- direction = "bottom";
8020
- top = triggerRect.bottom + TRIGGER_GAP;
8021
- } else {
8022
- direction = "top";
8023
- top = triggerRect.top - TRIGGER_GAP - room;
8024
- }
8025
- maxHeight = room;
8026
- }
8027
- let left = triggerRect.left;
8028
- if (left + popW > clip.right - 8) {
8029
- left = triggerRect.right - popW;
8030
- }
8031
- if (left < clip.left + 8) left = clip.left + 8;
8032
- const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
8033
- return {
8034
- direction,
8035
- top,
8036
- left,
8037
- maxHeight,
8038
- over: {
8039
- top: Math.max(0, clip.top - top),
8040
- right: Math.max(0, left + popW - clip.right),
8041
- bottom: Math.max(0, top + drawnH - clip.bottom),
8042
- left: Math.max(0, clip.left - left)
8043
- }
8044
- };
8045
- };
8046
- var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8047
- const directionRef = React19.useRef("bottom");
8048
- const sizeRef = React19.useRef(null);
8049
- const scrollParentRef = React19.useRef(null);
8050
- const placedRef = React19.useRef(false);
8051
- const calculatePosition = React19.useCallback((remeasure = false) => {
8052
- const pop = popRef.current;
8053
- if (!triggerRef.current || !pop) return;
8054
- if (remeasure || !sizeRef.current) {
8055
- sizeRef.current = {
8056
- w: pop.offsetWidth,
8057
- h: Math.max(pop.offsetHeight, pop.scrollHeight)
8058
- };
8059
- }
8060
- const { w: popW, h: popH } = sizeRef.current;
8061
- const triggerRect = triggerRef.current.getBoundingClientRect();
8062
- if (popH === 0 || popW === 0) {
8063
- sizeRef.current = null;
8064
- return;
8065
- }
8066
- const parentRect = scrollParentRef.current?.getBoundingClientRect();
8067
- const clip = {
8068
- top: Math.max(parentRect?.top ?? 0, 0),
8069
- bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
8070
- left: Math.max(parentRect?.left ?? 0, 0),
8071
- right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
8072
- };
8073
- const first = !placedRef.current;
8074
- if (first) pop.style.transition = "none";
8075
- const { direction: next, top, left, over, maxHeight } = computePlacement(
8076
- triggerRect,
8077
- popW,
8078
- popH,
8079
- clip
8080
- );
8081
- pop.style.top = `${top + window.scrollY}px`;
8082
- pop.style.left = `${left + window.scrollX}px`;
8083
- pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
8084
- 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";
8085
- directionRef.current = next;
8086
- pop.classList.toggle("top", next === "top");
8087
- pop.classList.toggle("bottom", next === "bottom");
8088
- if (first) {
8089
- void pop.offsetHeight;
8090
- pop.style.transition = "";
8091
- placedRef.current = true;
8092
- }
8093
- }, [triggerRef, popRef]);
8094
- React19.useLayoutEffect(() => {
8095
- if (!enabled) {
8096
- sizeRef.current = null;
8097
- scrollParentRef.current = null;
8098
- placedRef.current = false;
8099
- return;
8100
- }
8101
- if (triggerRef.current) {
8102
- scrollParentRef.current = findScrollParent(triggerRef.current);
8103
- }
8104
- calculatePosition(true);
8105
- const raf = requestAnimationFrame(() => calculatePosition(true));
8106
- return () => cancelAnimationFrame(raf);
8107
- }, [calculatePosition, enabled, triggerRef]);
8108
- React19.useEffect(() => {
8109
- if (!enabled || !popRef.current) return;
8110
- const observer = new ResizeObserver(() => {
8111
- calculatePosition(true);
8112
- });
8113
- observer.observe(popRef.current);
8114
- return () => observer.disconnect();
8115
- }, [calculatePosition, enabled, popRef]);
8116
- React19.useEffect(() => {
8117
- if (!enabled) return;
8118
- const onScroll = () => calculatePosition();
8119
- const onResize = () => calculatePosition(true);
8120
- window.addEventListener("resize", onResize, { passive: true });
8121
- window.addEventListener("scroll", onScroll, { passive: true, capture: true });
8122
- return () => {
8123
- window.removeEventListener("resize", onResize);
8124
- window.removeEventListener("scroll", onScroll, true);
8125
- };
8126
- }, [calculatePosition, enabled]);
8127
- };
8128
- var useAutoPosition_default = useAutoPosition;
8129
-
8130
8135
  // src/tokens/hooks/useClickOutside.ts
8131
8136
  import React20 from "react";
8132
8137
  var useClickOutside = (refs, handler, enabled = true) => {
@@ -8163,7 +8168,7 @@ var Dropdown = (props) => {
8163
8168
  const menuRef = React21.useRef(null);
8164
8169
  useAutoPosition_default(triggerRef, menuRef, mounted);
8165
8170
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
8166
- useCloseOnContainerScroll(isOpen, menuRef, () => setIsOpen(false));
8171
+ useCloseWhenFocusHidden(isOpen, triggerRef, menuRef, () => setIsOpen(false));
8167
8172
  useEscapeKey(isOpen, () => {
8168
8173
  setIsOpen(false);
8169
8174
  triggerRef.current?.focus({ preventScroll: true });
@@ -10094,7 +10099,7 @@ var PopOver = (props) => {
10094
10099
  const [localOpen, setLocalOpen] = React27.useState(false);
10095
10100
  const [eventTrigger, setEventTrigger] = React27.useState(false);
10096
10101
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
10097
- useCloseOnContainerScroll(isOpen, popRef, onClose);
10102
+ useCloseWhenFocusHidden(isOpen, triggerRef, popRef, onClose);
10098
10103
  useEscapeKey(isOpen, () => {
10099
10104
  onClose();
10100
10105
  triggerRef.current?.focus({ preventScroll: true });
@@ -10374,7 +10379,7 @@ var SelectRoot = (props) => {
10374
10379
  }, []);
10375
10380
  const toggle = React31.useCallback(() => setOpen((prev) => !prev), []);
10376
10381
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
10377
- useCloseOnContainerScroll(isOpen, contentRef, close);
10382
+ useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
10378
10383
  useEscapeKey(isOpen, () => {
10379
10384
  close();
10380
10385
  triggerRef.current?.focus({ preventScroll: true });
@@ -11315,7 +11320,7 @@ var TimePicker = (props) => {
11315
11320
  }, [step, min, max]);
11316
11321
  const close = React40.useCallback(() => setOpen(false), []);
11317
11322
  useClickOutside_default([triggerRef, contentRef], close, isOpen);
11318
- useCloseOnContainerScroll(isOpen, contentRef, close);
11323
+ useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
11319
11324
  useEscapeKey(isOpen, () => {
11320
11325
  close();
11321
11326
  triggerRef.current?.focus({ preventScroll: true });