@bigtablet/design-system 3.7.0 → 3.8.0

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
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import './index.css';
3
- import * as React15 from 'react';
3
+ import * as React16 from 'react';
4
4
  import { createContext, useRef, useState, useId, useEffect, useContext, useCallback, useMemo, Fragment, useImperativeHandle, useLayoutEffect } from 'react';
5
5
  import { useSpring, animated } from '@react-spring/web';
6
6
  import { ChevronDown, ChevronRight, Globe, ChevronLeft, ArrowUp, ArrowDown, ArrowUpDown, XCircle, AlertTriangle, CheckCircle2, Info, Bell, Search, Check, Image, X, TriangleAlert } from 'lucide-react';
@@ -58,15 +58,137 @@ function registerOverlay(onEscape) {
58
58
  };
59
59
  }
60
60
  function useOverlayEscape(active, onEscape) {
61
- const handlerRef = React15.useRef(onEscape);
62
- React15.useEffect(() => {
61
+ const handlerRef = React16.useRef(onEscape);
62
+ React16.useEffect(() => {
63
63
  handlerRef.current = onEscape;
64
64
  });
65
- React15.useEffect(() => {
65
+ React16.useEffect(() => {
66
66
  if (!active) return;
67
67
  return registerOverlay(() => handlerRef.current());
68
68
  }, [active]);
69
69
  }
70
+ var useSafeLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
71
+
72
+ // src/utils/use-anchored-position.ts
73
+ var OPPOSITE = {
74
+ top: "bottom",
75
+ bottom: "top",
76
+ left: "right",
77
+ right: "left"
78
+ };
79
+ var isVertical = (side) => side === "top" || side === "bottom";
80
+ var clamp = (value, min, max) => (
81
+ // max < min(가용 공간이 플로팅보다 작을 때)이면 min(가장자리 여백)에 고정.
82
+ Math.max(min, Math.min(max, value))
83
+ );
84
+ var mainAxisStart = (side, anchor, floating, gap) => {
85
+ switch (side) {
86
+ case "top":
87
+ return anchor.top - gap - floating.height;
88
+ case "bottom":
89
+ return anchor.top + anchor.height + gap;
90
+ case "left":
91
+ return anchor.left - gap - floating.width;
92
+ case "right":
93
+ return anchor.left + anchor.width + gap;
94
+ }
95
+ };
96
+ var fitsMainAxis = (side, anchor, floating, viewport, gap, padding) => {
97
+ const start = mainAxisStart(side, anchor, floating, gap);
98
+ switch (side) {
99
+ case "top":
100
+ return start >= padding;
101
+ case "bottom":
102
+ return start + floating.height <= viewport.height - padding;
103
+ case "left":
104
+ return start >= padding;
105
+ case "right":
106
+ return start + floating.width <= viewport.width - padding;
107
+ }
108
+ };
109
+ function computeAnchoredPosition(anchor, floating, viewport, options) {
110
+ const gap = options.gap ?? 8;
111
+ const padding = options.padding;
112
+ const available = viewport.width - padding * 2;
113
+ const maxWidth = available;
114
+ const sized = {
115
+ width: Math.min(floating.width, available),
116
+ height: floating.height
117
+ };
118
+ let side = options.placement;
119
+ if (!fitsMainAxis(side, anchor, sized, viewport, gap, padding) && fitsMainAxis(OPPOSITE[side], anchor, sized, viewport, gap, padding)) {
120
+ side = OPPOSITE[side];
121
+ }
122
+ let x;
123
+ let y;
124
+ if (isVertical(side)) {
125
+ y = mainAxisStart(side, anchor, sized, gap);
126
+ x = anchor.left + anchor.width / 2 - sized.width / 2;
127
+ x = clamp(x, padding, viewport.width - padding - sized.width);
128
+ } else {
129
+ x = mainAxisStart(side, anchor, sized, gap);
130
+ y = anchor.top + anchor.height / 2 - sized.height / 2;
131
+ y = clamp(y, padding, viewport.height - padding - sized.height);
132
+ }
133
+ return { x, y, placement: side, maxWidth };
134
+ }
135
+ function useAnchoredPosition({
136
+ open,
137
+ anchorRef,
138
+ floatingRef,
139
+ placement,
140
+ gap,
141
+ padding
142
+ }) {
143
+ const [state, setState] = React16.useState({
144
+ x: 0,
145
+ y: 0,
146
+ placement,
147
+ maxWidth: 0,
148
+ ready: false
149
+ });
150
+ useSafeLayoutEffect(() => {
151
+ if (!open) {
152
+ setState((prev) => prev.ready ? { ...prev, ready: false } : prev);
153
+ return;
154
+ }
155
+ const anchor = anchorRef.current;
156
+ const floating = floatingRef.current;
157
+ if (!anchor || !floating) return;
158
+ const update = () => {
159
+ const a = anchor.getBoundingClientRect();
160
+ const f = floating.getBoundingClientRect();
161
+ const result = computeAnchoredPosition(
162
+ { top: a.top, left: a.left, width: a.width, height: a.height },
163
+ { width: f.width, height: f.height },
164
+ { width: window.innerWidth, height: window.innerHeight },
165
+ { placement, gap, padding }
166
+ );
167
+ setState({ ...result, ready: true });
168
+ };
169
+ let frame = 0;
170
+ const schedule = () => {
171
+ if (frame) return;
172
+ frame = requestAnimationFrame(() => {
173
+ frame = 0;
174
+ update();
175
+ });
176
+ };
177
+ update();
178
+ window.addEventListener("scroll", schedule, true);
179
+ window.addEventListener("resize", schedule);
180
+ const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(schedule) : null;
181
+ observer?.observe(floating);
182
+ observer?.observe(anchor);
183
+ return () => {
184
+ if (frame) cancelAnimationFrame(frame);
185
+ window.removeEventListener("scroll", schedule, true);
186
+ window.removeEventListener("resize", schedule);
187
+ observer?.disconnect();
188
+ };
189
+ }, [open, placement, gap, padding, anchorRef, floatingRef]);
190
+ return state;
191
+ }
70
192
  var FOCUSABLE_SELECTORS = [
71
193
  "a[href]",
72
194
  "button:not([disabled])",
@@ -76,8 +198,8 @@ var FOCUSABLE_SELECTORS = [
76
198
  '[tabindex]:not([tabindex="-1"])'
77
199
  ].join(", ");
78
200
  function useFocusTrap(containerRef, isActive) {
79
- const previousActiveElement = React15.useRef(null);
80
- React15.useEffect(() => {
201
+ const previousActiveElement = React16.useRef(null);
202
+ React16.useEffect(() => {
81
203
  if (!isActive) return;
82
204
  const container = containerRef.current;
83
205
  if (!container) return;
@@ -126,8 +248,8 @@ function useFocusTrap(containerRef, isActive) {
126
248
  }, [isActive, containerRef]);
127
249
  }
128
250
  function useIsMounted() {
129
- const [mounted, setMounted] = React15.useState(false);
130
- React15.useEffect(() => {
251
+ const [mounted, setMounted] = React16.useState(false);
252
+ React16.useEffect(() => {
131
253
  setMounted(true);
132
254
  }, []);
133
255
  return mounted;
@@ -161,14 +283,13 @@ function getServerSnapshot() {
161
283
  return false;
162
284
  }
163
285
  function useReducedMotion() {
164
- return React15.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
286
+ return React16.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
165
287
  }
166
- var useSafeLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
167
288
  function useSpringHover({
168
289
  scale = 1.02,
169
290
  lift = -2
170
291
  } = {}) {
171
- const [hovered, setHovered] = React15.useState(false);
292
+ const [hovered, setHovered] = React16.useState(false);
172
293
  const reduced = useReducedMotion();
173
294
  const style = useSpring({
174
295
  transform: hovered ? `translateY(${lift}px) scale(${scale})` : "translateY(0px) scale(1)",
@@ -232,9 +353,9 @@ var Accordion = ({
232
353
  ...props
233
354
  }) => {
234
355
  const isControlled = controlledKeys !== void 0;
235
- const [internalKeys, setInternalKeys] = React15.useState(defaultOpenKeys);
356
+ const [internalKeys, setInternalKeys] = React16.useState(defaultOpenKeys);
236
357
  const open = isControlled ? controlledKeys ?? [] : internalKeys;
237
- const idPrefix = React15.useId();
358
+ const idPrefix = React16.useId();
238
359
  const toggle = (key) => {
239
360
  const isOpen = open.includes(key);
240
361
  const next = isOpen ? open.filter((k) => k !== key) : multiple ? [...open, key] : [key];
@@ -300,7 +421,7 @@ var Avatar = ({
300
421
  style,
301
422
  ...props
302
423
  }) => {
303
- const [imgFailed, setImgFailed] = React15.useState(false);
424
+ const [imgFailed, setImgFailed] = React16.useState(false);
304
425
  const showImage = src && !imgFailed;
305
426
  const initials = getInitials(name);
306
427
  return /* @__PURE__ */ jsx(
@@ -519,12 +640,12 @@ var Breadcrumb = ({
519
640
  }) }) });
520
641
  };
521
642
  var Menu = ({ items, trigger, align = "start" }) => {
522
- const [open, setOpen] = React15.useState(false);
523
- const wrapperRef = React15.useRef(null);
524
- const itemRefs = React15.useRef([]);
525
- const menuId = React15.useId();
643
+ const [open, setOpen] = React16.useState(false);
644
+ const wrapperRef = React16.useRef(null);
645
+ const itemRefs = React16.useRef([]);
646
+ const menuId = React16.useId();
526
647
  const style = useSpringPresence({ visible: open, from: "translateY(-4px)" });
527
- React15.useEffect(() => {
648
+ React16.useEffect(() => {
528
649
  if (!open) return;
529
650
  const handleClick = (e) => {
530
651
  if (!wrapperRef.current?.contains(e.target)) setOpen(false);
@@ -539,7 +660,7 @@ var Menu = ({ items, trigger, align = "start" }) => {
539
660
  document.removeEventListener("keydown", handleEsc);
540
661
  };
541
662
  }, [open]);
542
- React15.useEffect(() => {
663
+ React16.useEffect(() => {
543
664
  const active = document.activeElement;
544
665
  if (!open || active && itemRefs.current.includes(active)) return;
545
666
  const first = items.findIndex((it) => !it.disabled);
@@ -585,7 +706,7 @@ var Menu = ({ items, trigger, align = "start" }) => {
585
706
  break;
586
707
  }
587
708
  };
588
- const triggerWithProps = React15.cloneElement(
709
+ const triggerWithProps = React16.cloneElement(
589
710
  trigger,
590
711
  {
591
712
  onClick: () => setOpen((o) => !o),
@@ -727,6 +848,7 @@ var LocaleSwitcher = ({ locale }) => {
727
848
  const itemRefs = useRef([]);
728
849
  const menuId = useId();
729
850
  const currentOption = locale.options.find((o) => o.value === locale.current);
851
+ const currentLabel = currentOption?.label ?? locale.current.toUpperCase();
730
852
  useEffect(() => {
731
853
  if (!open) return;
732
854
  const handler = (e) => {
@@ -800,10 +922,11 @@ var LocaleSwitcher = ({ locale }) => {
800
922
  "aria-haspopup": "menu",
801
923
  "aria-expanded": open,
802
924
  "aria-controls": menuId,
925
+ "aria-label": locale.ariaLabel ?? currentLabel,
803
926
  onClick: () => setOpen((p) => !p),
804
927
  children: [
805
928
  /* @__PURE__ */ jsx(Globe, { size: iconSize.sm, "aria-hidden": "true" }),
806
- !locale.hideLabel && /* @__PURE__ */ jsx("span", { className: "nav_bar_locale_label", children: currentOption?.label ?? locale.current.toUpperCase() }),
929
+ !locale.hideLabel && /* @__PURE__ */ jsx("span", { className: "nav_bar_locale_label", children: currentLabel }),
807
930
  /* @__PURE__ */ jsx(
808
931
  ChevronDown,
809
932
  {
@@ -876,9 +999,9 @@ var Sidebar = ({
876
999
  ...props
877
1000
  }) => {
878
1001
  const isControlled = collapsedProp !== void 0;
879
- const [internalCollapsed, setInternalCollapsed] = React15.useState(defaultCollapsed);
1002
+ const [internalCollapsed, setInternalCollapsed] = React16.useState(defaultCollapsed);
880
1003
  const collapsed = isControlled ? collapsedProp : internalCollapsed;
881
- const toggle = React15.useCallback(() => {
1004
+ const toggle = React16.useCallback(() => {
882
1005
  const next = !collapsed;
883
1006
  if (!isControlled) setInternalCollapsed(next);
884
1007
  onCollapsedChange?.(next);
@@ -951,9 +1074,9 @@ var SidebarSection = ({ label, className, children, ...props }) => {
951
1074
  children
952
1075
  ] });
953
1076
  };
954
- var TabsContext = React15.createContext(null);
1077
+ var TabsContext = React16.createContext(null);
955
1078
  function useTabsContext() {
956
- const ctx = React15.useContext(TabsContext);
1079
+ const ctx = React16.useContext(TabsContext);
957
1080
  if (!ctx) {
958
1081
  throw new Error(
959
1082
  '[Bigtablet DS] <Tab>, <TabList>, <TabPanel>\uC740 \uBC18\uB4DC\uC2DC <Tabs> \uC548\uC5D0 \uC788\uC5B4\uC57C \uD569\uB2C8\uB2E4.\n\n\uC62C\uBC14\uB978 \uC0AC\uC6A9 \uC608:\n <Tabs defaultValue="a">\n <TabList>\n <Tab value="a">A</Tab>\n </TabList>\n <TabPanel value="a">...</TabPanel>\n </Tabs>'
@@ -972,18 +1095,18 @@ var Tabs = ({
972
1095
  ...props
973
1096
  }) => {
974
1097
  const isControlled = controlledValue !== void 0;
975
- const [internalValue, setInternalValue] = React15.useState(defaultValue);
1098
+ const [internalValue, setInternalValue] = React16.useState(defaultValue);
976
1099
  const value = isControlled ? controlledValue : internalValue;
977
- const setValue = React15.useCallback(
1100
+ const setValue = React16.useCallback(
978
1101
  (v) => {
979
1102
  if (!isControlled) setInternalValue(v);
980
1103
  onValueChange?.(v);
981
1104
  },
982
1105
  [isControlled, onValueChange]
983
1106
  );
984
- const orderRef = React15.useRef([]);
985
- const [firstTabValue, setFirstTabValue] = React15.useState();
986
- const registerTab = React15.useCallback((v) => {
1107
+ const orderRef = React16.useRef([]);
1108
+ const [firstTabValue, setFirstTabValue] = React16.useState();
1109
+ const registerTab = React16.useCallback((v) => {
987
1110
  if (!orderRef.current.includes(v)) {
988
1111
  orderRef.current = [...orderRef.current, v];
989
1112
  setFirstTabValue(orderRef.current[0]);
@@ -993,8 +1116,8 @@ var Tabs = ({
993
1116
  setFirstTabValue(orderRef.current[0]);
994
1117
  };
995
1118
  }, []);
996
- const idPrefix = React15.useId();
997
- const ctx = React15.useMemo(
1119
+ const idPrefix = React16.useId();
1120
+ const ctx = React16.useMemo(
998
1121
  () => ({ value, setValue, variant, size, idPrefix, registerTab, firstTabValue }),
999
1122
  [value, setValue, variant, size, idPrefix, registerTab, firstTabValue]
1000
1123
  );
@@ -1002,9 +1125,9 @@ var Tabs = ({
1002
1125
  };
1003
1126
  var TabList = ({ ariaLabel, className, children, ...props }) => {
1004
1127
  const { variant } = useTabsContext();
1005
- const listRef = React15.useRef(null);
1006
- const [indicator, setIndicator] = React15.useState(null);
1007
- const [hasMounted, setHasMounted] = React15.useState(false);
1128
+ const listRef = React16.useRef(null);
1129
+ const [indicator, setIndicator] = React16.useState(null);
1130
+ const [hasMounted, setHasMounted] = React16.useState(false);
1008
1131
  useSafeLayoutEffect(() => {
1009
1132
  const list = listRef.current;
1010
1133
  if (!list) return;
@@ -1067,7 +1190,7 @@ var Tab = ({ value, className, children, onClick, onKeyDown, ...props }) => {
1067
1190
  const panelId = `${ctx.idPrefix}-panel-${value}`;
1068
1191
  const tabId = `${ctx.idPrefix}-tab-${value}`;
1069
1192
  const { registerTab } = ctx;
1070
- React15.useEffect(() => registerTab(value), [registerTab, value]);
1193
+ React16.useEffect(() => registerTab(value), [registerTab, value]);
1071
1194
  const handleClick = (e) => {
1072
1195
  ctx.setValue(value);
1073
1196
  onClick?.(e);
@@ -1137,14 +1260,7 @@ var TabPanel = ({
1137
1260
  }
1138
1261
  );
1139
1262
  };
1140
- var FOCUSABLE_SELECTORS2 = [
1141
- "a[href]",
1142
- "button:not([disabled])",
1143
- "input:not([disabled])",
1144
- "select:not([disabled])",
1145
- "textarea:not([disabled])",
1146
- '[tabindex]:not([tabindex="-1"])'
1147
- ].join(", ");
1263
+ var POPOVER_GAP = 8;
1148
1264
  var Popover = ({
1149
1265
  trigger,
1150
1266
  content,
@@ -1157,23 +1273,31 @@ var Popover = ({
1157
1273
  className
1158
1274
  }) => {
1159
1275
  const isControlled = openProp !== void 0;
1160
- const [internalOpen, setInternalOpen] = React15.useState(defaultOpen);
1276
+ const [internalOpen, setInternalOpen] = React16.useState(defaultOpen);
1161
1277
  const open = isControlled ? openProp : internalOpen;
1162
- const [shouldRender, setShouldRender] = React15.useState(open ?? false);
1278
+ const [shouldRender, setShouldRender] = React16.useState(open ?? false);
1163
1279
  if (open && !shouldRender) setShouldRender(true);
1164
- const wrapperRef = React15.useRef(null);
1165
- const popoverRef = React15.useRef(null);
1166
- const previousFocusRef = React15.useRef(null);
1167
- const popoverId = React15.useId();
1168
- const setOpen = React15.useCallback(
1280
+ const wrapperRef = React16.useRef(null);
1281
+ const positionRef = React16.useRef(null);
1282
+ const popoverRef = React16.useRef(null);
1283
+ const popoverId = React16.useId();
1284
+ const setOpen = React16.useCallback(
1169
1285
  (next) => {
1170
1286
  if (!isControlled) setInternalOpen(next);
1171
1287
  onOpenChange?.(next);
1172
1288
  },
1173
1289
  [isControlled, onOpenChange]
1174
1290
  );
1291
+ const pos = useAnchoredPosition({
1292
+ open: shouldRender,
1293
+ anchorRef: wrapperRef,
1294
+ floatingRef: positionRef,
1295
+ placement,
1296
+ gap: POPOVER_GAP,
1297
+ padding: 8
1298
+ });
1175
1299
  const fromTransform = (() => {
1176
- switch (placement) {
1300
+ switch (pos.placement) {
1177
1301
  case "top":
1178
1302
  return "translateY(4px)";
1179
1303
  case "bottom":
@@ -1184,28 +1308,27 @@ var Popover = ({
1184
1308
  return "translateX(-4px)";
1185
1309
  }
1186
1310
  })();
1187
- const style = useSpringPresence({ visible: open, from: fromTransform, onExitComplete: () => setShouldRender(false) });
1188
- React15.useEffect(() => {
1189
- if (!open) return;
1190
- previousFocusRef.current = document.activeElement;
1191
- const node = popoverRef.current;
1192
- if (!node) return;
1193
- const focusable = node.querySelector(FOCUSABLE_SELECTORS2);
1194
- (focusable ?? node).focus();
1195
- }, [open]);
1196
- React15.useEffect(() => {
1311
+ const style = useSpringPresence({
1312
+ visible: open,
1313
+ from: fromTransform,
1314
+ onExitComplete: () => setShouldRender(false)
1315
+ });
1316
+ useFocusTrap(popoverRef, open);
1317
+ React16.useEffect(() => {
1197
1318
  if (!open) return;
1198
1319
  const handleClick = (e) => {
1199
- if (!wrapperRef.current?.contains(e.target)) setOpen(false);
1320
+ const target = e.target;
1321
+ if (!wrapperRef.current?.contains(target) && !popoverRef.current?.contains(target)) {
1322
+ setOpen(false);
1323
+ }
1200
1324
  };
1201
1325
  document.addEventListener("mousedown", handleClick);
1202
1326
  return () => document.removeEventListener("mousedown", handleClick);
1203
1327
  }, [open, setOpen]);
1204
1328
  useOverlayEscape(open, () => {
1205
1329
  setOpen(false);
1206
- previousFocusRef.current?.focus();
1207
1330
  });
1208
- const triggerWithProps = React15.cloneElement(
1331
+ const triggerWithProps = React16.cloneElement(
1209
1332
  trigger,
1210
1333
  {
1211
1334
  onClick: (e) => {
@@ -1220,23 +1343,43 @@ var Popover = ({
1220
1343
  );
1221
1344
  return /* @__PURE__ */ jsxs("div", { className: "popover_wrapper", ref: wrapperRef, children: [
1222
1345
  triggerWithProps,
1223
- shouldRender && /* @__PURE__ */ jsx("div", { className: cn("popover_position", `popover_placement_${placement}`), children: /* @__PURE__ */ jsx(
1224
- animated.div,
1225
- {
1226
- id: popoverId,
1227
- ref: popoverRef,
1228
- role: "dialog",
1229
- tabIndex: -1,
1230
- "aria-label": ariaLabel,
1231
- "aria-labelledby": ariaLabelledby,
1232
- style,
1233
- className: cn("popover", className),
1234
- children: content
1235
- }
1236
- ) })
1346
+ shouldRender && typeof document !== "undefined" && createPortal(
1347
+ /* @__PURE__ */ jsx(
1348
+ "div",
1349
+ {
1350
+ ref: positionRef,
1351
+ className: "popover_position",
1352
+ style: {
1353
+ position: "fixed",
1354
+ left: pos.x,
1355
+ top: pos.y,
1356
+ // 최초 측정 전(ready=false)에는 maxWidth(=0)를 걸지 않는다 - 걸면 자연 폭 대신
1357
+ // 0px 로 측정돼 첫 프레임 좌표가 어긋난다. ready 후에만 상한 적용.
1358
+ maxWidth: pos.ready ? pos.maxWidth : void 0,
1359
+ visibility: pos.ready ? void 0 : "hidden"
1360
+ },
1361
+ children: /* @__PURE__ */ jsx(
1362
+ animated.div,
1363
+ {
1364
+ id: popoverId,
1365
+ ref: popoverRef,
1366
+ role: "dialog",
1367
+ tabIndex: -1,
1368
+ "aria-label": ariaLabelledby ? ariaLabel : ariaLabel ?? "Dialog",
1369
+ "aria-labelledby": ariaLabelledby,
1370
+ style,
1371
+ className: cn("popover", className),
1372
+ children: content
1373
+ }
1374
+ )
1375
+ }
1376
+ ),
1377
+ document.body
1378
+ )
1237
1379
  ] });
1238
1380
  };
1239
1381
  Popover.displayName = "Popover";
1382
+ var TOOLTIP_GAP = 6;
1240
1383
  var Tooltip = ({
1241
1384
  content,
1242
1385
  placement = "top",
@@ -1244,33 +1387,45 @@ var Tooltip = ({
1244
1387
  disabled = false,
1245
1388
  children
1246
1389
  }) => {
1247
- const [open, setOpen] = React15.useState(false);
1248
- const timerRef = React15.useRef(null);
1249
- const tooltipId = React15.useId();
1390
+ const [open, setOpen] = React16.useState(false);
1391
+ const [shouldRender, setShouldRender] = React16.useState(false);
1392
+ if (open && !shouldRender) setShouldRender(true);
1393
+ const timerRef = React16.useRef(null);
1394
+ const tooltipId = React16.useId();
1395
+ const wrapperRef = React16.useRef(null);
1396
+ const positionRef = React16.useRef(null);
1250
1397
  const HIDE_DELAY = 120;
1251
- const show = React15.useCallback(() => {
1398
+ const show = React16.useCallback(() => {
1252
1399
  if (timerRef.current) clearTimeout(timerRef.current);
1253
1400
  timerRef.current = setTimeout(() => setOpen(true), delay);
1254
1401
  }, [delay]);
1255
- const hideNow = React15.useCallback(() => {
1402
+ const hideNow = React16.useCallback(() => {
1256
1403
  if (timerRef.current) clearTimeout(timerRef.current);
1257
1404
  setOpen(false);
1258
1405
  }, []);
1259
- const hide = React15.useCallback(() => {
1406
+ const hide = React16.useCallback(() => {
1260
1407
  if (timerRef.current) clearTimeout(timerRef.current);
1261
1408
  timerRef.current = setTimeout(() => setOpen(false), HIDE_DELAY);
1262
1409
  }, []);
1263
- const cancelHide = React15.useCallback(() => {
1410
+ const cancelHide = React16.useCallback(() => {
1264
1411
  if (timerRef.current) clearTimeout(timerRef.current);
1265
1412
  }, []);
1266
- React15.useEffect(() => {
1413
+ React16.useEffect(() => {
1267
1414
  return () => {
1268
1415
  if (timerRef.current) clearTimeout(timerRef.current);
1269
1416
  };
1270
1417
  }, []);
1271
1418
  useOverlayEscape(open, hideNow);
1419
+ const pos = useAnchoredPosition({
1420
+ open: shouldRender,
1421
+ anchorRef: wrapperRef,
1422
+ floatingRef: positionRef,
1423
+ placement,
1424
+ gap: TOOLTIP_GAP,
1425
+ padding: 8
1426
+ });
1272
1427
  const fromTransform = (() => {
1273
- switch (placement) {
1428
+ switch (pos.placement) {
1274
1429
  case "top":
1275
1430
  return "translateY(4px)";
1276
1431
  case "bottom":
@@ -1281,10 +1436,14 @@ var Tooltip = ({
1281
1436
  return "translateX(-4px)";
1282
1437
  }
1283
1438
  })();
1284
- const style = useSpringPresence({ visible: open, from: fromTransform });
1439
+ const style = useSpringPresence({
1440
+ visible: open,
1441
+ from: fromTransform,
1442
+ onExitComplete: () => setShouldRender(false)
1443
+ });
1285
1444
  const child = children;
1286
1445
  const childProps = child.props;
1287
- const trigger = React15.cloneElement(child, {
1446
+ const trigger = React16.cloneElement(child, {
1288
1447
  onMouseEnter: (e) => {
1289
1448
  childProps.onMouseEnter?.(e);
1290
1449
  show();
@@ -1305,25 +1464,29 @@ var Tooltip = ({
1305
1464
  "aria-describedby": open ? [childProps["aria-describedby"], tooltipId].filter(Boolean).join(" ") : childProps["aria-describedby"]
1306
1465
  });
1307
1466
  if (disabled) return children;
1308
- return /* @__PURE__ */ jsxs("span", { className: "tooltip_wrapper", children: [
1467
+ return /* @__PURE__ */ jsxs("span", { className: "tooltip_wrapper", ref: wrapperRef, children: [
1309
1468
  trigger,
1310
- open && /* @__PURE__ */ jsx(
1311
- "span",
1312
- {
1313
- className: cn("tooltip_position", `tooltip_placement_${placement}`),
1314
- onMouseEnter: cancelHide,
1315
- onMouseLeave: hide,
1316
- children: /* @__PURE__ */ jsx(
1317
- animated.span,
1318
- {
1319
- id: tooltipId,
1320
- role: "tooltip",
1321
- style,
1322
- className: cn("tooltip", `tooltip_placement_${placement}`),
1323
- children: content
1324
- }
1325
- )
1326
- }
1469
+ shouldRender && typeof document !== "undefined" && createPortal(
1470
+ /* @__PURE__ */ jsx(
1471
+ "span",
1472
+ {
1473
+ ref: positionRef,
1474
+ className: "tooltip_position",
1475
+ style: {
1476
+ position: "fixed",
1477
+ left: pos.x,
1478
+ top: pos.y,
1479
+ // 최초 측정 전(ready=false)에는 maxWidth(=0)를 걸지 않는다 - 걸면 자연 폭 대신
1480
+ // 0px 로 측정돼 첫 프레임 좌표가 어긋난다. ready 후에만 상한 적용.
1481
+ maxWidth: pos.ready ? pos.maxWidth : void 0,
1482
+ visibility: pos.ready ? void 0 : "hidden"
1483
+ },
1484
+ onMouseEnter: cancelHide,
1485
+ onMouseLeave: hide,
1486
+ children: /* @__PURE__ */ jsx(animated.span, { id: tooltipId, role: "tooltip", style, className: "tooltip", children: content })
1487
+ }
1488
+ ),
1489
+ document.body
1327
1490
  )
1328
1491
  ] });
1329
1492
  };
@@ -2251,12 +2414,12 @@ var Checkbox = ({
2251
2414
  ref,
2252
2415
  ...props
2253
2416
  }) => {
2254
- const inputRef = React15.useRef(null);
2255
- React15.useImperativeHandle(
2417
+ const inputRef = React16.useRef(null);
2418
+ React16.useImperativeHandle(
2256
2419
  ref,
2257
2420
  () => inputRef.current
2258
2421
  );
2259
- React15.useEffect(() => {
2422
+ React16.useEffect(() => {
2260
2423
  if (!inputRef.current) return;
2261
2424
  inputRef.current.indeterminate = Boolean(indeterminate);
2262
2425
  }, [indeterminate]);
@@ -2314,8 +2477,8 @@ var Table = ({
2314
2477
  const isEmpty = !isLoading && data.length === 0;
2315
2478
  const getRowKey = (item, index) => rowKey?.(item) ?? String(index);
2316
2479
  const allRowKeys = selectable ? data.map((item, index) => getRowKey(item, index)) : [];
2317
- const rowClickHintId = React15.useId();
2318
- const selectedSet = React15.useMemo(() => new Set(selectedKeys ?? []), [selectedKeys]);
2480
+ const rowClickHintId = React16.useId();
2481
+ const selectedSet = React16.useMemo(() => new Set(selectedKeys ?? []), [selectedKeys]);
2319
2482
  const selectedCount = allRowKeys.filter((key) => selectedSet.has(key)).length;
2320
2483
  const isAllSelected = allRowKeys.length > 0 && selectedCount === allRowKeys.length;
2321
2484
  const isSomeSelected = selectedCount > 0 && !isAllSelected;
@@ -2538,9 +2701,9 @@ var AlertModal = ({
2538
2701
  onClose
2539
2702
  }) => {
2540
2703
  const dismiss = onCancel ?? onClose;
2541
- const panelRef = React15.useRef(null);
2542
- const titleId = React15.useId();
2543
- const messageId = React15.useId();
2704
+ const panelRef = React16.useRef(null);
2705
+ const titleId = React16.useId();
2706
+ const messageId = React16.useId();
2544
2707
  const [shouldRender, setShouldRender] = useState(isOpen);
2545
2708
  useFocusTrap(panelRef, isOpen);
2546
2709
  useOverlayEscape(isOpen, () => dismiss());
@@ -2560,7 +2723,7 @@ var AlertModal = ({
2560
2723
  immediate: reduced,
2561
2724
  config: { tension: 280, friction: 28, clamp: !isOpen }
2562
2725
  });
2563
- React15.useEffect(() => {
2726
+ React16.useEffect(() => {
2564
2727
  if (!shouldRender) return;
2565
2728
  const body = document.body;
2566
2729
  const openModals = parseInt(body.dataset.openModals || "0", 10);
@@ -2687,7 +2850,7 @@ var Spinner = ({ size = 24, ariaLabel = "Loading" }) => {
2687
2850
  }
2688
2851
  );
2689
2852
  };
2690
- var ToastContext = React15.createContext(null);
2853
+ var ToastContext = React16.createContext(null);
2691
2854
  var VARIANT_ICONS = {
2692
2855
  success: /* @__PURE__ */ jsx(CheckCircle2, { size: iconSize.md }),
2693
2856
  error: /* @__PURE__ */ jsx(XCircle, { size: iconSize.md }),
@@ -2696,9 +2859,9 @@ var VARIANT_ICONS = {
2696
2859
  default: /* @__PURE__ */ jsx(Bell, { size: iconSize.md })
2697
2860
  };
2698
2861
  var ToastItemComponent = ({ item, onRemove, closeAriaLabel }) => {
2699
- const [visible, setVisible] = React15.useState(true);
2700
- const closingRef = React15.useRef(false);
2701
- const rootRef = React15.useRef(null);
2862
+ const [visible, setVisible] = React16.useState(true);
2863
+ const closingRef = React16.useRef(false);
2864
+ const rootRef = React16.useRef(null);
2702
2865
  const style = useSpringPresence({
2703
2866
  visible,
2704
2867
  from: "translateX(20px)",
@@ -2718,7 +2881,7 @@ var ToastItemComponent = ({ item, onRemove, closeAriaLabel }) => {
2718
2881
  onRemove(item.id);
2719
2882
  }
2720
2883
  });
2721
- const close = React15.useCallback(() => {
2884
+ const close = React16.useCallback(() => {
2722
2885
  if (closingRef.current) return;
2723
2886
  closingRef.current = true;
2724
2887
  setVisible(false);
@@ -2752,19 +2915,19 @@ var ToastProvider = ({
2752
2915
  maxCount = 5,
2753
2916
  closeAriaLabel = "Close"
2754
2917
  }) => {
2755
- const [toasts, setToasts] = React15.useState([]);
2918
+ const [toasts, setToasts] = React16.useState([]);
2756
2919
  const isMounted = useIsMounted();
2757
- const addToast = React15.useCallback(
2920
+ const addToast = React16.useCallback(
2758
2921
  (message, variant, duration = 3e3) => {
2759
2922
  const id = crypto.randomUUID();
2760
2923
  setToasts((prev) => [{ id, message, variant, duration }, ...prev].slice(0, maxCount));
2761
2924
  },
2762
2925
  [maxCount]
2763
2926
  );
2764
- const removeToast = React15.useCallback((id) => {
2927
+ const removeToast = React16.useCallback((id) => {
2765
2928
  setToasts((prev) => prev.filter((t) => t.id !== id));
2766
2929
  }, []);
2767
- const contextValue = React15.useMemo(() => ({ addToast }), [addToast]);
2930
+ const contextValue = React16.useMemo(() => ({ addToast }), [addToast]);
2768
2931
  return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: contextValue, children: [
2769
2932
  children,
2770
2933
  isMounted && createPortal(
@@ -3198,9 +3361,9 @@ var DatePicker = ({
3198
3361
  minDateSrFormat = "Minimum date: {date}",
3199
3362
  selectableRangeUntilTodaySrText = "Selectable up to today"
3200
3363
  }) => {
3201
- const groupId = React15.useId();
3202
- const constraintId = React15.useId();
3203
- const { todayYear, todayMonth, todayDay } = React15.useMemo(() => {
3364
+ const groupId = React16.useId();
3365
+ const constraintId = React16.useId();
3366
+ const { todayYear, todayMonth, todayDay } = React16.useMemo(() => {
3204
3367
  const now = /* @__PURE__ */ new Date();
3205
3368
  return {
3206
3369
  todayYear: now.getFullYear(),
@@ -3209,7 +3372,7 @@ var DatePicker = ({
3209
3372
  };
3210
3373
  }, []);
3211
3374
  const endYear = endYearProp ?? todayYear + 10;
3212
- const parsed = React15.useMemo(() => {
3375
+ const parsed = React16.useMemo(() => {
3213
3376
  if (!value) return { year: 0, month: 0, day: 0 };
3214
3377
  const [y, m, d] = value.split("-").map(Number);
3215
3378
  return {
@@ -3218,7 +3381,7 @@ var DatePicker = ({
3218
3381
  day: d || 0
3219
3382
  };
3220
3383
  }, [value]);
3221
- const min = React15.useMemo(() => {
3384
+ const min = React16.useMemo(() => {
3222
3385
  if (!minDate) return { year: 0, month: 0, day: 0 };
3223
3386
  const [y, m, d] = minDate.split("-").map(Number);
3224
3387
  return {
@@ -3238,7 +3401,7 @@ var DatePicker = ({
3238
3401
  min.year > 0 && min.month > 0 && year === min.year && month === min.month ? min.day : 1
3239
3402
  )
3240
3403
  );
3241
- const maxDay = React15.useMemo(() => {
3404
+ const maxDay = React16.useMemo(() => {
3242
3405
  if (!year || !month) return 31;
3243
3406
  const daysInMonth = getDaysInMonth(year, month);
3244
3407
  if (selectableRange === "until-today" && year === todayYear && month === todayMonth) {
@@ -3246,28 +3409,28 @@ var DatePicker = ({
3246
3409
  }
3247
3410
  return daysInMonth;
3248
3411
  }, [year, month, selectableRange, todayYear, todayMonth, todayDay]);
3249
- const yearOptions = React15.useMemo(
3412
+ const yearOptions = React16.useMemo(
3250
3413
  () => range(startYear, maxYear).map((y) => ({
3251
3414
  value: String(y),
3252
3415
  label: String(y)
3253
3416
  })),
3254
3417
  [startYear, maxYear]
3255
3418
  );
3256
- const monthOptions = React15.useMemo(
3419
+ const monthOptions = React16.useMemo(
3257
3420
  () => range(minMonth, Math.max(minMonth, maxMonth)).map((m) => ({
3258
3421
  value: String(m),
3259
3422
  label: pad(m)
3260
3423
  })),
3261
3424
  [minMonth, maxMonth]
3262
3425
  );
3263
- const dayOptions = React15.useMemo(
3426
+ const dayOptions = React16.useMemo(
3264
3427
  () => range(minDay, Math.max(minDay, maxDay)).map((d) => ({
3265
3428
  value: String(d),
3266
3429
  label: pad(d)
3267
3430
  })),
3268
3431
  [minDay, maxDay]
3269
3432
  );
3270
- const emit = React15.useCallback(
3433
+ const emit = React16.useCallback(
3271
3434
  (yy, mm, dd) => {
3272
3435
  const cb = onValueChange ?? onChange;
3273
3436
  if (mode === "year-month") {
@@ -3279,7 +3442,7 @@ var DatePicker = ({
3279
3442
  },
3280
3443
  [mode, onValueChange, onChange]
3281
3444
  );
3282
- const handleYearChange = React15.useCallback(
3445
+ const handleYearChange = React16.useCallback(
3283
3446
  (raw) => {
3284
3447
  if (!raw) return;
3285
3448
  const newYear = Number(raw);
@@ -3296,14 +3459,14 @@ var DatePicker = ({
3296
3459
  },
3297
3460
  [month, day, min.year, min.month, selectableRange, todayYear, todayMonth, emit]
3298
3461
  );
3299
- const handleMonthChange = React15.useCallback(
3462
+ const handleMonthChange = React16.useCallback(
3300
3463
  (raw) => {
3301
3464
  if (!raw || !year) return;
3302
3465
  emit(year, Number(raw), day || void 0);
3303
3466
  },
3304
3467
  [year, day, emit]
3305
3468
  );
3306
- const handleDayChange = React15.useCallback(
3469
+ const handleDayChange = React16.useCallback(
3307
3470
  (raw) => {
3308
3471
  if (!raw || !year || !month) return;
3309
3472
  emit(year, month, Number(raw));
@@ -3387,11 +3550,11 @@ var FileInput = ({
3387
3550
  onChange,
3388
3551
  ...props
3389
3552
  }) => {
3390
- const inputId = React15.useId();
3391
- const helperId = React15.useId();
3392
- const inputRef = React15.useRef(null);
3393
- const [previewUrls, setPreviewUrls] = React15.useState([]);
3394
- const previewUrlsRef = React15.useRef([]);
3553
+ const inputId = React16.useId();
3554
+ const helperId = React16.useId();
3555
+ const inputRef = React16.useRef(null);
3556
+ const [previewUrls, setPreviewUrls] = React16.useState([]);
3557
+ const previewUrlsRef = React16.useRef([]);
3395
3558
  const isPreviewVariant = variant === "preview";
3396
3559
  const showPreview = isPreviewVariant || preview;
3397
3560
  const handleChange = (e) => {
@@ -3432,7 +3595,7 @@ var FileInput = ({
3432
3595
  }
3433
3596
  onFiles?.(null);
3434
3597
  };
3435
- React15.useEffect(() => {
3598
+ React16.useEffect(() => {
3436
3599
  return () => {
3437
3600
  for (const url of previewUrlsRef.current) {
3438
3601
  URL.revokeObjectURL(url);
@@ -3841,12 +4004,12 @@ var OtpInput = ({
3841
4004
  ariaLabel = "OTP \uC785\uB825",
3842
4005
  className
3843
4006
  }) => {
3844
- const inputsRef = React15.useRef([]);
3845
- const isTypingRef = React15.useRef(false);
3846
- React15.useEffect(() => {
4007
+ const inputsRef = React16.useRef([]);
4008
+ const isTypingRef = React16.useRef(false);
4009
+ React16.useEffect(() => {
3847
4010
  if (autoFocus) inputsRef.current[0]?.focus();
3848
4011
  }, [autoFocus]);
3849
- const digits = React15.useMemo(() => {
4012
+ const digits = React16.useMemo(() => {
3850
4013
  const chars = value.split("").slice(0, length);
3851
4014
  while (chars.length < length) chars.push("");
3852
4015
  return chars;
@@ -3923,7 +4086,7 @@ var OtpInput = ({
3923
4086
  focusInput(nextIndex);
3924
4087
  };
3925
4088
  const rootClassName = cn("otp_input", className);
3926
- const supportingId = React15.useId();
4089
+ const supportingId = React16.useId();
3927
4090
  return (
3928
4091
  // biome-ignore lint/a11y/useSemanticElements: <fieldset> would force border/legend styles; role=group is the WAI-ARIA equivalent for OTP grouping
3929
4092
  /* @__PURE__ */ jsxs("div", { className: rootClassName, role: "group", "aria-label": ariaLabel, children: [
@@ -3967,9 +4130,9 @@ var OtpInput = ({
3967
4130
  );
3968
4131
  };
3969
4132
  OtpInput.displayName = "OtpInput";
3970
- var RadioGroupContext = React15.createContext(null);
4133
+ var RadioGroupContext = React16.createContext(null);
3971
4134
  function useRadioGroupContext() {
3972
- return React15.useContext(RadioGroupContext);
4135
+ return React16.useContext(RadioGroupContext);
3973
4136
  }
3974
4137
  var RadioGroup = ({
3975
4138
  value: controlledValue,
@@ -3987,21 +4150,21 @@ var RadioGroup = ({
3987
4150
  ...props
3988
4151
  }) => {
3989
4152
  const isControlled = controlledValue !== void 0;
3990
- const [internalValue, setInternalValue] = React15.useState(defaultValue);
4153
+ const [internalValue, setInternalValue] = React16.useState(defaultValue);
3991
4154
  const value = isControlled ? controlledValue : internalValue;
3992
- const generatedName = React15.useId();
4155
+ const generatedName = React16.useId();
3993
4156
  const name = nameProp ?? generatedName;
3994
- const idPrefix = React15.useId();
4157
+ const idPrefix = React16.useId();
3995
4158
  const labelId = label ? `${idPrefix}-label` : void 0;
3996
4159
  const helperId = supportingText ? `${idPrefix}-help` : void 0;
3997
- const onChange = React15.useCallback(
4160
+ const onChange = React16.useCallback(
3998
4161
  (next) => {
3999
4162
  if (!isControlled) setInternalValue(next);
4000
4163
  onValueChange?.(next);
4001
4164
  },
4002
4165
  [isControlled, onValueChange]
4003
4166
  );
4004
- const ctx = React15.useMemo(
4167
+ const ctx = React16.useMemo(
4005
4168
  () => ({ name, value, onChange, size, disabled }),
4006
4169
  [name, value, onChange, size, disabled]
4007
4170
  );
@@ -4331,7 +4494,7 @@ var Toggle = ({
4331
4494
  ...props
4332
4495
  }) => {
4333
4496
  const isControlled = checked !== void 0;
4334
- const [innerChecked, setInnerChecked] = React15.useState(!!defaultChecked);
4497
+ const [innerChecked, setInnerChecked] = React16.useState(!!defaultChecked);
4335
4498
  const isOn = isControlled ? !!checked : innerChecked;
4336
4499
  const handleToggle = (e) => {
4337
4500
  props.onClick?.(e);
@@ -4420,7 +4583,7 @@ var Pagination = ({
4420
4583
  const emit = onPageChange ?? onChange;
4421
4584
  const prevDisabled = page <= 1;
4422
4585
  const nextDisabled = page >= totalPages;
4423
- const items = React15.useMemo(() => getPaginationItems(page, totalPages), [page, totalPages]);
4586
+ const items = React16.useMemo(() => getPaginationItems(page, totalPages), [page, totalPages]);
4424
4587
  return /* @__PURE__ */ jsxs("nav", { className: "pagination", "aria-label": "Pagination", children: [
4425
4588
  /* @__PURE__ */ jsx(
4426
4589
  "button",
@@ -4485,9 +4648,9 @@ var Drawer = ({
4485
4648
  className,
4486
4649
  ...props
4487
4650
  }) => {
4488
- const panelRef = React15.useRef(null);
4489
- const titleId = React15.useId();
4490
- const [shouldRender, setShouldRender] = React15.useState(open);
4651
+ const panelRef = React16.useRef(null);
4652
+ const titleId = React16.useId();
4653
+ const [shouldRender, setShouldRender] = React16.useState(open);
4491
4654
  const reduced = useReducedMotion();
4492
4655
  const isMounted = useIsMounted();
4493
4656
  useFocusTrap(panelRef, open && isMounted);
@@ -4506,7 +4669,7 @@ var Drawer = ({
4506
4669
  immediate: reduced,
4507
4670
  config: { tension: 280, friction: 28, clamp: !open }
4508
4671
  });
4509
- React15.useEffect(() => {
4672
+ React16.useEffect(() => {
4510
4673
  if (!open) return;
4511
4674
  const body = document.body;
4512
4675
  const openModals = parseInt(body.dataset.openModals || "0", 10);
@@ -4594,9 +4757,9 @@ var Modal = ({
4594
4757
  ariaLabel,
4595
4758
  ...props
4596
4759
  }) => {
4597
- const panelRef = React15.useRef(null);
4598
- const titleId = React15.useId();
4599
- const [shouldRender, setShouldRender] = React15.useState(open);
4760
+ const panelRef = React16.useRef(null);
4761
+ const titleId = React16.useId();
4762
+ const [shouldRender, setShouldRender] = React16.useState(open);
4600
4763
  const isMounted = useIsMounted();
4601
4764
  useFocusTrap(panelRef, open && isMounted);
4602
4765
  useOverlayEscape(open && isMounted, () => onClose?.());
@@ -4616,7 +4779,7 @@ var Modal = ({
4616
4779
  immediate: reduced,
4617
4780
  config: { tension: 280, friction: 28, clamp: !open }
4618
4781
  });
4619
- React15.useEffect(() => {
4782
+ React16.useEffect(() => {
4620
4783
  if (!open) return;
4621
4784
  const body = document.body;
4622
4785
  const openModals = parseInt(body.dataset.openModals || "0", 10);
@@ -4686,9 +4849,9 @@ var Modal = ({
4686
4849
  document.body
4687
4850
  );
4688
4851
  };
4689
- var ThemeContext = React15.createContext(null);
4852
+ var ThemeContext = React16.createContext(null);
4690
4853
  var useTheme = () => {
4691
- const ctx = React15.useContext(ThemeContext);
4854
+ const ctx = React16.useContext(ThemeContext);
4692
4855
  if (!ctx) {
4693
4856
  throw new Error(
4694
4857
  '[Bigtablet DS] useTheme\uB294 <ThemeProvider> \uC548\uC5D0\uC11C\uB9CC \uC0AC\uC6A9 \uAC00\uB2A5\uD569\uB2C8\uB2E4.\n\n\uC571 \uCD5C\uC0C1\uB2E8\uC5D0 <ThemeProvider>\uB85C \uAC10\uC2F8\uC8FC\uC138\uC694:\n <ThemeProvider mode="system">\n <YourApp />\n </ThemeProvider>'
@@ -4712,15 +4875,15 @@ var ThemeProvider = ({
4712
4875
  targetSelector,
4713
4876
  children
4714
4877
  }) => {
4715
- const [mode, setModeState] = React15.useState(defaultMode);
4716
- const [systemDark, setSystemDark] = React15.useState(false);
4717
- React15.useEffect(() => {
4878
+ const [mode, setModeState] = React16.useState(defaultMode);
4879
+ const [systemDark, setSystemDark] = React16.useState(false);
4880
+ React16.useEffect(() => {
4718
4881
  setModeState(readStored(storageKey) ?? defaultMode);
4719
4882
  if (isClient) {
4720
4883
  setSystemDark(window.matchMedia("(prefers-color-scheme: dark)").matches);
4721
4884
  }
4722
4885
  }, [storageKey, defaultMode]);
4723
- React15.useEffect(() => {
4886
+ React16.useEffect(() => {
4724
4887
  if (!isClient) return;
4725
4888
  const mq = window.matchMedia("(prefers-color-scheme: dark)");
4726
4889
  const handler = (e) => setSystemDark(e.matches);
@@ -4728,7 +4891,7 @@ var ThemeProvider = ({
4728
4891
  return () => mq.removeEventListener("change", handler);
4729
4892
  }, []);
4730
4893
  const resolved = mode === "system" ? systemDark ? "dark" : "light" : mode;
4731
- React15.useEffect(() => {
4894
+ React16.useEffect(() => {
4732
4895
  if (!isClient) return;
4733
4896
  const target = targetSelector ? document.querySelector(targetSelector) : document.documentElement;
4734
4897
  if (!target) return;
@@ -4738,7 +4901,7 @@ var ThemeProvider = ({
4738
4901
  target.setAttribute("data-theme", mode);
4739
4902
  }
4740
4903
  }, [mode, targetSelector]);
4741
- const setMode = React15.useCallback(
4904
+ const setMode = React16.useCallback(
4742
4905
  (next) => {
4743
4906
  setModeState(next);
4744
4907
  if (storageKey && isClient) {
@@ -4750,7 +4913,7 @@ var ThemeProvider = ({
4750
4913
  },
4751
4914
  [storageKey]
4752
4915
  );
4753
- const value = React15.useMemo(
4916
+ const value = React16.useMemo(
4754
4917
  () => ({ mode, resolved, setMode }),
4755
4918
  [mode, resolved, setMode]
4756
4919
  );
@@ -4863,4 +5026,4 @@ var Stack = ({
4863
5026
  );
4864
5027
  };
4865
5028
 
4866
- export { Accordion, AlertProvider, Avatar, Badge, BottomNav, BottomNavItem, BottomNavSpacer, Breadcrumb, Button, Card, Checkbox, Chip, Container, DatePicker, Divider, Drawer, Dropdown, EmptyState, ErrorState, FileInput, Grid, Hero, Icon, IconButton, ImageCropper, LinearProgress, ListItem, MediaCard, Menu, Modal, NavBar, NavLink, OtpInput, Pagination, Popover, Radio, RadioGroup, Section, Sidebar, SidebarItem, SidebarSection, Skeleton, Spinner, Stack, Tab, TabList, TabPanel, Table, Tabs, TextField, Textarea, ThemeProvider, ToastProvider, Toggle, Tooltip, TopLoading, a11y, baseBorderWidth, baseColors, baseTypography, borderWidth, breakpoints, cn, colors, elevation, iconSize, motion, opacity, radius, skeleton, spacing, typography, useAlert, useFocusTrap, useReducedMotion, useSpringHover, useSpringPresence, useTheme, useToast, zIndex };
5029
+ export { Accordion, AlertProvider, Avatar, Badge, BottomNav, BottomNavItem, BottomNavSpacer, Breadcrumb, Button, Card, Checkbox, Chip, Container, DatePicker, Divider, Drawer, Dropdown, EmptyState, ErrorState, FileInput, Grid, Hero, Icon, IconButton, ImageCropper, LinearProgress, ListItem, MediaCard, Menu, Modal, NavBar, NavLink, OtpInput, Pagination, Popover, Radio, RadioGroup, Section, Sidebar, SidebarItem, SidebarSection, Skeleton, Spinner, Stack, Tab, TabList, TabPanel, Table, Tabs, TextField, Textarea, ThemeProvider, ToastProvider, Toggle, Tooltip, TopLoading, a11y, baseBorderWidth, baseColors, baseTypography, borderWidth, breakpoints, cn, colors, elevation, iconSize, motion, opacity, radius, skeleton, spacing, typography, useAlert, useFocusTrap, useRadioGroupContext, useReducedMotion, useSpringHover, useSpringPresence, useTheme, useToast, zIndex };