@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/LICENSE +53 -0
- package/README.md +12 -9
- package/dist/index.css +46 -45
- package/dist/index.d.ts +72 -7
- package/dist/index.js +341 -178
- package/dist/styles/colors/_index.scss +30 -0
- package/dist/styles/layout/_index.scss +17 -3
- package/dist/styles/motion/_index.scss +14 -1
- package/dist/vanilla/bigtablet.min.css +7 -1
- package/dist/vanilla/bigtablet.min.js +21 -21
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import './index.css';
|
|
3
|
-
import * as
|
|
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 =
|
|
62
|
-
|
|
61
|
+
const handlerRef = React16.useRef(onEscape);
|
|
62
|
+
React16.useEffect(() => {
|
|
63
63
|
handlerRef.current = onEscape;
|
|
64
64
|
});
|
|
65
|
-
|
|
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 =
|
|
80
|
-
|
|
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] =
|
|
130
|
-
|
|
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
|
|
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] =
|
|
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] =
|
|
356
|
+
const [internalKeys, setInternalKeys] = React16.useState(defaultOpenKeys);
|
|
236
357
|
const open = isControlled ? controlledKeys ?? [] : internalKeys;
|
|
237
|
-
const idPrefix =
|
|
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] =
|
|
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] =
|
|
523
|
-
const wrapperRef =
|
|
524
|
-
const itemRefs =
|
|
525
|
-
const menuId =
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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:
|
|
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] =
|
|
1002
|
+
const [internalCollapsed, setInternalCollapsed] = React16.useState(defaultCollapsed);
|
|
880
1003
|
const collapsed = isControlled ? collapsedProp : internalCollapsed;
|
|
881
|
-
const toggle =
|
|
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 =
|
|
1077
|
+
var TabsContext = React16.createContext(null);
|
|
955
1078
|
function useTabsContext() {
|
|
956
|
-
const ctx =
|
|
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] =
|
|
1098
|
+
const [internalValue, setInternalValue] = React16.useState(defaultValue);
|
|
976
1099
|
const value = isControlled ? controlledValue : internalValue;
|
|
977
|
-
const setValue =
|
|
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 =
|
|
985
|
-
const [firstTabValue, setFirstTabValue] =
|
|
986
|
-
const registerTab =
|
|
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 =
|
|
997
|
-
const ctx =
|
|
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 =
|
|
1006
|
-
const [indicator, setIndicator] =
|
|
1007
|
-
const [hasMounted, setHasMounted] =
|
|
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
|
-
|
|
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
|
|
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] =
|
|
1276
|
+
const [internalOpen, setInternalOpen] = React16.useState(defaultOpen);
|
|
1161
1277
|
const open = isControlled ? openProp : internalOpen;
|
|
1162
|
-
const [shouldRender, setShouldRender] =
|
|
1278
|
+
const [shouldRender, setShouldRender] = React16.useState(open ?? false);
|
|
1163
1279
|
if (open && !shouldRender) setShouldRender(true);
|
|
1164
|
-
const wrapperRef =
|
|
1165
|
-
const
|
|
1166
|
-
const
|
|
1167
|
-
const popoverId =
|
|
1168
|
-
const setOpen =
|
|
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({
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
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
|
-
|
|
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 =
|
|
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 &&
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
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] =
|
|
1248
|
-
const
|
|
1249
|
-
|
|
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 =
|
|
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 =
|
|
1402
|
+
const hideNow = React16.useCallback(() => {
|
|
1256
1403
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
1257
1404
|
setOpen(false);
|
|
1258
1405
|
}, []);
|
|
1259
|
-
const hide =
|
|
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 =
|
|
1410
|
+
const cancelHide = React16.useCallback(() => {
|
|
1264
1411
|
if (timerRef.current) clearTimeout(timerRef.current);
|
|
1265
1412
|
}, []);
|
|
1266
|
-
|
|
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({
|
|
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 =
|
|
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
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
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 =
|
|
2255
|
-
|
|
2417
|
+
const inputRef = React16.useRef(null);
|
|
2418
|
+
React16.useImperativeHandle(
|
|
2256
2419
|
ref,
|
|
2257
2420
|
() => inputRef.current
|
|
2258
2421
|
);
|
|
2259
|
-
|
|
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 =
|
|
2318
|
-
const selectedSet =
|
|
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 =
|
|
2542
|
-
const titleId =
|
|
2543
|
-
const messageId =
|
|
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
|
-
|
|
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 =
|
|
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] =
|
|
2700
|
-
const closingRef =
|
|
2701
|
-
const rootRef =
|
|
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 =
|
|
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] =
|
|
2918
|
+
const [toasts, setToasts] = React16.useState([]);
|
|
2756
2919
|
const isMounted = useIsMounted();
|
|
2757
|
-
const addToast =
|
|
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 =
|
|
2927
|
+
const removeToast = React16.useCallback((id) => {
|
|
2765
2928
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
2766
2929
|
}, []);
|
|
2767
|
-
const contextValue =
|
|
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 =
|
|
3202
|
-
const constraintId =
|
|
3203
|
-
const { todayYear, todayMonth, todayDay } =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
3391
|
-
const helperId =
|
|
3392
|
-
const inputRef =
|
|
3393
|
-
const [previewUrls, setPreviewUrls] =
|
|
3394
|
-
const previewUrlsRef =
|
|
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
|
-
|
|
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 =
|
|
3845
|
-
const isTypingRef =
|
|
3846
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
4133
|
+
var RadioGroupContext = React16.createContext(null);
|
|
3971
4134
|
function useRadioGroupContext() {
|
|
3972
|
-
return
|
|
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] =
|
|
4153
|
+
const [internalValue, setInternalValue] = React16.useState(defaultValue);
|
|
3991
4154
|
const value = isControlled ? controlledValue : internalValue;
|
|
3992
|
-
const generatedName =
|
|
4155
|
+
const generatedName = React16.useId();
|
|
3993
4156
|
const name = nameProp ?? generatedName;
|
|
3994
|
-
const idPrefix =
|
|
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 =
|
|
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 =
|
|
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] =
|
|
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 =
|
|
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 =
|
|
4489
|
-
const titleId =
|
|
4490
|
-
const [shouldRender, setShouldRender] =
|
|
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
|
-
|
|
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 =
|
|
4598
|
-
const titleId =
|
|
4599
|
-
const [shouldRender, setShouldRender] =
|
|
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
|
-
|
|
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 =
|
|
4852
|
+
var ThemeContext = React16.createContext(null);
|
|
4690
4853
|
var useTheme = () => {
|
|
4691
|
-
const ctx =
|
|
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] =
|
|
4716
|
-
const [systemDark, setSystemDark] =
|
|
4717
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 };
|