@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.
@@ -2951,7 +2951,7 @@ Chip.displayName = "Chip";
2951
2951
  var Chip_default = Chip;
2952
2952
 
2953
2953
  // src/components/DatePicker/InputDatePicker/index.tsx
2954
- import React13 from "react";
2954
+ import React14 from "react";
2955
2955
 
2956
2956
  // src/components/Input/Input.tsx
2957
2957
  import React8 from "react";
@@ -3124,11 +3124,149 @@ PasswordInput.displayName = "PasswordInput";
3124
3124
  var PasswordInput_default = PasswordInput;
3125
3125
 
3126
3126
  // src/components/Modal/Modal.tsx
3127
- import React11 from "react";
3127
+ import React12 from "react";
3128
3128
  import { createPortal } from "react-dom";
3129
3129
 
3130
3130
  // src/tokens/hooks/useOverlayKeyboard.ts
3131
+ import React11 from "react";
3132
+
3133
+ // src/tokens/hooks/useAutoPosition.ts
3131
3134
  import React10 from "react";
3135
+ var findScrollParent = (el) => {
3136
+ for (let p = el.parentElement; p; p = p.parentElement) {
3137
+ const { overflowY, overflowX } = getComputedStyle(p);
3138
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
3139
+ }
3140
+ return null;
3141
+ };
3142
+ var TRIGGER_GAP = 8;
3143
+ var computePlacement = (triggerRect, popW, popH, clip) => {
3144
+ const roomBelow = clip.bottom - triggerRect.bottom - TRIGGER_GAP;
3145
+ const roomAbove = triggerRect.top - clip.top - TRIGGER_GAP;
3146
+ let direction;
3147
+ let top;
3148
+ let maxHeight = null;
3149
+ if (popH <= roomBelow) {
3150
+ direction = "bottom";
3151
+ top = triggerRect.bottom + TRIGGER_GAP;
3152
+ } else if (popH <= roomAbove) {
3153
+ direction = "top";
3154
+ top = triggerRect.top - TRIGGER_GAP - popH;
3155
+ } else {
3156
+ const room = Math.max(roomBelow, roomAbove, 0);
3157
+ if (roomBelow >= roomAbove) {
3158
+ direction = "bottom";
3159
+ top = triggerRect.bottom + TRIGGER_GAP;
3160
+ } else {
3161
+ direction = "top";
3162
+ top = triggerRect.top - TRIGGER_GAP - room;
3163
+ }
3164
+ maxHeight = room;
3165
+ }
3166
+ let left = triggerRect.left;
3167
+ if (left + popW > clip.right - 8) {
3168
+ left = triggerRect.right - popW;
3169
+ }
3170
+ if (left < clip.left + 8) left = clip.left + 8;
3171
+ const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
3172
+ return {
3173
+ direction,
3174
+ top,
3175
+ left,
3176
+ maxHeight,
3177
+ over: {
3178
+ top: Math.max(0, clip.top - top),
3179
+ right: Math.max(0, left + popW - clip.right),
3180
+ bottom: Math.max(0, top + drawnH - clip.bottom),
3181
+ left: Math.max(0, clip.left - left)
3182
+ }
3183
+ };
3184
+ };
3185
+ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3186
+ const directionRef = React10.useRef("bottom");
3187
+ const sizeRef = React10.useRef(null);
3188
+ const scrollParentRef = React10.useRef(null);
3189
+ const placedRef = React10.useRef(false);
3190
+ const calculatePosition = React10.useCallback((remeasure = false) => {
3191
+ const pop = popRef.current;
3192
+ if (!triggerRef.current || !pop) return;
3193
+ if (remeasure || !sizeRef.current) {
3194
+ sizeRef.current = {
3195
+ w: pop.offsetWidth,
3196
+ h: Math.max(pop.offsetHeight, pop.scrollHeight)
3197
+ };
3198
+ }
3199
+ const { w: popW, h: popH } = sizeRef.current;
3200
+ const triggerRect = triggerRef.current.getBoundingClientRect();
3201
+ if (popH === 0 || popW === 0) {
3202
+ sizeRef.current = null;
3203
+ return;
3204
+ }
3205
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
3206
+ const clip = {
3207
+ top: Math.max(parentRect?.top ?? 0, 0),
3208
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
3209
+ left: Math.max(parentRect?.left ?? 0, 0),
3210
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
3211
+ };
3212
+ const first = !placedRef.current;
3213
+ if (first) pop.style.transition = "none";
3214
+ const { direction: next, top, left, over, maxHeight } = computePlacement(
3215
+ triggerRect,
3216
+ popW,
3217
+ popH,
3218
+ clip
3219
+ );
3220
+ pop.style.top = `${top + window.scrollY}px`;
3221
+ pop.style.left = `${left + window.scrollX}px`;
3222
+ pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
3223
+ 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";
3224
+ directionRef.current = next;
3225
+ pop.classList.toggle("top", next === "top");
3226
+ pop.classList.toggle("bottom", next === "bottom");
3227
+ if (first) {
3228
+ void pop.offsetHeight;
3229
+ pop.style.transition = "";
3230
+ placedRef.current = true;
3231
+ }
3232
+ }, [triggerRef, popRef]);
3233
+ React10.useLayoutEffect(() => {
3234
+ if (!enabled) {
3235
+ sizeRef.current = null;
3236
+ scrollParentRef.current = null;
3237
+ placedRef.current = false;
3238
+ return;
3239
+ }
3240
+ if (triggerRef.current) {
3241
+ scrollParentRef.current = findScrollParent(triggerRef.current);
3242
+ }
3243
+ calculatePosition(true);
3244
+ const raf = requestAnimationFrame(() => calculatePosition(true));
3245
+ return () => cancelAnimationFrame(raf);
3246
+ }, [calculatePosition, enabled, triggerRef]);
3247
+ React10.useEffect(() => {
3248
+ if (!enabled || !popRef.current) return;
3249
+ const observer = new ResizeObserver(() => {
3250
+ calculatePosition(true);
3251
+ });
3252
+ observer.observe(popRef.current);
3253
+ return () => observer.disconnect();
3254
+ }, [calculatePosition, enabled, popRef]);
3255
+ React10.useEffect(() => {
3256
+ if (!enabled) return;
3257
+ const onScroll = () => calculatePosition();
3258
+ const onResize = () => calculatePosition(true);
3259
+ window.addEventListener("resize", onResize, { passive: true });
3260
+ window.addEventListener("scroll", onScroll, { passive: true, capture: true });
3261
+ return () => {
3262
+ window.removeEventListener("resize", onResize);
3263
+ window.removeEventListener("scroll", onScroll, true);
3264
+ };
3265
+ }, [calculatePosition, enabled]);
3266
+ };
3267
+ var useAutoPosition_default = useAutoPosition;
3268
+
3269
+ // src/tokens/hooks/useOverlayKeyboard.ts
3132
3270
  var FOCUSABLE = [
3133
3271
  "a[href]",
3134
3272
  "button:not([disabled])",
@@ -3142,7 +3280,7 @@ var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
3142
3280
  (n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
3143
3281
  );
3144
3282
  var useEscapeKey = (enabled, onEscape) => {
3145
- React10.useEffect(() => {
3283
+ React11.useEffect(() => {
3146
3284
  if (!enabled) return;
3147
3285
  const onKey = (e) => {
3148
3286
  if (e.key !== "Escape") return;
@@ -3156,8 +3294,8 @@ var useEscapeKey = (enabled, onEscape) => {
3156
3294
  };
3157
3295
  var useFocusTrap = (containerRef, enabled, options = {}) => {
3158
3296
  const { trap = false, initialFocus } = options;
3159
- const restoreRef = React10.useRef(null);
3160
- React10.useEffect(() => {
3297
+ const restoreRef = React11.useRef(null);
3298
+ React11.useEffect(() => {
3161
3299
  if (!enabled) return;
3162
3300
  restoreRef.current = document.activeElement;
3163
3301
  const raf = requestAnimationFrame(() => {
@@ -3175,7 +3313,7 @@ var useFocusTrap = (containerRef, enabled, options = {}) => {
3175
3313
  if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
3176
3314
  };
3177
3315
  }, [enabled, containerRef, initialFocus]);
3178
- React10.useEffect(() => {
3316
+ React11.useEffect(() => {
3179
3317
  if (!enabled || !trap) return;
3180
3318
  const onKey = (e) => {
3181
3319
  if (e.key !== "Tab") return;
@@ -3201,22 +3339,25 @@ var useFocusTrap = (containerRef, enabled, options = {}) => {
3201
3339
  return () => document.removeEventListener("keydown", onKey);
3202
3340
  }, [enabled, trap, containerRef]);
3203
3341
  };
3204
- var useCloseOnContainerScroll = (enabled, popRef, onClose) => {
3205
- const onCloseRef = React10.useRef(onClose);
3342
+ var useCloseWhenFocusHidden = (enabled, triggerRef, popRef, onClose) => {
3343
+ const onCloseRef = React11.useRef(onClose);
3206
3344
  onCloseRef.current = onClose;
3207
- React10.useEffect(() => {
3208
- if (!enabled) return;
3209
- const onScroll = (e) => {
3210
- const target = e.target;
3211
- if (target === document || target === document.documentElement || target === document.body) {
3212
- return;
3213
- }
3214
- if (target instanceof Node && popRef.current?.contains(target)) return;
3215
- onCloseRef.current();
3216
- };
3217
- window.addEventListener("scroll", onScroll, { passive: true, capture: true });
3218
- return () => window.removeEventListener("scroll", onScroll, true);
3219
- }, [enabled, popRef]);
3345
+ React11.useEffect(() => {
3346
+ const trigger = triggerRef.current;
3347
+ if (!enabled || !trigger) return;
3348
+ const observer = new IntersectionObserver(
3349
+ ([entry]) => {
3350
+ if (entry.isIntersecting) return;
3351
+ if (!popRef.current?.contains(document.activeElement)) return;
3352
+ onCloseRef.current();
3353
+ trigger.focus({ preventScroll: true });
3354
+ },
3355
+ // 그릇이 없으면 root: null → 뷰포트 기준
3356
+ { root: findScrollParent(trigger), threshold: 0 }
3357
+ );
3358
+ observer.observe(trigger);
3359
+ return () => observer.disconnect();
3360
+ }, [enabled, triggerRef, popRef]);
3220
3361
  };
3221
3362
 
3222
3363
  // src/components/Modal/Modal.tsx
@@ -3224,13 +3365,13 @@ import { jsx as jsx313 } from "react/jsx-runtime";
3224
3365
  var ANIMATION_DURATION_MS = 200;
3225
3366
  var Modal = (props) => {
3226
3367
  const { isOpen, onClose, children } = props;
3227
- const [mounted, setMounted] = React11.useState(false);
3228
- const [visible, setVisible] = React11.useState(false);
3229
- const [settled, setSettled] = React11.useState(false);
3230
- const boxRef = React11.useRef(null);
3368
+ const [mounted, setMounted] = React12.useState(false);
3369
+ const [visible, setVisible] = React12.useState(false);
3370
+ const [settled, setSettled] = React12.useState(false);
3371
+ const boxRef = React12.useRef(null);
3231
3372
  useEscapeKey(isOpen, onClose);
3232
3373
  useFocusTrap(boxRef, isOpen && mounted, { trap: true });
3233
- React11.useEffect(() => {
3374
+ React12.useEffect(() => {
3234
3375
  if (isOpen) {
3235
3376
  setMounted(true);
3236
3377
  const show = setTimeout(() => setVisible(true), 1);
@@ -3274,9 +3415,9 @@ Modal.displayName = "Modal";
3274
3415
  var Modal_default = Modal;
3275
3416
 
3276
3417
  // src/components/DatePicker/SingleDatePicker/index.tsx
3277
- import React12 from "react";
3418
+ import React13 from "react";
3278
3419
  import { Fragment as Fragment4, jsx as jsx314, jsxs as jsxs200 } from "react/jsx-runtime";
3279
- var DayCell2 = React12.memo(
3420
+ var DayCell2 = React13.memo(
3280
3421
  ({
3281
3422
  day,
3282
3423
  disabled,
@@ -3325,33 +3466,33 @@ var SingleDatePicker = (props) => {
3325
3466
  required,
3326
3467
  validations
3327
3468
  } = props;
3328
- const labelId = React12.useId();
3469
+ const labelId = React13.useId();
3329
3470
  const initialYear = value?.getFullYear();
3330
3471
  const initialMonth = value?.getMonth();
3331
3472
  const { year, month, days, goToPrevMonth, goToNextMonth, setYear, setMonth } = useCalendar(
3332
3473
  initialYear,
3333
3474
  initialMonth
3334
3475
  );
3335
- const [pickerMode, setPickerMode] = React12.useState("days");
3336
- const [yearRangeStart, setYearRangeStart] = React12.useState(
3476
+ const [pickerMode, setPickerMode] = React13.useState("days");
3477
+ const [yearRangeStart, setYearRangeStart] = React13.useState(
3337
3478
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
3338
3479
  );
3339
- const minTime = React12.useMemo(
3480
+ const minTime = React13.useMemo(
3340
3481
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
3341
3482
  [minDate]
3342
3483
  );
3343
- const maxTime = React12.useMemo(
3484
+ const maxTime = React13.useMemo(
3344
3485
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
3345
3486
  [maxDate]
3346
3487
  );
3347
- const highlightSet = React12.useMemo(() => {
3488
+ const highlightSet = React13.useMemo(() => {
3348
3489
  const set = /* @__PURE__ */ new Set();
3349
3490
  for (const h of highlightDates) {
3350
3491
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
3351
3492
  }
3352
3493
  return set;
3353
3494
  }, [highlightDates]);
3354
- const handleSelect = React12.useCallback(
3495
+ const handleSelect = React13.useCallback(
3355
3496
  (date) => {
3356
3497
  onChange?.(date);
3357
3498
  },
@@ -3494,8 +3635,8 @@ var InputDatePicker = (props) => {
3494
3635
  required,
3495
3636
  validations
3496
3637
  } = props;
3497
- const [isOpen, setIsOpen] = React13.useState(false);
3498
- const [tempDate, setTempDate] = React13.useState(value ?? /* @__PURE__ */ new Date());
3638
+ const [isOpen, setIsOpen] = React14.useState(false);
3639
+ const [tempDate, setTempDate] = React14.useState(value ?? /* @__PURE__ */ new Date());
3499
3640
  const handleOpen = () => {
3500
3641
  if (disabled) return;
3501
3642
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -3547,18 +3688,18 @@ InputDatePicker.displayName = "InputDatePicker";
3547
3688
  var InputDatePicker_default = InputDatePicker;
3548
3689
 
3549
3690
  // src/components/DatePicker/PopupPicker/index.tsx
3550
- import React17 from "react";
3691
+ import React18 from "react";
3551
3692
 
3552
3693
  // src/components/DatePicker/RangePicker/index.tsx
3553
- import React16 from "react";
3694
+ import React17 from "react";
3554
3695
 
3555
3696
  // src/components/Tab/Tab.tsx
3556
- import React15 from "react";
3697
+ import React16 from "react";
3557
3698
 
3558
3699
  // src/components/Tab/TabItem.tsx
3559
- import React14 from "react";
3700
+ import React15 from "react";
3560
3701
  import { jsx as jsx316 } from "react/jsx-runtime";
3561
- var TabItem = React14.forwardRef((props, ref) => {
3702
+ var TabItem = React15.forwardRef((props, ref) => {
3562
3703
  const { isActive: isActive2, title, onClick } = props;
3563
3704
  return /* @__PURE__ */ jsx316(
3564
3705
  "button",
@@ -3582,11 +3723,11 @@ import { jsx as jsx317, jsxs as jsxs202 } from "react/jsx-runtime";
3582
3723
  var Tab = (props) => {
3583
3724
  const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
3584
3725
  const shape = variant ?? type ?? "default";
3585
- const [underlineStyle, setUnderlineStyle] = React15.useState({
3726
+ const [underlineStyle, setUnderlineStyle] = React16.useState({
3586
3727
  left: 0,
3587
3728
  width: 0
3588
3729
  });
3589
- const itemRefs = React15.useRef([]);
3730
+ const itemRefs = React16.useRef([]);
3590
3731
  const handleKeyDown = (e) => {
3591
3732
  const last = tabs.length - 1;
3592
3733
  let next = null;
@@ -3602,7 +3743,7 @@ var Tab = (props) => {
3602
3743
  const handleChangeActiveTab = (tabItem, tabIdx) => {
3603
3744
  onChange(tabItem, tabIdx);
3604
3745
  };
3605
- React15.useEffect(() => {
3746
+ React16.useEffect(() => {
3606
3747
  const el = itemRefs.current[activeIndex];
3607
3748
  if (el) {
3608
3749
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
@@ -3658,8 +3799,8 @@ var RangePicker = (props) => {
3658
3799
  required,
3659
3800
  validations
3660
3801
  } = props;
3661
- const labelId = React16.useId();
3662
- const [activeTab, setActiveTab] = React16.useState("start");
3802
+ const labelId = React17.useId();
3803
+ const [activeTab, setActiveTab] = React17.useState("start");
3663
3804
  const handleStartChange = (date) => {
3664
3805
  if (!date) return;
3665
3806
  const newStart = date > endDate ? endDate : date;
@@ -3753,7 +3894,7 @@ var RangePicker_default = RangePicker;
3753
3894
  import { jsx as jsx319, jsxs as jsxs204 } from "react/jsx-runtime";
3754
3895
  var PopupPicker = (props) => {
3755
3896
  const { component, type, locale } = props;
3756
- const [isOpen, setIsOpen] = React17.useState(false);
3897
+ const [isOpen, setIsOpen] = React18.useState(false);
3757
3898
  const handleClick = () => setIsOpen(true);
3758
3899
  const handleClose = () => setIsOpen(false);
3759
3900
  const handleSingleChange = (date) => {
@@ -3762,7 +3903,7 @@ var PopupPicker = (props) => {
3762
3903
  handleClose();
3763
3904
  };
3764
3905
  return /* @__PURE__ */ jsxs204("div", { className: "lib-xplat-popup-datepicker", children: [
3765
- React17.cloneElement(component, { onClick: handleClick }),
3906
+ React18.cloneElement(component, { onClick: handleClick }),
3766
3907
  /* @__PURE__ */ jsx319(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ jsxs204("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
3767
3908
  /* @__PURE__ */ jsxs204("div", { className: "popup-datepicker-content", children: [
3768
3909
  type === "single" && /* @__PURE__ */ jsx319(
@@ -3821,18 +3962,18 @@ Divider.displayName = "Divider";
3821
3962
  var Divider_default = Divider;
3822
3963
 
3823
3964
  // src/components/Drawer/Drawer.tsx
3824
- import React18 from "react";
3965
+ import React19 from "react";
3825
3966
  import { createPortal as createPortal2 } from "react-dom";
3826
3967
  import { jsx as jsx321, jsxs as jsxs205 } from "react/jsx-runtime";
3827
3968
  var ANIMATION_DURATION_MS2 = 250;
3828
3969
  var Drawer = (props) => {
3829
3970
  const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
3830
- const [mounted, setMounted] = React18.useState(false);
3831
- const [visible, setVisible] = React18.useState(false);
3832
- const panelRef = React18.useRef(null);
3971
+ const [mounted, setMounted] = React19.useState(false);
3972
+ const [visible, setVisible] = React19.useState(false);
3973
+ const panelRef = React19.useRef(null);
3833
3974
  useEscapeKey(isOpen, onClose);
3834
3975
  useFocusTrap(panelRef, isOpen && mounted, { trap: true });
3835
- React18.useEffect(() => {
3976
+ React19.useEffect(() => {
3836
3977
  if (isOpen) {
3837
3978
  setMounted(true);
3838
3979
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -3888,142 +4029,6 @@ var Portal = ({ children }) => {
3888
4029
  Portal.displayName = "Portal";
3889
4030
  var Portal_default = Portal;
3890
4031
 
3891
- // src/tokens/hooks/useAutoPosition.ts
3892
- import React19 from "react";
3893
- var findScrollParent = (el) => {
3894
- for (let p = el.parentElement; p; p = p.parentElement) {
3895
- const { overflowY, overflowX } = getComputedStyle(p);
3896
- if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
3897
- }
3898
- return null;
3899
- };
3900
- var TRIGGER_GAP = 8;
3901
- var computePlacement = (triggerRect, popW, popH, clip) => {
3902
- const roomBelow = clip.bottom - triggerRect.bottom - TRIGGER_GAP;
3903
- const roomAbove = triggerRect.top - clip.top - TRIGGER_GAP;
3904
- let direction;
3905
- let top;
3906
- let maxHeight = null;
3907
- if (popH <= roomBelow) {
3908
- direction = "bottom";
3909
- top = triggerRect.bottom + TRIGGER_GAP;
3910
- } else if (popH <= roomAbove) {
3911
- direction = "top";
3912
- top = triggerRect.top - TRIGGER_GAP - popH;
3913
- } else {
3914
- const room = Math.max(roomBelow, roomAbove, 0);
3915
- if (roomBelow >= roomAbove) {
3916
- direction = "bottom";
3917
- top = triggerRect.bottom + TRIGGER_GAP;
3918
- } else {
3919
- direction = "top";
3920
- top = triggerRect.top - TRIGGER_GAP - room;
3921
- }
3922
- maxHeight = room;
3923
- }
3924
- let left = triggerRect.left;
3925
- if (left + popW > clip.right - 8) {
3926
- left = triggerRect.right - popW;
3927
- }
3928
- if (left < clip.left + 8) left = clip.left + 8;
3929
- const drawnH = maxHeight === null ? popH : Math.min(popH, maxHeight);
3930
- return {
3931
- direction,
3932
- top,
3933
- left,
3934
- maxHeight,
3935
- over: {
3936
- top: Math.max(0, clip.top - top),
3937
- right: Math.max(0, left + popW - clip.right),
3938
- bottom: Math.max(0, top + drawnH - clip.bottom),
3939
- left: Math.max(0, clip.left - left)
3940
- }
3941
- };
3942
- };
3943
- var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3944
- const directionRef = React19.useRef("bottom");
3945
- const sizeRef = React19.useRef(null);
3946
- const scrollParentRef = React19.useRef(null);
3947
- const placedRef = React19.useRef(false);
3948
- const calculatePosition = React19.useCallback((remeasure = false) => {
3949
- const pop = popRef.current;
3950
- if (!triggerRef.current || !pop) return;
3951
- if (remeasure || !sizeRef.current) {
3952
- sizeRef.current = {
3953
- w: pop.offsetWidth,
3954
- h: Math.max(pop.offsetHeight, pop.scrollHeight)
3955
- };
3956
- }
3957
- const { w: popW, h: popH } = sizeRef.current;
3958
- const triggerRect = triggerRef.current.getBoundingClientRect();
3959
- if (popH === 0 || popW === 0) {
3960
- sizeRef.current = null;
3961
- return;
3962
- }
3963
- const parentRect = scrollParentRef.current?.getBoundingClientRect();
3964
- const clip = {
3965
- top: Math.max(parentRect?.top ?? 0, 0),
3966
- bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
3967
- left: Math.max(parentRect?.left ?? 0, 0),
3968
- right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
3969
- };
3970
- const first = !placedRef.current;
3971
- if (first) pop.style.transition = "none";
3972
- const { direction: next, top, left, over, maxHeight } = computePlacement(
3973
- triggerRect,
3974
- popW,
3975
- popH,
3976
- clip
3977
- );
3978
- pop.style.top = `${top + window.scrollY}px`;
3979
- pop.style.left = `${left + window.scrollX}px`;
3980
- pop.style.maxHeight = maxHeight === null ? "" : `${maxHeight}px`;
3981
- 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";
3982
- directionRef.current = next;
3983
- pop.classList.toggle("top", next === "top");
3984
- pop.classList.toggle("bottom", next === "bottom");
3985
- if (first) {
3986
- void pop.offsetHeight;
3987
- pop.style.transition = "";
3988
- placedRef.current = true;
3989
- }
3990
- }, [triggerRef, popRef]);
3991
- React19.useLayoutEffect(() => {
3992
- if (!enabled) {
3993
- sizeRef.current = null;
3994
- scrollParentRef.current = null;
3995
- placedRef.current = false;
3996
- return;
3997
- }
3998
- if (triggerRef.current) {
3999
- scrollParentRef.current = findScrollParent(triggerRef.current);
4000
- }
4001
- calculatePosition(true);
4002
- const raf = requestAnimationFrame(() => calculatePosition(true));
4003
- return () => cancelAnimationFrame(raf);
4004
- }, [calculatePosition, enabled, triggerRef]);
4005
- React19.useEffect(() => {
4006
- if (!enabled || !popRef.current) return;
4007
- const observer = new ResizeObserver(() => {
4008
- calculatePosition(true);
4009
- });
4010
- observer.observe(popRef.current);
4011
- return () => observer.disconnect();
4012
- }, [calculatePosition, enabled, popRef]);
4013
- React19.useEffect(() => {
4014
- if (!enabled) return;
4015
- const onScroll = () => calculatePosition();
4016
- const onResize = () => calculatePosition(true);
4017
- window.addEventListener("resize", onResize, { passive: true });
4018
- window.addEventListener("scroll", onScroll, { passive: true, capture: true });
4019
- return () => {
4020
- window.removeEventListener("resize", onResize);
4021
- window.removeEventListener("scroll", onScroll, true);
4022
- };
4023
- }, [calculatePosition, enabled]);
4024
- };
4025
- var useAutoPosition_default = useAutoPosition;
4026
-
4027
4032
  // src/tokens/hooks/useClickOutside.ts
4028
4033
  import React20 from "react";
4029
4034
  var useClickOutside = (refs, handler, enabled = true) => {
@@ -4060,7 +4065,7 @@ var Dropdown = (props) => {
4060
4065
  const menuRef = React21.useRef(null);
4061
4066
  useAutoPosition_default(triggerRef, menuRef, mounted);
4062
4067
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
4063
- useCloseOnContainerScroll(isOpen, menuRef, () => setIsOpen(false));
4068
+ useCloseWhenFocusHidden(isOpen, triggerRef, menuRef, () => setIsOpen(false));
4064
4069
  useEscapeKey(isOpen, () => {
4065
4070
  setIsOpen(false);
4066
4071
  triggerRef.current?.focus({ preventScroll: true });
@@ -5991,7 +5996,7 @@ var PopOver = (props) => {
5991
5996
  const [localOpen, setLocalOpen] = React27.useState(false);
5992
5997
  const [eventTrigger, setEventTrigger] = React27.useState(false);
5993
5998
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
5994
- useCloseOnContainerScroll(isOpen, popRef, onClose);
5999
+ useCloseWhenFocusHidden(isOpen, triggerRef, popRef, onClose);
5995
6000
  useEscapeKey(isOpen, () => {
5996
6001
  onClose();
5997
6002
  triggerRef.current?.focus({ preventScroll: true });
@@ -6271,7 +6276,7 @@ var SelectRoot = (props) => {
6271
6276
  }, []);
6272
6277
  const toggle = React31.useCallback(() => setOpen((prev) => !prev), []);
6273
6278
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
6274
- useCloseOnContainerScroll(isOpen, contentRef, close);
6279
+ useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
6275
6280
  useEscapeKey(isOpen, () => {
6276
6281
  close();
6277
6282
  triggerRef.current?.focus({ preventScroll: true });
@@ -7212,7 +7217,7 @@ var TimePicker = (props) => {
7212
7217
  }, [step, min, max]);
7213
7218
  const close = React40.useCallback(() => setOpen(false), []);
7214
7219
  useClickOutside_default([triggerRef, contentRef], close, isOpen);
7215
- useCloseOnContainerScroll(isOpen, contentRef, close);
7220
+ useCloseWhenFocusHidden(isOpen, triggerRef, contentRef, close);
7216
7221
  useEscapeKey(isOpen, () => {
7217
7222
  close();
7218
7223
  triggerRef.current?.focus({ preventScroll: true });