@bigtablet/design-system 3.2.2 → 3.3.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.css +8 -8
- package/dist/index.d.ts +132 -77
- package/dist/index.js +226 -72
- package/package.json +19 -15
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import './index.css';
|
|
3
3
|
import * as React20 from 'react';
|
|
4
|
-
import { createContext, useRef, useState,
|
|
4
|
+
import { createContext, useRef, useState, useId, useEffect, useContext, useCallback, useMemo, Fragment, useLayoutEffect } from 'react';
|
|
5
5
|
import { useSpring, animated } from '@react-spring/web';
|
|
6
6
|
import { ChevronDown, Globe, ChevronRight, ChevronLeft, Check, Image, X, TriangleAlert, XCircle, AlertTriangle, CheckCircle2, Info, Bell } from 'lucide-react';
|
|
7
7
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
@@ -172,6 +172,7 @@ var Accordion = ({
|
|
|
172
172
|
multiple = false,
|
|
173
173
|
defaultOpenKeys = [],
|
|
174
174
|
openKeys: controlledKeys,
|
|
175
|
+
onValueChange,
|
|
175
176
|
onChange,
|
|
176
177
|
className,
|
|
177
178
|
...props
|
|
@@ -183,7 +184,7 @@ var Accordion = ({
|
|
|
183
184
|
const isOpen = open.includes(key);
|
|
184
185
|
const next = isOpen ? open.filter((k) => k !== key) : multiple ? [...open, key] : [key];
|
|
185
186
|
if (!isControlled) setInternalKeys(next);
|
|
186
|
-
onChange?.(next);
|
|
187
|
+
(onValueChange ?? onChange)?.(next);
|
|
187
188
|
};
|
|
188
189
|
return /* @__PURE__ */ jsx("div", { className: cn("accordion", className), ...props, children: items.map((item) => {
|
|
189
190
|
const isOpen = open.includes(item.key);
|
|
@@ -220,6 +221,7 @@ var Accordion = ({
|
|
|
220
221
|
role: "region",
|
|
221
222
|
"aria-labelledby": headerId,
|
|
222
223
|
"aria-hidden": !isOpen,
|
|
224
|
+
inert: !isOpen,
|
|
223
225
|
className: cn("accordion_panel", isOpen && "accordion_panel_open"),
|
|
224
226
|
children: /* @__PURE__ */ jsx("div", { className: "accordion_panel_wrap", children: /* @__PURE__ */ jsx("div", { className: "accordion_content", children: item.content }) })
|
|
225
227
|
}
|
|
@@ -463,6 +465,7 @@ var ErrorState = ({
|
|
|
463
465
|
var Menu = ({ items, trigger, align = "start" }) => {
|
|
464
466
|
const [open, setOpen] = React20.useState(false);
|
|
465
467
|
const wrapperRef = React20.useRef(null);
|
|
468
|
+
const itemRefs = React20.useRef([]);
|
|
466
469
|
const menuId = React20.useId();
|
|
467
470
|
const style = useSpringPresence({ visible: open, from: "translateY(-4px)" });
|
|
468
471
|
React20.useEffect(() => {
|
|
@@ -480,6 +483,52 @@ var Menu = ({ items, trigger, align = "start" }) => {
|
|
|
480
483
|
document.removeEventListener("keydown", handleEsc);
|
|
481
484
|
};
|
|
482
485
|
}, [open]);
|
|
486
|
+
React20.useEffect(() => {
|
|
487
|
+
const active = document.activeElement;
|
|
488
|
+
if (!open || active && itemRefs.current.includes(active)) return;
|
|
489
|
+
const first = items.findIndex((it) => !it.disabled);
|
|
490
|
+
if (first >= 0) itemRefs.current[first]?.focus();
|
|
491
|
+
}, [open, items]);
|
|
492
|
+
const moveFocus = (dir) => {
|
|
493
|
+
const enabled = items.flatMap((it, i) => it.disabled ? [] : [i]);
|
|
494
|
+
if (enabled.length === 0) return;
|
|
495
|
+
if (dir === "first") return void itemRefs.current[enabled[0]]?.focus();
|
|
496
|
+
if (dir === "last") return void itemRefs.current[enabled[enabled.length - 1]]?.focus();
|
|
497
|
+
const pos = enabled.findIndex((i) => itemRefs.current[i] === document.activeElement);
|
|
498
|
+
const next = pos < 0 ? dir === 1 ? 0 : enabled.length - 1 : (pos + dir + enabled.length) % enabled.length;
|
|
499
|
+
itemRefs.current[enabled[next]]?.focus();
|
|
500
|
+
};
|
|
501
|
+
const handleMenuKeyDown = (e) => {
|
|
502
|
+
if (["ArrowDown", "ArrowUp", "Home", "End", "Escape"].includes(e.key)) {
|
|
503
|
+
e.stopPropagation();
|
|
504
|
+
}
|
|
505
|
+
switch (e.key) {
|
|
506
|
+
case "ArrowDown":
|
|
507
|
+
e.preventDefault();
|
|
508
|
+
moveFocus(1);
|
|
509
|
+
break;
|
|
510
|
+
case "ArrowUp":
|
|
511
|
+
e.preventDefault();
|
|
512
|
+
moveFocus(-1);
|
|
513
|
+
break;
|
|
514
|
+
case "Home":
|
|
515
|
+
e.preventDefault();
|
|
516
|
+
moveFocus("first");
|
|
517
|
+
break;
|
|
518
|
+
case "End":
|
|
519
|
+
e.preventDefault();
|
|
520
|
+
moveFocus("last");
|
|
521
|
+
break;
|
|
522
|
+
case "Escape":
|
|
523
|
+
e.preventDefault();
|
|
524
|
+
setOpen(false);
|
|
525
|
+
wrapperRef.current?.querySelector("[aria-haspopup]")?.focus();
|
|
526
|
+
break;
|
|
527
|
+
case "Tab":
|
|
528
|
+
setOpen(false);
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
};
|
|
483
532
|
const triggerWithProps = React20.cloneElement(
|
|
484
533
|
trigger,
|
|
485
534
|
{
|
|
@@ -498,11 +547,16 @@ var Menu = ({ items, trigger, align = "start" }) => {
|
|
|
498
547
|
role: "menu",
|
|
499
548
|
style,
|
|
500
549
|
className: cn("menu", `menu_align_${align}`),
|
|
501
|
-
|
|
550
|
+
onKeyDown: handleMenuKeyDown,
|
|
551
|
+
children: items.map((item, index) => /* @__PURE__ */ jsxs(
|
|
502
552
|
"button",
|
|
503
553
|
{
|
|
554
|
+
ref: (el) => {
|
|
555
|
+
itemRefs.current[index] = el;
|
|
556
|
+
},
|
|
504
557
|
type: "button",
|
|
505
558
|
role: "menuitem",
|
|
559
|
+
tabIndex: -1,
|
|
506
560
|
disabled: item.disabled,
|
|
507
561
|
className: cn(
|
|
508
562
|
"menu_item",
|
|
@@ -543,7 +597,7 @@ var NavBar = ({
|
|
|
543
597
|
const linksRef = useRef(null);
|
|
544
598
|
const [indicator, setIndicator] = useState(null);
|
|
545
599
|
const [hasMounted, setHasMounted] = useState(false);
|
|
546
|
-
|
|
600
|
+
useSafeLayoutEffect(() => {
|
|
547
601
|
const links = linksRef.current;
|
|
548
602
|
if (!links) return;
|
|
549
603
|
const update = () => {
|
|
@@ -614,6 +668,7 @@ var NavBar = ({
|
|
|
614
668
|
var LocaleSwitcher = ({ locale }) => {
|
|
615
669
|
const [open, setOpen] = useState(false);
|
|
616
670
|
const wrapperRef = useRef(null);
|
|
671
|
+
const itemRefs = useRef([]);
|
|
617
672
|
const menuId = useId();
|
|
618
673
|
const currentOption = locale.options.find((o) => o.value === locale.current);
|
|
619
674
|
useEffect(() => {
|
|
@@ -631,8 +686,53 @@ var LocaleSwitcher = ({ locale }) => {
|
|
|
631
686
|
document.removeEventListener("keydown", escHandler);
|
|
632
687
|
};
|
|
633
688
|
}, [open]);
|
|
689
|
+
useEffect(() => {
|
|
690
|
+
const active = document.activeElement;
|
|
691
|
+
if (!open || active && itemRefs.current.includes(active)) return;
|
|
692
|
+
itemRefs.current[0]?.focus();
|
|
693
|
+
}, [open]);
|
|
694
|
+
const moveFocus = (dir) => {
|
|
695
|
+
const n = locale.options.length;
|
|
696
|
+
if (n === 0) return;
|
|
697
|
+
if (dir === "first") return void itemRefs.current[0]?.focus();
|
|
698
|
+
if (dir === "last") return void itemRefs.current[n - 1]?.focus();
|
|
699
|
+
const pos = itemRefs.current.indexOf(document.activeElement);
|
|
700
|
+
const next = pos < 0 ? dir === 1 ? 0 : n - 1 : (pos + dir + n) % n;
|
|
701
|
+
itemRefs.current[next]?.focus();
|
|
702
|
+
};
|
|
703
|
+
const handleMenuKeyDown = (e) => {
|
|
704
|
+
if (["ArrowDown", "ArrowUp", "Home", "End", "Escape"].includes(e.key)) {
|
|
705
|
+
e.stopPropagation();
|
|
706
|
+
}
|
|
707
|
+
switch (e.key) {
|
|
708
|
+
case "ArrowDown":
|
|
709
|
+
e.preventDefault();
|
|
710
|
+
moveFocus(1);
|
|
711
|
+
break;
|
|
712
|
+
case "ArrowUp":
|
|
713
|
+
e.preventDefault();
|
|
714
|
+
moveFocus(-1);
|
|
715
|
+
break;
|
|
716
|
+
case "Home":
|
|
717
|
+
e.preventDefault();
|
|
718
|
+
moveFocus("first");
|
|
719
|
+
break;
|
|
720
|
+
case "End":
|
|
721
|
+
e.preventDefault();
|
|
722
|
+
moveFocus("last");
|
|
723
|
+
break;
|
|
724
|
+
case "Escape":
|
|
725
|
+
e.preventDefault();
|
|
726
|
+
setOpen(false);
|
|
727
|
+
wrapperRef.current?.querySelector("[aria-haspopup]")?.focus();
|
|
728
|
+
break;
|
|
729
|
+
case "Tab":
|
|
730
|
+
setOpen(false);
|
|
731
|
+
break;
|
|
732
|
+
}
|
|
733
|
+
};
|
|
634
734
|
const handleSelect = (value) => {
|
|
635
|
-
locale.onChange(value);
|
|
735
|
+
(locale.onValueChange ?? locale.onChange)?.(value);
|
|
636
736
|
setOpen(false);
|
|
637
737
|
};
|
|
638
738
|
return /* @__PURE__ */ jsxs("div", { ref: wrapperRef, className: "nav_bar_locale", children: [
|
|
@@ -652,19 +752,32 @@ var LocaleSwitcher = ({ locale }) => {
|
|
|
652
752
|
]
|
|
653
753
|
}
|
|
654
754
|
),
|
|
655
|
-
open && /* @__PURE__ */ jsx(
|
|
656
|
-
"
|
|
755
|
+
open && /* @__PURE__ */ jsx(
|
|
756
|
+
"ul",
|
|
657
757
|
{
|
|
658
|
-
|
|
659
|
-
role: "
|
|
660
|
-
className:
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
758
|
+
id: menuId,
|
|
759
|
+
role: "menu",
|
|
760
|
+
className: "nav_bar_locale_menu",
|
|
761
|
+
onKeyDown: handleMenuKeyDown,
|
|
762
|
+
children: locale.options.map((opt, index) => /* @__PURE__ */ jsx("li", { role: "none", children: /* @__PURE__ */ jsx(
|
|
763
|
+
"button",
|
|
764
|
+
{
|
|
765
|
+
ref: (el) => {
|
|
766
|
+
itemRefs.current[index] = el;
|
|
767
|
+
},
|
|
768
|
+
type: "button",
|
|
769
|
+
role: "menuitem",
|
|
770
|
+
tabIndex: -1,
|
|
771
|
+
className: cn(
|
|
772
|
+
"nav_bar_locale_item",
|
|
773
|
+
opt.value === locale.current && "nav_bar_locale_item_active"
|
|
774
|
+
),
|
|
775
|
+
onClick: () => handleSelect(opt.value),
|
|
776
|
+
children: opt.label
|
|
777
|
+
}
|
|
778
|
+
) }, opt.value))
|
|
666
779
|
}
|
|
667
|
-
)
|
|
780
|
+
)
|
|
668
781
|
] });
|
|
669
782
|
};
|
|
670
783
|
var NavLink = ({ active, className, children, ...props }) => {
|
|
@@ -816,7 +929,7 @@ var TabList = ({ ariaLabel, className, children, ...props }) => {
|
|
|
816
929
|
const listRef = React20.useRef(null);
|
|
817
930
|
const [indicator, setIndicator] = React20.useState(null);
|
|
818
931
|
const [hasMounted, setHasMounted] = React20.useState(false);
|
|
819
|
-
|
|
932
|
+
useSafeLayoutEffect(() => {
|
|
820
933
|
const list = listRef.current;
|
|
821
934
|
if (!list) return;
|
|
822
935
|
const update = () => {
|
|
@@ -1086,12 +1199,27 @@ var Tooltip = ({
|
|
|
1086
1199
|
}
|
|
1087
1200
|
})();
|
|
1088
1201
|
const style = useSpringPresence({ visible: open, from: fromTransform });
|
|
1089
|
-
const
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1202
|
+
const child = children;
|
|
1203
|
+
const childProps = child.props;
|
|
1204
|
+
const trigger = React20.cloneElement(child, {
|
|
1205
|
+
onMouseEnter: (e) => {
|
|
1206
|
+
childProps.onMouseEnter?.(e);
|
|
1207
|
+
show();
|
|
1208
|
+
},
|
|
1209
|
+
onMouseLeave: (e) => {
|
|
1210
|
+
childProps.onMouseLeave?.(e);
|
|
1211
|
+
hide();
|
|
1212
|
+
},
|
|
1213
|
+
onFocus: (e) => {
|
|
1214
|
+
childProps.onFocus?.(e);
|
|
1215
|
+
show();
|
|
1216
|
+
},
|
|
1217
|
+
onBlur: (e) => {
|
|
1218
|
+
childProps.onBlur?.(e);
|
|
1219
|
+
hide();
|
|
1220
|
+
},
|
|
1221
|
+
// 자식의 기존 aria-describedby 보존 + tooltip id 합성 (폼 설명/에러 연결 끊김 방지)
|
|
1222
|
+
"aria-describedby": open ? [childProps["aria-describedby"], tooltipId].filter(Boolean).join(" ") : childProps["aria-describedby"]
|
|
1095
1223
|
});
|
|
1096
1224
|
if (disabled) return children;
|
|
1097
1225
|
return /* @__PURE__ */ jsxs("span", { className: "tooltip_wrapper", children: [
|
|
@@ -1165,10 +1293,13 @@ var baseColors = {
|
|
|
1165
1293
|
neutral900: "#121212",
|
|
1166
1294
|
neutral925: "#141414",
|
|
1167
1295
|
neutral950: "#0A0A0A",
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1296
|
+
// caption 전용 AA 값 (neutral_500 과 분리 — SCSS _index.scss 와 동일)
|
|
1297
|
+
textCaptionLight: "#6F6F6F",
|
|
1298
|
+
// status — SCSS _index.scss 와 동일한 AA 통과(red/green/amber/blue-700) 값
|
|
1299
|
+
statusError: "#B91C1C",
|
|
1300
|
+
statusSuccess: "#047857",
|
|
1301
|
+
statusWarning: "#B45309",
|
|
1302
|
+
statusInfo: "#1D4ED8",
|
|
1172
1303
|
alphaBlack5: "rgba(0, 0, 0, 0.05)",
|
|
1173
1304
|
alphaBlack8: "rgba(0, 0, 0, 0.08)",
|
|
1174
1305
|
alphaBlack12: "rgba(26, 26, 26, 0.12)",
|
|
@@ -1186,7 +1317,7 @@ var colors = {
|
|
|
1186
1317
|
text: {
|
|
1187
1318
|
heading: baseColors.neutral900,
|
|
1188
1319
|
body: baseColors.neutral700,
|
|
1189
|
-
caption: baseColors.
|
|
1320
|
+
caption: baseColors.textCaptionLight,
|
|
1190
1321
|
brand: baseColors.brandPrimary,
|
|
1191
1322
|
inverse: baseColors.neutral0,
|
|
1192
1323
|
disabled: baseColors.alphaBlack38
|
|
@@ -1592,6 +1723,8 @@ var Button = ({
|
|
|
1592
1723
|
fullWidth = false,
|
|
1593
1724
|
radius: radius2,
|
|
1594
1725
|
danger = false,
|
|
1726
|
+
type = "button",
|
|
1727
|
+
ref,
|
|
1595
1728
|
className,
|
|
1596
1729
|
children,
|
|
1597
1730
|
...props
|
|
@@ -1605,7 +1738,7 @@ var Button = ({
|
|
|
1605
1738
|
danger && "button_danger",
|
|
1606
1739
|
className
|
|
1607
1740
|
);
|
|
1608
|
-
return /* @__PURE__ */ jsxs("button", { className: buttonClassName, ...props, children: [
|
|
1741
|
+
return /* @__PURE__ */ jsxs("button", { ref, type, className: buttonClassName, ...props, children: [
|
|
1609
1742
|
leadingIcon && /* @__PURE__ */ jsx("span", { className: "button_icon", "aria-hidden": "true", children: leadingIcon }),
|
|
1610
1743
|
children && /* @__PURE__ */ jsx("span", { className: "button_label", children }),
|
|
1611
1744
|
trailingIcon && /* @__PURE__ */ jsx("span", { className: "button_icon", "aria-hidden": "true", children: trailingIcon })
|
|
@@ -1757,6 +1890,7 @@ var Card = ({
|
|
|
1757
1890
|
interactive = false,
|
|
1758
1891
|
footer,
|
|
1759
1892
|
footerAlign = "end",
|
|
1893
|
+
ref,
|
|
1760
1894
|
className,
|
|
1761
1895
|
children,
|
|
1762
1896
|
...props
|
|
@@ -1769,7 +1903,7 @@ var Card = ({
|
|
|
1769
1903
|
{ card_bordered: bordered, card_interactive: interactive },
|
|
1770
1904
|
className
|
|
1771
1905
|
);
|
|
1772
|
-
return /* @__PURE__ */ jsxs("div", { className: cardClassName, ...props, children: [
|
|
1906
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cardClassName, ...props, children: [
|
|
1773
1907
|
heading ? /* @__PURE__ */ jsx(HeadingTag, { className: "card_title", children: heading }) : null,
|
|
1774
1908
|
/* @__PURE__ */ jsx("div", { className: "card_body", children }),
|
|
1775
1909
|
footer ? /* @__PURE__ */ jsx("div", { className: cn("card_footer", `card_footer_${footerAlign}`), children: footer }) : null
|
|
@@ -1966,6 +2100,7 @@ var Dropdown = ({
|
|
|
1966
2100
|
placeholder = "Select\u2026",
|
|
1967
2101
|
options,
|
|
1968
2102
|
value,
|
|
2103
|
+
onValueChange,
|
|
1969
2104
|
onChange,
|
|
1970
2105
|
defaultValue = null,
|
|
1971
2106
|
disabled,
|
|
@@ -1990,9 +2125,9 @@ var Dropdown = ({
|
|
|
1990
2125
|
(next) => {
|
|
1991
2126
|
const option = options.find((o) => o.value === next) ?? null;
|
|
1992
2127
|
if (!isControlled) setInternalValue(next);
|
|
1993
|
-
onChange?.(next, option);
|
|
2128
|
+
(onValueChange ?? onChange)?.(next, option);
|
|
1994
2129
|
},
|
|
1995
|
-
[isControlled, onChange, options]
|
|
2130
|
+
[isControlled, onValueChange, onChange, options]
|
|
1996
2131
|
);
|
|
1997
2132
|
useEffect(() => {
|
|
1998
2133
|
const handleOutsideClick = (e) => {
|
|
@@ -2178,6 +2313,7 @@ var range = (start, end) => Array.from({ length: end - start + 1 }, (_, i) => st
|
|
|
2178
2313
|
var DatePicker = ({
|
|
2179
2314
|
label,
|
|
2180
2315
|
value,
|
|
2316
|
+
onValueChange,
|
|
2181
2317
|
onChange,
|
|
2182
2318
|
mode = "year-month-day",
|
|
2183
2319
|
startYear = 1950,
|
|
@@ -2264,14 +2400,15 @@ var DatePicker = ({
|
|
|
2264
2400
|
);
|
|
2265
2401
|
const emit = React20.useCallback(
|
|
2266
2402
|
(yy, mm, dd) => {
|
|
2403
|
+
const cb = onValueChange ?? onChange;
|
|
2267
2404
|
if (mode === "year-month") {
|
|
2268
|
-
|
|
2405
|
+
cb?.(`${yy}-${pad(mm)}`);
|
|
2269
2406
|
return;
|
|
2270
2407
|
}
|
|
2271
2408
|
const safeDay = Math.min(dd ?? 1, getDaysInMonth(yy, mm));
|
|
2272
|
-
|
|
2409
|
+
cb?.(`${yy}-${pad(mm)}-${pad(safeDay)}`);
|
|
2273
2410
|
},
|
|
2274
|
-
[mode, onChange]
|
|
2411
|
+
[mode, onValueChange, onChange]
|
|
2275
2412
|
);
|
|
2276
2413
|
const handleYearChange = React20.useCallback(
|
|
2277
2414
|
(raw) => {
|
|
@@ -2333,7 +2470,7 @@ var DatePicker = ({
|
|
|
2333
2470
|
placeholder: yearLabel,
|
|
2334
2471
|
options: yearOptions,
|
|
2335
2472
|
value: year ? String(year) : null,
|
|
2336
|
-
|
|
2473
|
+
onValueChange: handleYearChange,
|
|
2337
2474
|
disabled
|
|
2338
2475
|
}
|
|
2339
2476
|
),
|
|
@@ -2346,7 +2483,7 @@ var DatePicker = ({
|
|
|
2346
2483
|
placeholder: monthLabel,
|
|
2347
2484
|
options: monthOptions,
|
|
2348
2485
|
value: month ? String(month) : null,
|
|
2349
|
-
|
|
2486
|
+
onValueChange: handleMonthChange,
|
|
2350
2487
|
disabled: disabled || !year
|
|
2351
2488
|
}
|
|
2352
2489
|
),
|
|
@@ -2359,7 +2496,7 @@ var DatePicker = ({
|
|
|
2359
2496
|
placeholder: dayLabel,
|
|
2360
2497
|
options: dayOptions,
|
|
2361
2498
|
value: day ? String(day) : null,
|
|
2362
|
-
|
|
2499
|
+
onValueChange: handleDayChange,
|
|
2363
2500
|
disabled: disabled || !month
|
|
2364
2501
|
}
|
|
2365
2502
|
)
|
|
@@ -2389,12 +2526,11 @@ var FileInput = ({
|
|
|
2389
2526
|
const helperId = React20.useId();
|
|
2390
2527
|
const inputRef = React20.useRef(null);
|
|
2391
2528
|
const [previewUrls, setPreviewUrls] = React20.useState([]);
|
|
2529
|
+
const previewUrlsRef = React20.useRef([]);
|
|
2392
2530
|
const isPreviewVariant = variant === "preview";
|
|
2393
2531
|
const showPreview = isPreviewVariant || preview;
|
|
2394
2532
|
const handleChange = (e) => {
|
|
2395
2533
|
const files = e.currentTarget.files;
|
|
2396
|
-
onFiles?.(files);
|
|
2397
|
-
onChange?.(e);
|
|
2398
2534
|
if (showPreview && files) {
|
|
2399
2535
|
for (const url of previewUrls) {
|
|
2400
2536
|
URL.revokeObjectURL(url);
|
|
@@ -2407,12 +2543,16 @@ var FileInput = ({
|
|
|
2407
2543
|
}
|
|
2408
2544
|
}
|
|
2409
2545
|
setPreviewUrls(urls);
|
|
2546
|
+
previewUrlsRef.current = urls;
|
|
2410
2547
|
} else {
|
|
2411
2548
|
for (const url of previewUrls) {
|
|
2412
2549
|
URL.revokeObjectURL(url);
|
|
2413
2550
|
}
|
|
2414
2551
|
setPreviewUrls([]);
|
|
2552
|
+
previewUrlsRef.current = [];
|
|
2415
2553
|
}
|
|
2554
|
+
onFiles?.(files);
|
|
2555
|
+
onChange?.(e);
|
|
2416
2556
|
};
|
|
2417
2557
|
const handleRemove = (e) => {
|
|
2418
2558
|
e.preventDefault();
|
|
@@ -2421,6 +2561,7 @@ var FileInput = ({
|
|
|
2421
2561
|
URL.revokeObjectURL(url);
|
|
2422
2562
|
}
|
|
2423
2563
|
setPreviewUrls([]);
|
|
2564
|
+
previewUrlsRef.current = [];
|
|
2424
2565
|
if (inputRef.current) {
|
|
2425
2566
|
inputRef.current.value = "";
|
|
2426
2567
|
}
|
|
@@ -2428,11 +2569,11 @@ var FileInput = ({
|
|
|
2428
2569
|
};
|
|
2429
2570
|
React20.useEffect(() => {
|
|
2430
2571
|
return () => {
|
|
2431
|
-
for (const url of
|
|
2572
|
+
for (const url of previewUrlsRef.current) {
|
|
2432
2573
|
URL.revokeObjectURL(url);
|
|
2433
2574
|
}
|
|
2434
2575
|
};
|
|
2435
|
-
}, [
|
|
2576
|
+
}, []);
|
|
2436
2577
|
const hasImage = previewUrls.length > 0;
|
|
2437
2578
|
const rootClassName = cn(
|
|
2438
2579
|
"file_input",
|
|
@@ -2564,6 +2705,8 @@ var IconButton = ({
|
|
|
2564
2705
|
variant = "standard",
|
|
2565
2706
|
size = "md",
|
|
2566
2707
|
icon,
|
|
2708
|
+
type = "button",
|
|
2709
|
+
ref,
|
|
2567
2710
|
className,
|
|
2568
2711
|
...props
|
|
2569
2712
|
}) => {
|
|
@@ -2573,7 +2716,7 @@ var IconButton = ({
|
|
|
2573
2716
|
`icon_button_size_${size}`,
|
|
2574
2717
|
className
|
|
2575
2718
|
);
|
|
2576
|
-
return /* @__PURE__ */ jsx("button", { className: buttonClassName, ...props, children: /* @__PURE__ */ jsx("span", { className: "icon_button_icon", "aria-hidden": "true", children: icon }) });
|
|
2719
|
+
return /* @__PURE__ */ jsx("button", { ref, type, className: buttonClassName, ...props, children: /* @__PURE__ */ jsx("span", { className: "icon_button_icon", "aria-hidden": "true", children: icon }) });
|
|
2577
2720
|
};
|
|
2578
2721
|
var LinearProgress = ({
|
|
2579
2722
|
totalSteps,
|
|
@@ -2646,7 +2789,7 @@ var ListItem = ({
|
|
|
2646
2789
|
if (disabled || !onClick) return;
|
|
2647
2790
|
if (e.key === "Enter" || e.key === " ") {
|
|
2648
2791
|
e.preventDefault();
|
|
2649
|
-
|
|
2792
|
+
e.currentTarget.click();
|
|
2650
2793
|
}
|
|
2651
2794
|
},
|
|
2652
2795
|
role: onClick ? "button" : void 0,
|
|
@@ -2742,14 +2885,6 @@ var Modal = ({
|
|
|
2742
2885
|
transform: open ? "scale(1) translateY(0px)" : "scale(0.96) translateY(-4px)",
|
|
2743
2886
|
config: { tension: 280, friction: 28, clamp: !open }
|
|
2744
2887
|
});
|
|
2745
|
-
const handleEscape = React20.useEffectEvent((e) => {
|
|
2746
|
-
if (e.key === "Escape") onClose?.();
|
|
2747
|
-
});
|
|
2748
|
-
React20.useEffect(() => {
|
|
2749
|
-
if (!open) return;
|
|
2750
|
-
document.addEventListener("keydown", handleEscape);
|
|
2751
|
-
return () => document.removeEventListener("keydown", handleEscape);
|
|
2752
|
-
}, [open]);
|
|
2753
2888
|
React20.useEffect(() => {
|
|
2754
2889
|
if (!open) return;
|
|
2755
2890
|
const body = document.body;
|
|
@@ -2784,7 +2919,10 @@ var Modal = ({
|
|
|
2784
2919
|
"aria-label": !hasTitle ? ariaLabel ?? "Dialog" : ariaLabel,
|
|
2785
2920
|
onClick: () => closeOnOverlay && onClose?.(),
|
|
2786
2921
|
onKeyDown: (e) => {
|
|
2787
|
-
if (e.key === "Escape")
|
|
2922
|
+
if (e.key === "Escape") {
|
|
2923
|
+
e.stopPropagation();
|
|
2924
|
+
onClose?.();
|
|
2925
|
+
}
|
|
2788
2926
|
},
|
|
2789
2927
|
children: /* @__PURE__ */ jsxs(
|
|
2790
2928
|
animated.div,
|
|
@@ -2822,6 +2960,7 @@ var Modal = ({
|
|
|
2822
2960
|
var OtpInput = ({
|
|
2823
2961
|
length = 6,
|
|
2824
2962
|
value = "",
|
|
2963
|
+
onValueChange,
|
|
2825
2964
|
onChange,
|
|
2826
2965
|
error = false,
|
|
2827
2966
|
disabled = false,
|
|
@@ -2844,7 +2983,7 @@ var OtpInput = ({
|
|
|
2844
2983
|
inputsRef.current[index]?.focus();
|
|
2845
2984
|
};
|
|
2846
2985
|
const updateValue = (newDigits) => {
|
|
2847
|
-
onChange?.(newDigits.join(""));
|
|
2986
|
+
(onValueChange ?? onChange)?.(newDigits.join(""));
|
|
2848
2987
|
};
|
|
2849
2988
|
const handleChange = (index, e) => {
|
|
2850
2989
|
const nextDigit = e.target.value;
|
|
@@ -2968,10 +3107,12 @@ var getPaginationItems = (page, totalPages) => {
|
|
|
2968
3107
|
var Pagination = ({
|
|
2969
3108
|
page,
|
|
2970
3109
|
totalPages,
|
|
3110
|
+
onPageChange,
|
|
2971
3111
|
onChange,
|
|
2972
3112
|
prevLabel = "Previous page",
|
|
2973
3113
|
nextLabel = "Next page"
|
|
2974
3114
|
}) => {
|
|
3115
|
+
const emit = onPageChange ?? onChange;
|
|
2975
3116
|
const prevDisabled = page <= 1;
|
|
2976
3117
|
const nextDisabled = page >= totalPages;
|
|
2977
3118
|
const items = React20.useMemo(() => getPaginationItems(page, totalPages), [page, totalPages]);
|
|
@@ -2981,7 +3122,7 @@ var Pagination = ({
|
|
|
2981
3122
|
{
|
|
2982
3123
|
type: "button",
|
|
2983
3124
|
className: "pagination_item",
|
|
2984
|
-
onClick: () =>
|
|
3125
|
+
onClick: () => emit?.(page - 1),
|
|
2985
3126
|
disabled: prevDisabled,
|
|
2986
3127
|
"aria-label": prevLabel,
|
|
2987
3128
|
children: "\u2039"
|
|
@@ -3000,7 +3141,7 @@ var Pagination = ({
|
|
|
3000
3141
|
{
|
|
3001
3142
|
type: "button",
|
|
3002
3143
|
className: buttonClassName,
|
|
3003
|
-
onClick: () =>
|
|
3144
|
+
onClick: () => emit?.(it),
|
|
3004
3145
|
"aria-current": isActive ? "page" : void 0,
|
|
3005
3146
|
children: it
|
|
3006
3147
|
}
|
|
@@ -3011,7 +3152,7 @@ var Pagination = ({
|
|
|
3011
3152
|
{
|
|
3012
3153
|
type: "button",
|
|
3013
3154
|
className: "pagination_item",
|
|
3014
|
-
onClick: () =>
|
|
3155
|
+
onClick: () => emit?.(page + 1),
|
|
3015
3156
|
disabled: nextDisabled,
|
|
3016
3157
|
"aria-label": nextLabel,
|
|
3017
3158
|
children: "\u203A"
|
|
@@ -3277,13 +3418,14 @@ var ThemeProvider = ({
|
|
|
3277
3418
|
targetSelector,
|
|
3278
3419
|
children
|
|
3279
3420
|
}) => {
|
|
3280
|
-
const [mode, setModeState] = React20.useState(
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
if (
|
|
3285
|
-
|
|
3286
|
-
|
|
3421
|
+
const [mode, setModeState] = React20.useState(defaultMode);
|
|
3422
|
+
const [systemDark, setSystemDark] = React20.useState(false);
|
|
3423
|
+
React20.useEffect(() => {
|
|
3424
|
+
setModeState(readStored(storageKey) ?? defaultMode);
|
|
3425
|
+
if (isClient) {
|
|
3426
|
+
setSystemDark(window.matchMedia("(prefers-color-scheme: dark)").matches);
|
|
3427
|
+
}
|
|
3428
|
+
}, [storageKey, defaultMode]);
|
|
3287
3429
|
React20.useEffect(() => {
|
|
3288
3430
|
if (!isClient) return;
|
|
3289
3431
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
@@ -3333,6 +3475,7 @@ var TextField = ({
|
|
|
3333
3475
|
fullWidth,
|
|
3334
3476
|
size = "md",
|
|
3335
3477
|
className,
|
|
3478
|
+
onValueChange,
|
|
3336
3479
|
onChangeAction,
|
|
3337
3480
|
imeStrategy = "delayed",
|
|
3338
3481
|
value,
|
|
@@ -3363,10 +3506,10 @@ var TextField = ({
|
|
|
3363
3506
|
setInnerValue(nextValue);
|
|
3364
3507
|
if (nextValue !== lastEmittedValueRef.current) {
|
|
3365
3508
|
lastEmittedValueRef.current = nextValue;
|
|
3366
|
-
onChangeAction?.(nextValue);
|
|
3509
|
+
(onValueChange ?? onChangeAction)?.(nextValue);
|
|
3367
3510
|
}
|
|
3368
3511
|
},
|
|
3369
|
-
[onChangeAction]
|
|
3512
|
+
[onValueChange, onChangeAction]
|
|
3370
3513
|
);
|
|
3371
3514
|
const handleClear = useCallback(() => {
|
|
3372
3515
|
emit("");
|
|
@@ -3416,7 +3559,7 @@ var TextField = ({
|
|
|
3416
3559
|
setInnerValue(rawValue);
|
|
3417
3560
|
if (imeStrategy === "immediate" && rawValue !== lastEmittedValueRef.current) {
|
|
3418
3561
|
lastEmittedValueRef.current = rawValue;
|
|
3419
|
-
onChangeAction?.(rawValue);
|
|
3562
|
+
(onValueChange ?? onChangeAction)?.(rawValue);
|
|
3420
3563
|
}
|
|
3421
3564
|
return;
|
|
3422
3565
|
}
|
|
@@ -3446,6 +3589,7 @@ var Textarea = ({
|
|
|
3446
3589
|
fullWidth,
|
|
3447
3590
|
size = "md",
|
|
3448
3591
|
className,
|
|
3592
|
+
onValueChange,
|
|
3449
3593
|
onChangeAction,
|
|
3450
3594
|
imeStrategy = "delayed",
|
|
3451
3595
|
value,
|
|
@@ -3513,7 +3657,7 @@ var Textarea = ({
|
|
|
3513
3657
|
setInnerValue(nextValue);
|
|
3514
3658
|
if (nextValue !== lastEmittedValueRef.current) {
|
|
3515
3659
|
lastEmittedValueRef.current = nextValue;
|
|
3516
|
-
onChangeAction?.(nextValue);
|
|
3660
|
+
(onValueChange ?? onChangeAction)?.(nextValue);
|
|
3517
3661
|
}
|
|
3518
3662
|
};
|
|
3519
3663
|
return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
|
|
@@ -3545,7 +3689,7 @@ var Textarea = ({
|
|
|
3545
3689
|
setInnerValue(rawValue);
|
|
3546
3690
|
if (imeStrategy === "immediate" && rawValue !== lastEmittedValueRef.current) {
|
|
3547
3691
|
lastEmittedValueRef.current = rawValue;
|
|
3548
|
-
onChangeAction?.(rawValue);
|
|
3692
|
+
(onValueChange ?? onChangeAction)?.(rawValue);
|
|
3549
3693
|
}
|
|
3550
3694
|
return;
|
|
3551
3695
|
}
|
|
@@ -3625,7 +3769,8 @@ var ToastProvider = ({
|
|
|
3625
3769
|
const removeToast = React20.useCallback((id) => {
|
|
3626
3770
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
3627
3771
|
}, []);
|
|
3628
|
-
|
|
3772
|
+
const contextValue = React20.useMemo(() => ({ addToast }), [addToast]);
|
|
3773
|
+
return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: contextValue, children: [
|
|
3629
3774
|
children,
|
|
3630
3775
|
isMounted && createPortal(
|
|
3631
3776
|
// biome-ignore lint/a11y/useSemanticElements: <section> would create unwanted nesting in portal; role=region is the WAI-ARIA equivalent for live announcements
|
|
@@ -3675,6 +3820,7 @@ var useToast = () => {
|
|
|
3675
3820
|
var Toggle = ({
|
|
3676
3821
|
checked,
|
|
3677
3822
|
defaultChecked,
|
|
3823
|
+
onCheckedChange,
|
|
3678
3824
|
onChange,
|
|
3679
3825
|
size = "sm",
|
|
3680
3826
|
disabled,
|
|
@@ -3690,7 +3836,7 @@ var Toggle = ({
|
|
|
3690
3836
|
if (disabled) return;
|
|
3691
3837
|
const next = !isOn;
|
|
3692
3838
|
if (!isControlled) setInnerChecked(next);
|
|
3693
|
-
onChange?.(next);
|
|
3839
|
+
(onCheckedChange ?? onChange)?.(next);
|
|
3694
3840
|
};
|
|
3695
3841
|
const rootClassName = cn(
|
|
3696
3842
|
"toggle",
|
|
@@ -3751,6 +3897,7 @@ var Container = ({
|
|
|
3751
3897
|
size = "xl",
|
|
3752
3898
|
center = true,
|
|
3753
3899
|
as: Tag = "div",
|
|
3900
|
+
ref,
|
|
3754
3901
|
className,
|
|
3755
3902
|
children,
|
|
3756
3903
|
...props
|
|
@@ -3758,6 +3905,7 @@ var Container = ({
|
|
|
3758
3905
|
return /* @__PURE__ */ jsx(
|
|
3759
3906
|
Tag,
|
|
3760
3907
|
{
|
|
3908
|
+
ref,
|
|
3761
3909
|
className: cn("container", `container_size_${size}`, center && "container_center", className),
|
|
3762
3910
|
...props,
|
|
3763
3911
|
children
|
|
@@ -3768,6 +3916,7 @@ var Section = ({
|
|
|
3768
3916
|
spacing: spacing2 = "md",
|
|
3769
3917
|
bg = "default",
|
|
3770
3918
|
as: Tag = "section",
|
|
3919
|
+
ref,
|
|
3771
3920
|
className,
|
|
3772
3921
|
children,
|
|
3773
3922
|
...props
|
|
@@ -3775,6 +3924,7 @@ var Section = ({
|
|
|
3775
3924
|
return /* @__PURE__ */ jsx(
|
|
3776
3925
|
Tag,
|
|
3777
3926
|
{
|
|
3927
|
+
ref,
|
|
3778
3928
|
className: cn(
|
|
3779
3929
|
"section",
|
|
3780
3930
|
`section_spacing_${spacing2}`,
|
|
@@ -3793,6 +3943,7 @@ var Stack = ({
|
|
|
3793
3943
|
justify,
|
|
3794
3944
|
wrap,
|
|
3795
3945
|
as: Tag = "div",
|
|
3946
|
+
ref,
|
|
3796
3947
|
className,
|
|
3797
3948
|
children,
|
|
3798
3949
|
style,
|
|
@@ -3801,6 +3952,7 @@ var Stack = ({
|
|
|
3801
3952
|
return /* @__PURE__ */ jsx(
|
|
3802
3953
|
Tag,
|
|
3803
3954
|
{
|
|
3955
|
+
ref,
|
|
3804
3956
|
className: cn(
|
|
3805
3957
|
"stack",
|
|
3806
3958
|
`stack_${direction}`,
|
|
@@ -3823,6 +3975,7 @@ var Grid = ({
|
|
|
3823
3975
|
colGap,
|
|
3824
3976
|
singleColOnMobile = true,
|
|
3825
3977
|
as: Tag = "div",
|
|
3978
|
+
ref,
|
|
3826
3979
|
className,
|
|
3827
3980
|
children,
|
|
3828
3981
|
style,
|
|
@@ -3832,6 +3985,7 @@ var Grid = ({
|
|
|
3832
3985
|
return /* @__PURE__ */ jsx(
|
|
3833
3986
|
Tag,
|
|
3834
3987
|
{
|
|
3988
|
+
ref,
|
|
3835
3989
|
className: cn("grid_layout", singleColOnMobile && "grid_layout_mobile_single", className),
|
|
3836
3990
|
style: {
|
|
3837
3991
|
"--grid-cols": gridTemplateColumns,
|
|
@@ -3846,4 +4000,4 @@ var Grid = ({
|
|
|
3846
4000
|
);
|
|
3847
4001
|
};
|
|
3848
4002
|
|
|
3849
|
-
export { Accordion, AlertProvider, Avatar, Badge, BottomNav, BottomNavItem, BottomNavSpacer, Breadcrumb, Button, Card, Checkbox, Chip, Container, DatePicker, Divider, Dropdown, EmptyState, ErrorState, FileInput, Grid, Hero, Icon, IconButton, 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, motion, opacity, radius, skeleton, spacing, typography, useAlert, useFocusTrap, useSpringHover, useSpringPresence, useTheme, useToast, zIndex };
|
|
4003
|
+
export { Accordion, AlertProvider, Avatar, Badge, BottomNav, BottomNavItem, BottomNavSpacer, Breadcrumb, Button, Card, Checkbox, Chip, Container, DatePicker, Divider, Dropdown, EmptyState, ErrorState, FileInput, Grid, Hero, Icon, IconButton, 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, motion, opacity, radius, skeleton, spacing, typography, useAlert, useFocusTrap, useReducedMotion, useSpringHover, useSpringPresence, useTheme, useToast, zIndex };
|