@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.
@@ -3053,7 +3053,7 @@ Chip.displayName = "Chip";
3053
3053
  var Chip_default = Chip;
3054
3054
 
3055
3055
  // src/components/DatePicker/InputDatePicker/index.tsx
3056
- var import_react13 = __toESM(require("react"), 1);
3056
+ var import_react14 = __toESM(require("react"), 1);
3057
3057
 
3058
3058
  // src/components/Input/Input.tsx
3059
3059
  var import_react8 = __toESM(require("react"), 1);
@@ -3226,11 +3226,149 @@ PasswordInput.displayName = "PasswordInput";
3226
3226
  var PasswordInput_default = PasswordInput;
3227
3227
 
3228
3228
  // src/components/Modal/Modal.tsx
3229
- var import_react11 = __toESM(require("react"), 1);
3229
+ var import_react12 = __toESM(require("react"), 1);
3230
3230
  var import_react_dom = require("react-dom");
3231
3231
 
3232
3232
  // src/tokens/hooks/useOverlayKeyboard.ts
3233
+ var import_react11 = __toESM(require("react"), 1);
3234
+
3235
+ // src/tokens/hooks/useAutoPosition.ts
3233
3236
  var import_react10 = __toESM(require("react"), 1);
3237
+ var findScrollParent = (el) => {
3238
+ for (let p = el.parentElement; p; p = p.parentElement) {
3239
+ const { overflowY, overflowX } = getComputedStyle(p);
3240
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
3241
+ }
3242
+ return null;
3243
+ };
3244
+ var TRIGGER_GAP = 8;
3245
+ var computePlacement = (triggerRect, popW, popH, clip) => {
3246
+ const roomBelow = clip.bottom - triggerRect.bottom - TRIGGER_GAP;
3247
+ const roomAbove = triggerRect.top - clip.top - TRIGGER_GAP;
3248
+ let direction;
3249
+ let top;
3250
+ let maxHeight = null;
3251
+ if (popH <= roomBelow) {
3252
+ direction = "bottom";
3253
+ top = triggerRect.bottom + TRIGGER_GAP;
3254
+ } else if (popH <= roomAbove) {
3255
+ direction = "top";
3256
+ top = triggerRect.top - TRIGGER_GAP - popH;
3257
+ } else {
3258
+ const room = Math.max(roomBelow, roomAbove, 0);
3259
+ if (roomBelow >= roomAbove) {
3260
+ direction = "bottom";
3261
+ top = triggerRect.bottom + TRIGGER_GAP;
3262
+ } else {
3263
+ direction = "top";
3264
+ top = triggerRect.top - TRIGGER_GAP - room;
3265
+ }
3266
+ maxHeight = room;
3267
+ }
3268
+ let left = triggerRect.left;
3269
+ if (left + popW > clip.right - 8) {
3270
+ left = triggerRect.right - popW;
3271
+ }
3272
+ if (left < clip.left + 8) left = clip.left + 8;
3273
+ const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
3274
+ return {
3275
+ direction,
3276
+ top,
3277
+ left,
3278
+ maxHeight,
3279
+ over: {
3280
+ top: Math.max(0, clip.top - top),
3281
+ right: Math.max(0, left + popW - clip.right),
3282
+ bottom: Math.max(0, top + drawnH - clip.bottom),
3283
+ left: Math.max(0, clip.left - left)
3284
+ }
3285
+ };
3286
+ };
3287
+ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3288
+ const directionRef = import_react10.default.useRef("bottom");
3289
+ const sizeRef = import_react10.default.useRef(null);
3290
+ const scrollParentRef = import_react10.default.useRef(null);
3291
+ const placedRef = import_react10.default.useRef(false);
3292
+ const calculatePosition = import_react10.default.useCallback((remeasure = false) => {
3293
+ const pop = popRef.current;
3294
+ if (!triggerRef.current || !pop) return;
3295
+ if (remeasure || !sizeRef.current) {
3296
+ sizeRef.current = {
3297
+ w: pop.offsetWidth,
3298
+ h: Math.max(pop.offsetHeight, pop.scrollHeight)
3299
+ };
3300
+ }
3301
+ const { w: popW, h: popH } = sizeRef.current;
3302
+ const triggerRect = triggerRef.current.getBoundingClientRect();
3303
+ if (popH === 0 || popW === 0) {
3304
+ sizeRef.current = null;
3305
+ return;
3306
+ }
3307
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
3308
+ const clip = {
3309
+ top: Math.max(parentRect?.top ?? 0, 0),
3310
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
3311
+ left: Math.max(parentRect?.left ?? 0, 0),
3312
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
3313
+ };
3314
+ const first = !placedRef.current;
3315
+ if (first) pop.style.transition = "none";
3316
+ const { direction: next, top, left, over, maxHeight } = computePlacement(
3317
+ triggerRect,
3318
+ popW,
3319
+ popH,
3320
+ clip
3321
+ );
3322
+ pop.style.top = `${top + window.scrollY}px`;
3323
+ pop.style.left = `${left + window.scrollX}px`;
3324
+ pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
3325
+ 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";
3326
+ directionRef.current = next;
3327
+ pop.classList.toggle("top", next === "top");
3328
+ pop.classList.toggle("bottom", next === "bottom");
3329
+ if (first) {
3330
+ void pop.offsetHeight;
3331
+ pop.style.transition = "";
3332
+ placedRef.current = true;
3333
+ }
3334
+ }, [triggerRef, popRef]);
3335
+ import_react10.default.useLayoutEffect(() => {
3336
+ if (!enabled) {
3337
+ sizeRef.current = null;
3338
+ scrollParentRef.current = null;
3339
+ placedRef.current = false;
3340
+ return;
3341
+ }
3342
+ if (triggerRef.current) {
3343
+ scrollParentRef.current = findScrollParent(triggerRef.current);
3344
+ }
3345
+ calculatePosition(true);
3346
+ const raf = requestAnimationFrame(() => calculatePosition(true));
3347
+ return () => cancelAnimationFrame(raf);
3348
+ }, [calculatePosition, enabled, triggerRef]);
3349
+ import_react10.default.useEffect(() => {
3350
+ if (!enabled || !popRef.current) return;
3351
+ const observer = new ResizeObserver(() => {
3352
+ calculatePosition(true);
3353
+ });
3354
+ observer.observe(popRef.current);
3355
+ return () => observer.disconnect();
3356
+ }, [calculatePosition, enabled, popRef]);
3357
+ import_react10.default.useEffect(() => {
3358
+ if (!enabled) return;
3359
+ const onScroll = () => calculatePosition();
3360
+ const onResize = () => calculatePosition(true);
3361
+ window.addEventListener("resize", onResize, { passive: true });
3362
+ window.addEventListener("scroll", onScroll, { passive: true, capture: true });
3363
+ return () => {
3364
+ window.removeEventListener("resize", onResize);
3365
+ window.removeEventListener("scroll", onScroll, true);
3366
+ };
3367
+ }, [calculatePosition, enabled]);
3368
+ };
3369
+ var useAutoPosition_default = useAutoPosition;
3370
+
3371
+ // src/tokens/hooks/useOverlayKeyboard.ts
3234
3372
  var FOCUSABLE = [
3235
3373
  "a[href]",
3236
3374
  "button:not([disabled])",
@@ -3244,7 +3382,7 @@ var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
3244
3382
  (n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
3245
3383
  );
3246
3384
  var useEscapeKey = (enabled, onEscape) => {
3247
- import_react10.default.useEffect(() => {
3385
+ import_react11.default.useEffect(() => {
3248
3386
  if (!enabled) return;
3249
3387
  const onKey = (e) => {
3250
3388
  if (e.key !== "Escape") return;
@@ -3258,8 +3396,8 @@ var useEscapeKey = (enabled, onEscape) => {
3258
3396
  };
3259
3397
  var useFocusTrap = (containerRef, enabled, options = {}) => {
3260
3398
  const { trap = false, initialFocus } = options;
3261
- const restoreRef = import_react10.default.useRef(null);
3262
- import_react10.default.useEffect(() => {
3399
+ const restoreRef = import_react11.default.useRef(null);
3400
+ import_react11.default.useEffect(() => {
3263
3401
  if (!enabled) return;
3264
3402
  restoreRef.current = document.activeElement;
3265
3403
  const raf = requestAnimationFrame(() => {
@@ -3277,7 +3415,7 @@ var useFocusTrap = (containerRef, enabled, options = {}) => {
3277
3415
  if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
3278
3416
  };
3279
3417
  }, [enabled, containerRef, initialFocus]);
3280
- import_react10.default.useEffect(() => {
3418
+ import_react11.default.useEffect(() => {
3281
3419
  if (!enabled || !trap) return;
3282
3420
  const onKey = (e) => {
3283
3421
  if (e.key !== "Tab") return;
@@ -3303,22 +3441,22 @@ var useFocusTrap = (containerRef, enabled, options = {}) => {
3303
3441
  return () => document.removeEventListener("keydown", onKey);
3304
3442
  }, [enabled, trap, containerRef]);
3305
3443
  };
3306
- var useCloseOnContainerScroll = (enabled, popRef, onClose) => {
3307
- const onCloseRef = import_react10.default.useRef(onClose);
3444
+ var useCloseWhenTriggerHidden = (enabled, triggerRef, onClose) => {
3445
+ const onCloseRef = import_react11.default.useRef(onClose);
3308
3446
  onCloseRef.current = onClose;
3309
- import_react10.default.useEffect(() => {
3310
- if (!enabled) return;
3311
- const onScroll = (e) => {
3312
- const target = e.target;
3313
- if (target === document || target === document.documentElement || target === document.body) {
3314
- return;
3315
- }
3316
- if (target instanceof Node && popRef.current?.contains(target)) return;
3317
- onCloseRef.current();
3318
- };
3319
- window.addEventListener("scroll", onScroll, { passive: true, capture: true });
3320
- return () => window.removeEventListener("scroll", onScroll, true);
3321
- }, [enabled, popRef]);
3447
+ import_react11.default.useEffect(() => {
3448
+ const trigger = triggerRef.current;
3449
+ if (!enabled || !trigger) return;
3450
+ const observer = new IntersectionObserver(
3451
+ ([entry]) => {
3452
+ if (!entry.isIntersecting) onCloseRef.current();
3453
+ },
3454
+ // 그릇이 없으면 root: null → 뷰포트 기준
3455
+ { root: findScrollParent(trigger), threshold: 0 }
3456
+ );
3457
+ observer.observe(trigger);
3458
+ return () => observer.disconnect();
3459
+ }, [enabled, triggerRef]);
3322
3460
  };
3323
3461
 
3324
3462
  // src/components/Modal/Modal.tsx
@@ -3326,13 +3464,13 @@ var import_jsx_runtime313 = require("react/jsx-runtime");
3326
3464
  var ANIMATION_DURATION_MS = 200;
3327
3465
  var Modal = (props) => {
3328
3466
  const { isOpen, onClose, children } = props;
3329
- const [mounted, setMounted] = import_react11.default.useState(false);
3330
- const [visible, setVisible] = import_react11.default.useState(false);
3331
- const [settled, setSettled] = import_react11.default.useState(false);
3332
- const boxRef = import_react11.default.useRef(null);
3467
+ const [mounted, setMounted] = import_react12.default.useState(false);
3468
+ const [visible, setVisible] = import_react12.default.useState(false);
3469
+ const [settled, setSettled] = import_react12.default.useState(false);
3470
+ const boxRef = import_react12.default.useRef(null);
3333
3471
  useEscapeKey(isOpen, onClose);
3334
3472
  useFocusTrap(boxRef, isOpen && mounted, { trap: true });
3335
- import_react11.default.useEffect(() => {
3473
+ import_react12.default.useEffect(() => {
3336
3474
  if (isOpen) {
3337
3475
  setMounted(true);
3338
3476
  const show = setTimeout(() => setVisible(true), 1);
@@ -3376,9 +3514,9 @@ Modal.displayName = "Modal";
3376
3514
  var Modal_default = Modal;
3377
3515
 
3378
3516
  // src/components/DatePicker/SingleDatePicker/index.tsx
3379
- var import_react12 = __toESM(require("react"), 1);
3517
+ var import_react13 = __toESM(require("react"), 1);
3380
3518
  var import_jsx_runtime314 = require("react/jsx-runtime");
3381
- var DayCell2 = import_react12.default.memo(
3519
+ var DayCell2 = import_react13.default.memo(
3382
3520
  ({
3383
3521
  day,
3384
3522
  disabled,
@@ -3427,33 +3565,33 @@ var SingleDatePicker = (props) => {
3427
3565
  required,
3428
3566
  validations
3429
3567
  } = props;
3430
- const labelId = import_react12.default.useId();
3568
+ const labelId = import_react13.default.useId();
3431
3569
  const initialYear = value?.getFullYear();
3432
3570
  const initialMonth = value?.getMonth();
3433
3571
  const { year, month, days, goToPrevMonth, goToNextMonth, setYear, setMonth } = useCalendar(
3434
3572
  initialYear,
3435
3573
  initialMonth
3436
3574
  );
3437
- const [pickerMode, setPickerMode] = import_react12.default.useState("days");
3438
- const [yearRangeStart, setYearRangeStart] = import_react12.default.useState(
3575
+ const [pickerMode, setPickerMode] = import_react13.default.useState("days");
3576
+ const [yearRangeStart, setYearRangeStart] = import_react13.default.useState(
3439
3577
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
3440
3578
  );
3441
- const minTime = import_react12.default.useMemo(
3579
+ const minTime = import_react13.default.useMemo(
3442
3580
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
3443
3581
  [minDate]
3444
3582
  );
3445
- const maxTime = import_react12.default.useMemo(
3583
+ const maxTime = import_react13.default.useMemo(
3446
3584
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
3447
3585
  [maxDate]
3448
3586
  );
3449
- const highlightSet = import_react12.default.useMemo(() => {
3587
+ const highlightSet = import_react13.default.useMemo(() => {
3450
3588
  const set = /* @__PURE__ */ new Set();
3451
3589
  for (const h of highlightDates) {
3452
3590
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
3453
3591
  }
3454
3592
  return set;
3455
3593
  }, [highlightDates]);
3456
- const handleSelect = import_react12.default.useCallback(
3594
+ const handleSelect = import_react13.default.useCallback(
3457
3595
  (date) => {
3458
3596
  onChange?.(date);
3459
3597
  },
@@ -3596,8 +3734,8 @@ var InputDatePicker = (props) => {
3596
3734
  required,
3597
3735
  validations
3598
3736
  } = props;
3599
- const [isOpen, setIsOpen] = import_react13.default.useState(false);
3600
- const [tempDate, setTempDate] = import_react13.default.useState(value ?? /* @__PURE__ */ new Date());
3737
+ const [isOpen, setIsOpen] = import_react14.default.useState(false);
3738
+ const [tempDate, setTempDate] = import_react14.default.useState(value ?? /* @__PURE__ */ new Date());
3601
3739
  const handleOpen = () => {
3602
3740
  if (disabled) return;
3603
3741
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -3649,18 +3787,18 @@ InputDatePicker.displayName = "InputDatePicker";
3649
3787
  var InputDatePicker_default = InputDatePicker;
3650
3788
 
3651
3789
  // src/components/DatePicker/PopupPicker/index.tsx
3652
- var import_react17 = __toESM(require("react"), 1);
3790
+ var import_react18 = __toESM(require("react"), 1);
3653
3791
 
3654
3792
  // src/components/DatePicker/RangePicker/index.tsx
3655
- var import_react16 = __toESM(require("react"), 1);
3793
+ var import_react17 = __toESM(require("react"), 1);
3656
3794
 
3657
3795
  // src/components/Tab/Tab.tsx
3658
- var import_react15 = __toESM(require("react"), 1);
3796
+ var import_react16 = __toESM(require("react"), 1);
3659
3797
 
3660
3798
  // src/components/Tab/TabItem.tsx
3661
- var import_react14 = __toESM(require("react"), 1);
3799
+ var import_react15 = __toESM(require("react"), 1);
3662
3800
  var import_jsx_runtime316 = require("react/jsx-runtime");
3663
- var TabItem = import_react14.default.forwardRef((props, ref) => {
3801
+ var TabItem = import_react15.default.forwardRef((props, ref) => {
3664
3802
  const { isActive: isActive2, title, onClick } = props;
3665
3803
  return /* @__PURE__ */ (0, import_jsx_runtime316.jsx)(
3666
3804
  "button",
@@ -3684,11 +3822,11 @@ var import_jsx_runtime317 = require("react/jsx-runtime");
3684
3822
  var Tab = (props) => {
3685
3823
  const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
3686
3824
  const shape = variant ?? type ?? "default";
3687
- const [underlineStyle, setUnderlineStyle] = import_react15.default.useState({
3825
+ const [underlineStyle, setUnderlineStyle] = import_react16.default.useState({
3688
3826
  left: 0,
3689
3827
  width: 0
3690
3828
  });
3691
- const itemRefs = import_react15.default.useRef([]);
3829
+ const itemRefs = import_react16.default.useRef([]);
3692
3830
  const handleKeyDown = (e) => {
3693
3831
  const last = tabs.length - 1;
3694
3832
  let next = null;
@@ -3704,7 +3842,7 @@ var Tab = (props) => {
3704
3842
  const handleChangeActiveTab = (tabItem, tabIdx) => {
3705
3843
  onChange(tabItem, tabIdx);
3706
3844
  };
3707
- import_react15.default.useEffect(() => {
3845
+ import_react16.default.useEffect(() => {
3708
3846
  const el = itemRefs.current[activeIndex];
3709
3847
  if (el) {
3710
3848
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
@@ -3760,8 +3898,8 @@ var RangePicker = (props) => {
3760
3898
  required,
3761
3899
  validations
3762
3900
  } = props;
3763
- const labelId = import_react16.default.useId();
3764
- const [activeTab, setActiveTab] = import_react16.default.useState("start");
3901
+ const labelId = import_react17.default.useId();
3902
+ const [activeTab, setActiveTab] = import_react17.default.useState("start");
3765
3903
  const handleStartChange = (date) => {
3766
3904
  if (!date) return;
3767
3905
  const newStart = date > endDate ? endDate : date;
@@ -3855,7 +3993,7 @@ var RangePicker_default = RangePicker;
3855
3993
  var import_jsx_runtime319 = require("react/jsx-runtime");
3856
3994
  var PopupPicker = (props) => {
3857
3995
  const { component, type, locale } = props;
3858
- const [isOpen, setIsOpen] = import_react17.default.useState(false);
3996
+ const [isOpen, setIsOpen] = import_react18.default.useState(false);
3859
3997
  const handleClick = () => setIsOpen(true);
3860
3998
  const handleClose = () => setIsOpen(false);
3861
3999
  const handleSingleChange = (date) => {
@@ -3864,7 +4002,7 @@ var PopupPicker = (props) => {
3864
4002
  handleClose();
3865
4003
  };
3866
4004
  return /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: "lib-xplat-popup-datepicker", children: [
3867
- import_react17.default.cloneElement(component, { onClick: handleClick }),
4005
+ import_react18.default.cloneElement(component, { onClick: handleClick }),
3868
4006
  /* @__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: [
3869
4007
  /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: "popup-datepicker-content", children: [
3870
4008
  type === "single" && /* @__PURE__ */ (0, import_jsx_runtime319.jsx)(
@@ -3923,18 +4061,18 @@ Divider.displayName = "Divider";
3923
4061
  var Divider_default = Divider;
3924
4062
 
3925
4063
  // src/components/Drawer/Drawer.tsx
3926
- var import_react18 = __toESM(require("react"), 1);
4064
+ var import_react19 = __toESM(require("react"), 1);
3927
4065
  var import_react_dom2 = require("react-dom");
3928
4066
  var import_jsx_runtime321 = require("react/jsx-runtime");
3929
4067
  var ANIMATION_DURATION_MS2 = 250;
3930
4068
  var Drawer = (props) => {
3931
4069
  const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
3932
- const [mounted, setMounted] = import_react18.default.useState(false);
3933
- const [visible, setVisible] = import_react18.default.useState(false);
3934
- const panelRef = import_react18.default.useRef(null);
4070
+ const [mounted, setMounted] = import_react19.default.useState(false);
4071
+ const [visible, setVisible] = import_react19.default.useState(false);
4072
+ const panelRef = import_react19.default.useRef(null);
3935
4073
  useEscapeKey(isOpen, onClose);
3936
4074
  useFocusTrap(panelRef, isOpen && mounted, { trap: true });
3937
- import_react18.default.useEffect(() => {
4075
+ import_react19.default.useEffect(() => {
3938
4076
  if (isOpen) {
3939
4077
  setMounted(true);
3940
4078
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -3990,141 +4128,6 @@ var Portal = ({ children }) => {
3990
4128
  Portal.displayName = "Portal";
3991
4129
  var Portal_default = Portal;
3992
4130
 
3993
- // src/tokens/hooks/useAutoPosition.ts
3994
- var import_react19 = __toESM(require("react"), 1);
3995
- var findScrollParent = (el) => {
3996
- for (let p = el.parentElement; p; p = p.parentElement) {
3997
- const { overflowY, overflowX } = getComputedStyle(p);
3998
- if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
3999
- }
4000
- return null;
4001
- };
4002
- var computePlacement = (triggerRect, popW, popH, clip) => {
4003
- const roomBelow = clip.bottom - triggerRect.bottom;
4004
- const roomAbove = triggerRect.top - clip.top;
4005
- let direction;
4006
- let top;
4007
- let maxHeight = null;
4008
- if (popH <= roomBelow) {
4009
- direction = "bottom";
4010
- top = triggerRect.bottom;
4011
- } else if (popH <= roomAbove) {
4012
- direction = "top";
4013
- top = triggerRect.top - popH;
4014
- } else {
4015
- const room = Math.max(roomBelow, roomAbove, 0);
4016
- if (roomBelow >= roomAbove) {
4017
- direction = "bottom";
4018
- top = triggerRect.bottom;
4019
- } else {
4020
- direction = "top";
4021
- top = triggerRect.top - room;
4022
- }
4023
- maxHeight = room;
4024
- }
4025
- let left = triggerRect.left;
4026
- if (left + popW > clip.right - 8) {
4027
- left = triggerRect.right - popW;
4028
- }
4029
- if (left < clip.left + 8) left = clip.left + 8;
4030
- const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
4031
- return {
4032
- direction,
4033
- top,
4034
- left,
4035
- maxHeight,
4036
- over: {
4037
- top: Math.max(0, clip.top - top),
4038
- right: Math.max(0, left + popW - clip.right),
4039
- bottom: Math.max(0, top + drawnH - clip.bottom),
4040
- left: Math.max(0, clip.left - left)
4041
- }
4042
- };
4043
- };
4044
- var useAutoPosition = (triggerRef, popRef, enabled = true) => {
4045
- const directionRef = import_react19.default.useRef("bottom");
4046
- const sizeRef = import_react19.default.useRef(null);
4047
- const scrollParentRef = import_react19.default.useRef(null);
4048
- const placedRef = import_react19.default.useRef(false);
4049
- const calculatePosition = import_react19.default.useCallback((remeasure = false) => {
4050
- const pop = popRef.current;
4051
- if (!triggerRef.current || !pop) return;
4052
- if (remeasure || !sizeRef.current) {
4053
- sizeRef.current = {
4054
- w: pop.offsetWidth,
4055
- h: Math.max(pop.offsetHeight, pop.scrollHeight)
4056
- };
4057
- }
4058
- const { w: popW, h: popH } = sizeRef.current;
4059
- const triggerRect = triggerRef.current.getBoundingClientRect();
4060
- if (popH === 0 || popW === 0) {
4061
- sizeRef.current = null;
4062
- return;
4063
- }
4064
- const parentRect = scrollParentRef.current?.getBoundingClientRect();
4065
- const clip = {
4066
- top: Math.max(parentRect?.top ?? 0, 0),
4067
- bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
4068
- left: Math.max(parentRect?.left ?? 0, 0),
4069
- right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
4070
- };
4071
- const first = !placedRef.current;
4072
- if (first) pop.style.transition = "none";
4073
- const { direction: next, top, left, over, maxHeight } = computePlacement(
4074
- triggerRect,
4075
- popW,
4076
- popH,
4077
- clip
4078
- );
4079
- pop.style.top = `${top + window.scrollY}px`;
4080
- pop.style.left = `${left + window.scrollX}px`;
4081
- pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
4082
- 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";
4083
- directionRef.current = next;
4084
- pop.classList.toggle("top", next === "top");
4085
- pop.classList.toggle("bottom", next === "bottom");
4086
- if (first) {
4087
- void pop.offsetHeight;
4088
- pop.style.transition = "";
4089
- placedRef.current = true;
4090
- }
4091
- }, [triggerRef, popRef]);
4092
- import_react19.default.useLayoutEffect(() => {
4093
- if (!enabled) {
4094
- sizeRef.current = null;
4095
- scrollParentRef.current = null;
4096
- placedRef.current = false;
4097
- return;
4098
- }
4099
- if (triggerRef.current) {
4100
- scrollParentRef.current = findScrollParent(triggerRef.current);
4101
- }
4102
- calculatePosition(true);
4103
- const raf = requestAnimationFrame(() => calculatePosition(true));
4104
- return () => cancelAnimationFrame(raf);
4105
- }, [calculatePosition, enabled, triggerRef]);
4106
- import_react19.default.useEffect(() => {
4107
- if (!enabled || !popRef.current) return;
4108
- const observer = new ResizeObserver(() => {
4109
- calculatePosition(true);
4110
- });
4111
- observer.observe(popRef.current);
4112
- return () => observer.disconnect();
4113
- }, [calculatePosition, enabled, popRef]);
4114
- import_react19.default.useEffect(() => {
4115
- if (!enabled) return;
4116
- const onScroll = () => calculatePosition();
4117
- const onResize = () => calculatePosition(true);
4118
- window.addEventListener("resize", onResize, { passive: true });
4119
- window.addEventListener("scroll", onScroll, { passive: true, capture: true });
4120
- return () => {
4121
- window.removeEventListener("resize", onResize);
4122
- window.removeEventListener("scroll", onScroll, true);
4123
- };
4124
- }, [calculatePosition, enabled]);
4125
- };
4126
- var useAutoPosition_default = useAutoPosition;
4127
-
4128
4131
  // src/tokens/hooks/useClickOutside.ts
4129
4132
  var import_react20 = __toESM(require("react"), 1);
4130
4133
  var useClickOutside = (refs, handler, enabled = true) => {
@@ -4161,7 +4164,7 @@ var Dropdown = (props) => {
4161
4164
  const menuRef = import_react21.default.useRef(null);
4162
4165
  useAutoPosition_default(triggerRef, menuRef, mounted);
4163
4166
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
4164
- useCloseOnContainerScroll(isOpen, menuRef, () => setIsOpen(false));
4167
+ useCloseWhenTriggerHidden(isOpen, triggerRef, () => setIsOpen(false));
4165
4168
  useEscapeKey(isOpen, () => {
4166
4169
  setIsOpen(false);
4167
4170
  triggerRef.current?.focus({ preventScroll: true });
@@ -6092,7 +6095,7 @@ var PopOver = (props) => {
6092
6095
  const [localOpen, setLocalOpen] = import_react27.default.useState(false);
6093
6096
  const [eventTrigger, setEventTrigger] = import_react27.default.useState(false);
6094
6097
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
6095
- useCloseOnContainerScroll(isOpen, popRef, onClose);
6098
+ useCloseWhenTriggerHidden(isOpen, triggerRef, onClose);
6096
6099
  useEscapeKey(isOpen, () => {
6097
6100
  onClose();
6098
6101
  triggerRef.current?.focus({ preventScroll: true });
@@ -6372,7 +6375,7 @@ var SelectRoot = (props) => {
6372
6375
  }, []);
6373
6376
  const toggle = import_react31.default.useCallback(() => setOpen((prev) => !prev), []);
6374
6377
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
6375
- useCloseOnContainerScroll(isOpen, contentRef, close);
6378
+ useCloseWhenTriggerHidden(isOpen, triggerRef, close);
6376
6379
  useEscapeKey(isOpen, () => {
6377
6380
  close();
6378
6381
  triggerRef.current?.focus({ preventScroll: true });
@@ -7313,7 +7316,7 @@ var TimePicker = (props) => {
7313
7316
  }, [step, min, max]);
7314
7317
  const close = import_react40.default.useCallback(() => setOpen(false), []);
7315
7318
  useClickOutside_default([triggerRef, contentRef], close, isOpen);
7316
- useCloseOnContainerScroll(isOpen, contentRef, close);
7319
+ useCloseWhenTriggerHidden(isOpen, triggerRef, close);
7317
7320
  useEscapeKey(isOpen, () => {
7318
7321
  close();
7319
7322
  triggerRef.current?.focus({ preventScroll: true });
@@ -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);