@bigtablet/design-system 3.16.0 → 3.17.1
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 +2237 -1341
- package/dist/index.d.ts +1028 -197
- package/dist/index.js +1994 -785
- package/dist/styles/layout/_index.scss +18 -0
- package/dist/styles/typography/_index.scss +23 -0
- package/dist/vanilla/bigtablet.min.css +1 -1
- package/dist/vanilla/bigtablet.min.js +10 -10
- package/docs/AGENT_GUIDE.md +591 -0
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import './index.css';
|
|
3
3
|
import * as React11 from 'react';
|
|
4
|
-
import { createContext,
|
|
4
|
+
import { createContext, useState, useRef, useCallback, useEffect, useMemo, useContext, useId, Fragment, useImperativeHandle, useLayoutEffect } from 'react';
|
|
5
5
|
import { useSpring, animated } from '@react-spring/web';
|
|
6
|
-
import { ChevronDown, ChevronRight, Globe, ChevronLeft, ArrowUp, ArrowDown, ArrowUpDown, XCircle, AlertTriangle, CheckCircle2, Info, Bell,
|
|
6
|
+
import { ChevronDown, ChevronRight, Globe, ChevronLeft, EyeOff, Eye, ArrowUp, ArrowDown, ArrowUpDown, Search, XCircle, AlertTriangle, CheckCircle2, Info, Bell, Check, Image, X, TriangleAlert } from 'lucide-react';
|
|
7
7
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
8
8
|
import { createPortal } from 'react-dom';
|
|
9
9
|
|
|
@@ -91,15 +91,23 @@ function lockBodyScroll() {
|
|
|
91
91
|
const open = Number.parseInt(body.dataset[COUNTER] || "0", 10);
|
|
92
92
|
if (open === 0) {
|
|
93
93
|
const scrollbarWidth = measureViewportInset();
|
|
94
|
+
const scroller = document.scrollingElement ?? html;
|
|
95
|
+
const documentScrolls = scroller.scrollHeight > scroller.clientHeight;
|
|
96
|
+
const canReserveGutter = typeof CSS !== "undefined" && typeof CSS.supports === "function" && CSS.supports("scrollbar-gutter: stable");
|
|
94
97
|
body.dataset[PREV_OVERFLOW] = body.style.overflow;
|
|
95
98
|
body.dataset[PREV_GUTTER] = html.style.scrollbarGutter;
|
|
96
99
|
body.dataset[PREV_PADDING_RIGHT] = body.style.paddingRight;
|
|
97
100
|
body.dataset[PREV_SCROLLBAR_WIDTH_VAR] = html.style.getPropertyValue(SCROLLBAR_WIDTH_VAR);
|
|
98
101
|
if (scrollbarWidth > 0) {
|
|
99
102
|
html.style.setProperty(SCROLLBAR_WIDTH_VAR, `${scrollbarWidth}px`);
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
+
}
|
|
104
|
+
if (documentScrolls && scrollbarWidth > 0) {
|
|
105
|
+
if (canReserveGutter) {
|
|
106
|
+
html.style.scrollbarGutter = "stable";
|
|
107
|
+
} else {
|
|
108
|
+
const current = Number.parseFloat(window.getComputedStyle(body).paddingRight) || 0;
|
|
109
|
+
body.style.paddingRight = `${current + scrollbarWidth}px`;
|
|
110
|
+
}
|
|
103
111
|
}
|
|
104
112
|
body.style.overflow = "hidden";
|
|
105
113
|
}
|
|
@@ -409,6 +417,168 @@ function useSpringPresence({
|
|
|
409
417
|
}
|
|
410
418
|
});
|
|
411
419
|
}
|
|
420
|
+
var MIN_SPACE_BELOW = 120;
|
|
421
|
+
function useListboxPopup({
|
|
422
|
+
items,
|
|
423
|
+
onCommit,
|
|
424
|
+
disabled = false,
|
|
425
|
+
returnFocusOnClose = false,
|
|
426
|
+
initialActiveIndex
|
|
427
|
+
}) {
|
|
428
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
429
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
430
|
+
const [dropUp, setDropUp] = useState(false);
|
|
431
|
+
const wrapperRef = useRef(null);
|
|
432
|
+
const triggerRef = useRef(null);
|
|
433
|
+
const listRef = useRef(null);
|
|
434
|
+
const close = useCallback(() => {
|
|
435
|
+
setIsOpen(false);
|
|
436
|
+
if (returnFocusOnClose) triggerRef.current?.focus();
|
|
437
|
+
}, [returnFocusOnClose]);
|
|
438
|
+
useEffect(() => {
|
|
439
|
+
const handleOutsideClick = (event) => {
|
|
440
|
+
if (!wrapperRef.current?.contains(event.target)) setIsOpen(false);
|
|
441
|
+
};
|
|
442
|
+
document.addEventListener("mousedown", handleOutsideClick);
|
|
443
|
+
return () => document.removeEventListener("mousedown", handleOutsideClick);
|
|
444
|
+
}, []);
|
|
445
|
+
const moveActive = useCallback(
|
|
446
|
+
(dir) => {
|
|
447
|
+
if (items.length === 0) return;
|
|
448
|
+
if (!isOpen) {
|
|
449
|
+
setIsOpen(true);
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
let i = activeIndex;
|
|
453
|
+
if (i === -1) {
|
|
454
|
+
i = dir === 1 ? -1 : 0;
|
|
455
|
+
}
|
|
456
|
+
const len = items.length;
|
|
457
|
+
for (let step = 0; step < len; step++) {
|
|
458
|
+
i = (i + dir + len) % len;
|
|
459
|
+
if (!items[i].disabled) {
|
|
460
|
+
setActiveIndex(i);
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
[items, isOpen, activeIndex]
|
|
466
|
+
);
|
|
467
|
+
const commitActive = useCallback(() => {
|
|
468
|
+
if (activeIndex < 0 || activeIndex >= items.length) return;
|
|
469
|
+
const item = items[activeIndex];
|
|
470
|
+
if (item.disabled) return;
|
|
471
|
+
onCommit(item);
|
|
472
|
+
}, [activeIndex, items, onCommit]);
|
|
473
|
+
const firstEnabled = useCallback(() => items.findIndex((o) => !o.disabled), [items]);
|
|
474
|
+
const lastEnabled = useCallback(() => {
|
|
475
|
+
for (let i = items.length - 1; i >= 0; i--) {
|
|
476
|
+
if (!items[i].disabled) return i;
|
|
477
|
+
}
|
|
478
|
+
return -1;
|
|
479
|
+
}, [items]);
|
|
480
|
+
const onTriggerKeyDown = useCallback(
|
|
481
|
+
(event) => {
|
|
482
|
+
if (disabled) return;
|
|
483
|
+
switch (event.key) {
|
|
484
|
+
case " ":
|
|
485
|
+
case "Enter":
|
|
486
|
+
event.preventDefault();
|
|
487
|
+
if (!isOpen) setIsOpen(true);
|
|
488
|
+
else commitActive();
|
|
489
|
+
break;
|
|
490
|
+
case "ArrowDown":
|
|
491
|
+
event.preventDefault();
|
|
492
|
+
moveActive(1);
|
|
493
|
+
break;
|
|
494
|
+
case "ArrowUp":
|
|
495
|
+
event.preventDefault();
|
|
496
|
+
moveActive(-1);
|
|
497
|
+
break;
|
|
498
|
+
case "Home":
|
|
499
|
+
event.preventDefault();
|
|
500
|
+
setIsOpen(true);
|
|
501
|
+
setActiveIndex(firstEnabled());
|
|
502
|
+
break;
|
|
503
|
+
case "End":
|
|
504
|
+
event.preventDefault();
|
|
505
|
+
setIsOpen(true);
|
|
506
|
+
setActiveIndex(lastEnabled());
|
|
507
|
+
break;
|
|
508
|
+
case "Escape":
|
|
509
|
+
event.preventDefault();
|
|
510
|
+
setIsOpen(false);
|
|
511
|
+
break;
|
|
512
|
+
case "Tab":
|
|
513
|
+
setIsOpen(false);
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
[disabled, isOpen, commitActive, moveActive, firstEnabled, lastEnabled]
|
|
518
|
+
);
|
|
519
|
+
const onInputKeyDown = useCallback(
|
|
520
|
+
(event) => {
|
|
521
|
+
if (disabled) return;
|
|
522
|
+
if (event.nativeEvent.isComposing) return;
|
|
523
|
+
switch (event.key) {
|
|
524
|
+
case "ArrowDown":
|
|
525
|
+
event.preventDefault();
|
|
526
|
+
moveActive(1);
|
|
527
|
+
break;
|
|
528
|
+
case "ArrowUp":
|
|
529
|
+
event.preventDefault();
|
|
530
|
+
moveActive(-1);
|
|
531
|
+
break;
|
|
532
|
+
case "Enter":
|
|
533
|
+
event.preventDefault();
|
|
534
|
+
commitActive();
|
|
535
|
+
break;
|
|
536
|
+
case "Escape":
|
|
537
|
+
event.preventDefault();
|
|
538
|
+
close();
|
|
539
|
+
break;
|
|
540
|
+
case "Tab":
|
|
541
|
+
close();
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
[disabled, moveActive, commitActive, close]
|
|
546
|
+
);
|
|
547
|
+
useEffect(() => {
|
|
548
|
+
if (!isOpen) return;
|
|
549
|
+
const preferred = initialActiveIndex?.(items) ?? -1;
|
|
550
|
+
setActiveIndex(preferred >= 0 ? preferred : items.findIndex((o) => !o.disabled));
|
|
551
|
+
}, [isOpen, items]);
|
|
552
|
+
useEffect(() => {
|
|
553
|
+
if (!isOpen || activeIndex < 0) return;
|
|
554
|
+
const list = listRef.current;
|
|
555
|
+
if (!list) return;
|
|
556
|
+
const option = list.querySelectorAll('[role="option"]')[activeIndex];
|
|
557
|
+
option?.scrollIntoView?.({ block: "nearest" });
|
|
558
|
+
}, [isOpen, activeIndex, items]);
|
|
559
|
+
useEffect(() => {
|
|
560
|
+
if (!isOpen || !triggerRef.current) return;
|
|
561
|
+
const rect = triggerRef.current.getBoundingClientRect();
|
|
562
|
+
const spaceBelow = window.innerHeight - rect.bottom;
|
|
563
|
+
const spaceAbove = rect.top;
|
|
564
|
+
setDropUp(spaceBelow < MIN_SPACE_BELOW && spaceAbove > spaceBelow);
|
|
565
|
+
}, [isOpen]);
|
|
566
|
+
return {
|
|
567
|
+
isOpen,
|
|
568
|
+
setIsOpen,
|
|
569
|
+
dropUp,
|
|
570
|
+
activeIndex,
|
|
571
|
+
setActiveIndex,
|
|
572
|
+
wrapperRef,
|
|
573
|
+
triggerRef,
|
|
574
|
+
listRef,
|
|
575
|
+
close,
|
|
576
|
+
moveActive,
|
|
577
|
+
commitActive,
|
|
578
|
+
onTriggerKeyDown,
|
|
579
|
+
onInputKeyDown
|
|
580
|
+
};
|
|
581
|
+
}
|
|
412
582
|
|
|
413
583
|
// src/styles/icon/index.ts
|
|
414
584
|
var iconSize = {
|
|
@@ -550,6 +720,90 @@ var Badge = ({
|
|
|
550
720
|
}
|
|
551
721
|
);
|
|
552
722
|
};
|
|
723
|
+
var DescriptionList = ({
|
|
724
|
+
items,
|
|
725
|
+
layout = "row",
|
|
726
|
+
divided = false,
|
|
727
|
+
className,
|
|
728
|
+
ref,
|
|
729
|
+
...props
|
|
730
|
+
}) => /* @__PURE__ */ jsx(
|
|
731
|
+
"dl",
|
|
732
|
+
{
|
|
733
|
+
ref,
|
|
734
|
+
className: cn(
|
|
735
|
+
"description_list",
|
|
736
|
+
`description_list_layout_${layout}`,
|
|
737
|
+
{ description_list_divided: divided },
|
|
738
|
+
className
|
|
739
|
+
),
|
|
740
|
+
...props,
|
|
741
|
+
children: items.map((item, index) => /* @__PURE__ */ jsxs(
|
|
742
|
+
"div",
|
|
743
|
+
{
|
|
744
|
+
className: cn("description_list_item", { description_list_item_full: item.full }),
|
|
745
|
+
children: [
|
|
746
|
+
/* @__PURE__ */ jsx("dt", { className: "description_list_label", children: item.label }),
|
|
747
|
+
/* @__PURE__ */ jsx("dd", { className: "description_list_value", children: item.value })
|
|
748
|
+
]
|
|
749
|
+
},
|
|
750
|
+
index
|
|
751
|
+
))
|
|
752
|
+
}
|
|
753
|
+
);
|
|
754
|
+
var isPresent = (value) => value !== void 0 && value !== null && value !== "";
|
|
755
|
+
var Stat = ({
|
|
756
|
+
label,
|
|
757
|
+
value,
|
|
758
|
+
delta,
|
|
759
|
+
deltaTone = "neutral",
|
|
760
|
+
icon,
|
|
761
|
+
className,
|
|
762
|
+
ref,
|
|
763
|
+
...props
|
|
764
|
+
}) => /* @__PURE__ */ jsxs("div", { ref, className: cn("stat", className), ...props, children: [
|
|
765
|
+
/* @__PURE__ */ jsxs("div", { className: "stat_label", children: [
|
|
766
|
+
icon && /* @__PURE__ */ jsx("span", { className: "stat_icon", "aria-hidden": "true", children: icon }),
|
|
767
|
+
label
|
|
768
|
+
] }),
|
|
769
|
+
/* @__PURE__ */ jsx("div", { className: "stat_value", children: value }),
|
|
770
|
+
isPresent(delta) && /* @__PURE__ */ jsx("div", { className: cn("stat_delta", `stat_delta_${deltaTone}`), children: delta })
|
|
771
|
+
] });
|
|
772
|
+
var CheckGlyph = () => /* @__PURE__ */ jsx(
|
|
773
|
+
"svg",
|
|
774
|
+
{
|
|
775
|
+
viewBox: "0 0 20 20",
|
|
776
|
+
fill: "none",
|
|
777
|
+
stroke: "currentColor",
|
|
778
|
+
strokeWidth: 2,
|
|
779
|
+
strokeLinecap: "round",
|
|
780
|
+
strokeLinejoin: "round",
|
|
781
|
+
"aria-hidden": "true",
|
|
782
|
+
focusable: "false",
|
|
783
|
+
className: "timeline_glyph",
|
|
784
|
+
children: /* @__PURE__ */ jsx("polyline", { points: "4 10 8 14 16 6" })
|
|
785
|
+
}
|
|
786
|
+
);
|
|
787
|
+
var isPresent2 = (value) => value !== void 0 && value !== null && value !== "";
|
|
788
|
+
var Timeline = ({ items, className, ref, ...props }) => /* @__PURE__ */ jsx("ol", { ref, className: cn("timeline", className), ...props, children: items.map((item) => {
|
|
789
|
+
const status = item.status ?? "pending";
|
|
790
|
+
return /* @__PURE__ */ jsxs("li", { className: cn("timeline_item", `timeline_item_${status}`), children: [
|
|
791
|
+
/* @__PURE__ */ jsx("span", { className: "timeline_indicator", "aria-hidden": "true", children: item.icon ?? (status === "done" ? /* @__PURE__ */ jsx(CheckGlyph, {}) : /* @__PURE__ */ jsx(
|
|
792
|
+
"span",
|
|
793
|
+
{
|
|
794
|
+
className: cn("timeline_dot", { timeline_dot_hollow: status === "pending" })
|
|
795
|
+
}
|
|
796
|
+
)) }),
|
|
797
|
+
/* @__PURE__ */ jsxs("div", { className: "timeline_body", children: [
|
|
798
|
+
/* @__PURE__ */ jsxs("div", { className: "timeline_head", children: [
|
|
799
|
+
/* @__PURE__ */ jsx("div", { className: "timeline_title", children: item.title }),
|
|
800
|
+
isPresent2(item.time) && /* @__PURE__ */ jsx("div", { className: "timeline_time", children: item.time })
|
|
801
|
+
] }),
|
|
802
|
+
isPresent2(item.description) && /* @__PURE__ */ jsx("div", { className: "timeline_description", children: item.description }),
|
|
803
|
+
item.children
|
|
804
|
+
] })
|
|
805
|
+
] }, item.id);
|
|
806
|
+
}) });
|
|
553
807
|
var EmptyState = ({
|
|
554
808
|
illustration,
|
|
555
809
|
title,
|
|
@@ -579,12 +833,181 @@ var EmptyState = ({
|
|
|
579
833
|
}
|
|
580
834
|
);
|
|
581
835
|
};
|
|
836
|
+
|
|
837
|
+
// src/ui/system/locale-provider/messages.ts
|
|
838
|
+
var ko = {
|
|
839
|
+
"chip.remove": "{label} \uC81C\uAC70",
|
|
840
|
+
"dataView.clearSelection": "\uC120\uD0DD \uD574\uC81C",
|
|
841
|
+
"dataView.empty": "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
842
|
+
"dataView.errorTitle": "\uBD88\uB7EC\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4",
|
|
843
|
+
"dataView.retry": "\uB2E4\uC2DC \uC2DC\uB3C4",
|
|
844
|
+
"dataView.search": "\uAC80\uC0C9",
|
|
845
|
+
"dataView.selectionSummary": "{count}\uAC1C \uC120\uD0DD\uB428",
|
|
846
|
+
"table.empty": "\uB370\uC774\uD130\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
847
|
+
"table.rowClickHint": "\uD074\uB9AD \uAC00\uB2A5\uD55C \uD589",
|
|
848
|
+
"table.selectAll": "\uC804\uCCB4 \uC120\uD0DD",
|
|
849
|
+
"table.selectRow": "{index}\uBC88\uC9F8 \uD589 \uC120\uD0DD",
|
|
850
|
+
"alert.cancel": "\uCDE8\uC18C",
|
|
851
|
+
"alert.confirm": "\uD655\uC778",
|
|
852
|
+
"errorState.title": "\uBB38\uC81C\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4",
|
|
853
|
+
"spinner.label": "\uB85C\uB529 \uC911",
|
|
854
|
+
"toast.close": "\uB2EB\uAE30",
|
|
855
|
+
"toast.region": "\uC54C\uB9BC",
|
|
856
|
+
"topLoading.label": "\uD398\uC774\uC9C0 \uB85C\uB529 \uC911",
|
|
857
|
+
"combobox.empty": "\uC77C\uCE58\uD558\uB294 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4",
|
|
858
|
+
"combobox.idle": "\uAC80\uC0C9\uC5B4\uB97C \uC785\uB825\uD558\uC138\uC694",
|
|
859
|
+
"combobox.loading": "\uAC80\uC0C9 \uC911",
|
|
860
|
+
"combobox.placeholder": "\uAC80\uC0C9\uD574\uC11C \uC120\uD0DD",
|
|
861
|
+
"datePicker.day": "\uC77C",
|
|
862
|
+
"datePicker.minDateSr": "\uCD5C\uC18C \uB0A0\uC9DC: {date}",
|
|
863
|
+
"datePicker.month": "\uC6D4",
|
|
864
|
+
"datePicker.rangeUntilTodaySr": "\uC624\uB298\uAE4C\uC9C0 \uC120\uD0DD \uAC00\uB2A5",
|
|
865
|
+
"datePicker.year": "\uB144",
|
|
866
|
+
"dateRange.end": "\uC885\uB8CC\uC77C",
|
|
867
|
+
"dateRange.start": "\uC2DC\uC791\uC77C",
|
|
868
|
+
"dropdown.empty": "\uACB0\uACFC \uC5C6\uC74C",
|
|
869
|
+
"dropdown.placeholder": "\uC120\uD0DD\u2026",
|
|
870
|
+
"dropdown.searchPlaceholder": "\uAC80\uC0C9\u2026",
|
|
871
|
+
"dropdown.selectedSummary": "{count}\uAC1C \uC120\uD0DD",
|
|
872
|
+
"fileInput.label": "\uD30C\uC77C \uC120\uD0DD",
|
|
873
|
+
"fileInput.removeImage": "\uC774\uBBF8\uC9C0 \uC81C\uAC70",
|
|
874
|
+
"imageCropper.hint": "\uB4DC\uB798\uADF8(\uB610\uB294 \uBC29\uD5A5\uD0A4)\uB85C \uC704\uCE58, \uD720\xB7\uC2AC\uB77C\uC774\uB354\uB85C \uBC30\uC728\uC744 \uB9DE\uCD94\uC138\uC694.",
|
|
875
|
+
"imageCropper.label": "\uC774\uBBF8\uC9C0 \uC704\uCE58\uC640 \uBC30\uC728 \uC870\uC815",
|
|
876
|
+
"imageCropper.noPanHint": "\uC774\uBBF8\uC9C0\uAC00 \uBDF0\uD3EC\uD2B8\uB97C \uB531 \uCC44\uC6CC \uC774\uB3D9 \uC5EC\uC720\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
877
|
+
"imageCropper.zoom": "\uBC30\uC728",
|
|
878
|
+
"imageCropper.zoomIn": "\uD655\uB300",
|
|
879
|
+
"imageCropper.zoomOut": "\uCD95\uC18C",
|
|
880
|
+
"otpInput.digit": "{index}\uBC88\uC9F8 \uC790\uB9AC",
|
|
881
|
+
"otpInput.label": "OTP \uC785\uB825",
|
|
882
|
+
"tagInput.added": "{names} \uCD94\uAC00\uB428",
|
|
883
|
+
"tagInput.addedWithNotes": "{names} \uCD94\uAC00\uB428 ({notes})",
|
|
884
|
+
"tagInput.atCap": "\uCD5C\uB300 {max}\uAC1C\uAE4C\uC9C0 \uCD94\uAC00\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4",
|
|
885
|
+
"tagInput.duplicate": "{names} \uC774\uBBF8 \uC788\uC74C",
|
|
886
|
+
"tagInput.placeholder": "\uC785\uB825 \uD6C4 Enter",
|
|
887
|
+
"tagInput.removed": "{name} \uC81C\uAC70\uB428",
|
|
888
|
+
"textField.clear": "\uC9C0\uC6B0\uAE30",
|
|
889
|
+
"textField.passwordHide": "\uBE44\uBC00\uBC88\uD638 \uC228\uAE30\uAE30",
|
|
890
|
+
"textField.passwordShow": "\uBE44\uBC00\uBC88\uD638 \uD45C\uC2DC",
|
|
891
|
+
"timePicker.hour": "\uC2DC",
|
|
892
|
+
"timePicker.minute": "\uBD84",
|
|
893
|
+
"timePicker.rangeSr": "{min} \uBD80\uD130 {max} \uAE4C\uC9C0 \uC120\uD0DD \uAC00\uB2A5",
|
|
894
|
+
"bottomNav.label": "\uC8FC\uC694 \uBA54\uB274",
|
|
895
|
+
"breadcrumb.label": "\uD604\uC7AC \uC704\uCE58",
|
|
896
|
+
"pagination.label": "\uD398\uC774\uC9C0 \uC774\uB3D9",
|
|
897
|
+
"pagination.next": "\uB2E4\uC74C \uD398\uC774\uC9C0",
|
|
898
|
+
"pagination.prev": "\uC774\uC804 \uD398\uC774\uC9C0",
|
|
899
|
+
"sidebar.toggle": "\uC0AC\uC774\uB4DC\uBC14 \uD1A0\uAE00",
|
|
900
|
+
"drawer.close": "\uB2EB\uAE30",
|
|
901
|
+
"modal.close": "\uB2EB\uAE30"
|
|
902
|
+
};
|
|
903
|
+
var en = {
|
|
904
|
+
"chip.remove": "Remove {label}",
|
|
905
|
+
"dataView.clearSelection": "Clear selection",
|
|
906
|
+
"dataView.empty": "No data",
|
|
907
|
+
"dataView.errorTitle": "Could not load",
|
|
908
|
+
"dataView.retry": "Try again",
|
|
909
|
+
"dataView.search": "Search",
|
|
910
|
+
"dataView.selectionSummary": "{count} selected",
|
|
911
|
+
"table.empty": "No data",
|
|
912
|
+
"table.rowClickHint": "Clickable row",
|
|
913
|
+
"table.selectAll": "Select all",
|
|
914
|
+
"table.selectRow": "Select row {index}",
|
|
915
|
+
"alert.cancel": "Cancel",
|
|
916
|
+
"alert.confirm": "OK",
|
|
917
|
+
"errorState.title": "Something went wrong",
|
|
918
|
+
"spinner.label": "Loading",
|
|
919
|
+
"toast.close": "Close",
|
|
920
|
+
"toast.region": "Notifications",
|
|
921
|
+
"topLoading.label": "Loading page",
|
|
922
|
+
"combobox.empty": "No matches",
|
|
923
|
+
"combobox.idle": "Type to search",
|
|
924
|
+
"combobox.loading": "Searching",
|
|
925
|
+
"combobox.placeholder": "Search to select",
|
|
926
|
+
"datePicker.day": "Day",
|
|
927
|
+
"datePicker.minDateSr": "Earliest date: {date}",
|
|
928
|
+
"datePicker.month": "Month",
|
|
929
|
+
"datePicker.rangeUntilTodaySr": "Selectable up to today",
|
|
930
|
+
"datePicker.year": "Year",
|
|
931
|
+
"dateRange.end": "End date",
|
|
932
|
+
"dateRange.start": "Start date",
|
|
933
|
+
"dropdown.empty": "No results",
|
|
934
|
+
"dropdown.placeholder": "Select\u2026",
|
|
935
|
+
"dropdown.searchPlaceholder": "Search\u2026",
|
|
936
|
+
"dropdown.selectedSummary": "{count} selected",
|
|
937
|
+
"fileInput.label": "Choose file",
|
|
938
|
+
"fileInput.removeImage": "Remove image",
|
|
939
|
+
"imageCropper.hint": "Drag (or use arrow keys) to move, wheel or slider to zoom.",
|
|
940
|
+
"imageCropper.label": "Adjust image position and zoom",
|
|
941
|
+
"imageCropper.noPanHint": "The image fills the viewport exactly, so there is no room to move it.",
|
|
942
|
+
"imageCropper.zoom": "Zoom",
|
|
943
|
+
"imageCropper.zoomIn": "Zoom in",
|
|
944
|
+
"imageCropper.zoomOut": "Zoom out",
|
|
945
|
+
"otpInput.digit": "Digit {index}",
|
|
946
|
+
"otpInput.label": "One-time code",
|
|
947
|
+
"tagInput.added": "{names} added",
|
|
948
|
+
"tagInput.addedWithNotes": "{names} added ({notes})",
|
|
949
|
+
"tagInput.atCap": "You can add up to {max}",
|
|
950
|
+
"tagInput.duplicate": "{names} already added",
|
|
951
|
+
"tagInput.placeholder": "Type and press Enter",
|
|
952
|
+
"tagInput.removed": "{name} removed",
|
|
953
|
+
"textField.clear": "Clear",
|
|
954
|
+
"textField.passwordHide": "Hide password",
|
|
955
|
+
"textField.passwordShow": "Show password",
|
|
956
|
+
"timePicker.hour": "Hour",
|
|
957
|
+
"timePicker.minute": "Minute",
|
|
958
|
+
"timePicker.rangeSr": "Selectable from {min} to {max}",
|
|
959
|
+
"bottomNav.label": "Main menu",
|
|
960
|
+
"breadcrumb.label": "Breadcrumb",
|
|
961
|
+
"pagination.label": "Pagination",
|
|
962
|
+
"pagination.next": "Next page",
|
|
963
|
+
"pagination.prev": "Previous page",
|
|
964
|
+
"sidebar.toggle": "Toggle sidebar",
|
|
965
|
+
"drawer.close": "Close",
|
|
966
|
+
"modal.close": "Close"
|
|
967
|
+
};
|
|
968
|
+
var catalogs = { ko, en };
|
|
969
|
+
function format(template, vars) {
|
|
970
|
+
if (!vars) return template;
|
|
971
|
+
return template.replace(
|
|
972
|
+
/\{(\w+)\}/g,
|
|
973
|
+
(whole, name) => name in vars ? String(vars[name]) : whole
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
function makeText(messages) {
|
|
977
|
+
return (key, vars) => format(messages[key], vars);
|
|
978
|
+
}
|
|
979
|
+
var FALLBACK = { locale: "ko", t: makeText(ko) };
|
|
980
|
+
var LocaleContext = createContext(void 0);
|
|
981
|
+
var LocaleProvider = ({ locale = "ko", messages, children }) => {
|
|
982
|
+
const stableMessages = useStableMessages(messages);
|
|
983
|
+
const value = useMemo(() => {
|
|
984
|
+
const base = catalogs[locale];
|
|
985
|
+
const merged = stableMessages ? { ...base, ...stableMessages } : base;
|
|
986
|
+
return { locale, t: makeText(merged) };
|
|
987
|
+
}, [locale, stableMessages]);
|
|
988
|
+
return /* @__PURE__ */ jsx(LocaleContext.Provider, { value, children });
|
|
989
|
+
};
|
|
990
|
+
function useStableMessages(messages) {
|
|
991
|
+
const ref = useRef(messages);
|
|
992
|
+
const previous = ref.current;
|
|
993
|
+
const same = previous === messages || !!previous && !!messages && Object.keys(previous).length === Object.keys(messages).length && Object.keys(messages).every((key) => previous[key] === messages[key]);
|
|
994
|
+
useEffect(() => {
|
|
995
|
+
if (!same) ref.current = messages;
|
|
996
|
+
}, [same, messages]);
|
|
997
|
+
return same ? previous : messages;
|
|
998
|
+
}
|
|
999
|
+
function useLocaleText() {
|
|
1000
|
+
return (useContext(LocaleContext) ?? FALLBACK).t;
|
|
1001
|
+
}
|
|
1002
|
+
function useLocaleName() {
|
|
1003
|
+
return (useContext(LocaleContext) ?? FALLBACK).locale;
|
|
1004
|
+
}
|
|
582
1005
|
var DEFAULT_ICON_SIZE = {
|
|
583
1006
|
page: 48,
|
|
584
1007
|
widget: 28
|
|
585
1008
|
};
|
|
586
1009
|
var ErrorState = ({
|
|
587
|
-
title
|
|
1010
|
+
title: titleProp,
|
|
588
1011
|
description,
|
|
589
1012
|
icon,
|
|
590
1013
|
action,
|
|
@@ -592,6 +1015,8 @@ var ErrorState = ({
|
|
|
592
1015
|
className,
|
|
593
1016
|
...props
|
|
594
1017
|
}) => {
|
|
1018
|
+
const t = useLocaleText();
|
|
1019
|
+
const title = titleProp === void 0 ? t("errorState.title") : titleProp;
|
|
595
1020
|
const resolvedIcon = icon === null ? null : icon ?? /* @__PURE__ */ jsx(TriangleAlert, { size: DEFAULT_ICON_SIZE[variant], strokeWidth: 1.5 });
|
|
596
1021
|
return /* @__PURE__ */ jsxs(
|
|
597
1022
|
"div",
|
|
@@ -609,15 +1034,17 @@ var ErrorState = ({
|
|
|
609
1034
|
);
|
|
610
1035
|
};
|
|
611
1036
|
var BottomNav = ({
|
|
612
|
-
ariaLabel
|
|
1037
|
+
ariaLabel: ariaLabelProp,
|
|
613
1038
|
className,
|
|
614
1039
|
children,
|
|
615
1040
|
...props
|
|
616
1041
|
}) => {
|
|
1042
|
+
const t = useLocaleText();
|
|
1043
|
+
const ariaLabel = ariaLabelProp ?? t("bottomNav.label");
|
|
617
1044
|
return /* @__PURE__ */ jsx("nav", { className: cn("bottom_nav", className), "aria-label": ariaLabel, ...props, children });
|
|
618
1045
|
};
|
|
619
1046
|
var BottomNavItem = (props) => {
|
|
620
|
-
const { icon, label, active, badge, as
|
|
1047
|
+
const { icon, label, active, badge, as, className, disabled, ref, ...rest } = props;
|
|
621
1048
|
const classes = cn(
|
|
622
1049
|
"bottom_nav_item",
|
|
623
1050
|
active && "bottom_nav_item_active",
|
|
@@ -625,6 +1052,8 @@ var BottomNavItem = (props) => {
|
|
|
625
1052
|
className
|
|
626
1053
|
);
|
|
627
1054
|
const ariaCurrent = active ? "page" : void 0;
|
|
1055
|
+
const anchorRest = rest;
|
|
1056
|
+
const Tag = as ?? (anchorRest.href != null ? "a" : "button");
|
|
628
1057
|
const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
629
1058
|
/* @__PURE__ */ jsxs("span", { className: "bottom_nav_item_icon", "aria-hidden": "true", children: [
|
|
630
1059
|
icon,
|
|
@@ -632,38 +1061,45 @@ var BottomNavItem = (props) => {
|
|
|
632
1061
|
] }),
|
|
633
1062
|
/* @__PURE__ */ jsx("span", { className: "bottom_nav_item_label", children: label })
|
|
634
1063
|
] });
|
|
635
|
-
if (
|
|
636
|
-
const {
|
|
1064
|
+
if (Tag === "button") {
|
|
1065
|
+
const {
|
|
1066
|
+
type,
|
|
1067
|
+
onClick: onClick2,
|
|
1068
|
+
href: _href,
|
|
1069
|
+
...buttonRest
|
|
1070
|
+
} = rest;
|
|
637
1071
|
return /* @__PURE__ */ jsx(
|
|
638
|
-
"
|
|
1072
|
+
"button",
|
|
639
1073
|
{
|
|
1074
|
+
ref,
|
|
1075
|
+
type: type ?? "button",
|
|
640
1076
|
className: classes,
|
|
641
|
-
|
|
1077
|
+
disabled,
|
|
642
1078
|
"aria-current": ariaCurrent,
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
onClick: (e) => {
|
|
646
|
-
if (disabled) {
|
|
647
|
-
e.preventDefault();
|
|
648
|
-
return;
|
|
649
|
-
}
|
|
650
|
-
onClick2?.(e);
|
|
651
|
-
},
|
|
652
|
-
...anchorRest,
|
|
1079
|
+
onClick: onClick2,
|
|
1080
|
+
...buttonRest,
|
|
653
1081
|
children: content
|
|
654
1082
|
}
|
|
655
1083
|
);
|
|
656
1084
|
}
|
|
657
|
-
const {
|
|
1085
|
+
const { onClick, tabIndex, ...tagProps } = anchorRest;
|
|
658
1086
|
return /* @__PURE__ */ jsx(
|
|
659
|
-
|
|
1087
|
+
Tag,
|
|
660
1088
|
{
|
|
661
|
-
|
|
1089
|
+
...tagProps,
|
|
1090
|
+
ref,
|
|
662
1091
|
className: classes,
|
|
663
|
-
disabled,
|
|
664
1092
|
"aria-current": ariaCurrent,
|
|
665
|
-
|
|
666
|
-
|
|
1093
|
+
"aria-disabled": disabled ? "true" : void 0,
|
|
1094
|
+
tabIndex: disabled ? -1 : tabIndex,
|
|
1095
|
+
onClick: (event) => {
|
|
1096
|
+
if (disabled) {
|
|
1097
|
+
event.preventDefault();
|
|
1098
|
+
event.stopPropagation();
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
onClick?.(event);
|
|
1102
|
+
},
|
|
667
1103
|
children: content
|
|
668
1104
|
}
|
|
669
1105
|
);
|
|
@@ -674,10 +1110,12 @@ var BottomNavSpacer = ({ className, ...props }) => {
|
|
|
674
1110
|
var Breadcrumb = ({
|
|
675
1111
|
items,
|
|
676
1112
|
separator,
|
|
677
|
-
navLabel
|
|
1113
|
+
navLabel: navLabelProp,
|
|
678
1114
|
className,
|
|
679
1115
|
...props
|
|
680
1116
|
}) => {
|
|
1117
|
+
const t = useLocaleText();
|
|
1118
|
+
const navLabel = navLabelProp ?? t("breadcrumb.label");
|
|
681
1119
|
const sep = separator ?? /* @__PURE__ */ jsx(ChevronRight, { size: iconSize.xs, "aria-hidden": "true" });
|
|
682
1120
|
return /* @__PURE__ */ jsx("nav", { "aria-label": navLabel, className: cn("breadcrumb", className), ...props, children: /* @__PURE__ */ jsx("ol", { className: "breadcrumb_list", children: items.map((item, idx) => {
|
|
683
1121
|
const isLast = idx === items.length - 1;
|
|
@@ -1018,7 +1456,7 @@ var Sidebar = ({
|
|
|
1018
1456
|
defaultCollapsed = false,
|
|
1019
1457
|
onCollapsedChange,
|
|
1020
1458
|
collapsible = true,
|
|
1021
|
-
toggleLabel
|
|
1459
|
+
toggleLabel: toggleLabelProp,
|
|
1022
1460
|
width = 240,
|
|
1023
1461
|
collapsedWidth = 64,
|
|
1024
1462
|
mode = "auto",
|
|
@@ -1027,6 +1465,8 @@ var Sidebar = ({
|
|
|
1027
1465
|
style,
|
|
1028
1466
|
...props
|
|
1029
1467
|
}) => {
|
|
1468
|
+
const t = useLocaleText();
|
|
1469
|
+
const toggleLabel = toggleLabelProp ?? t("sidebar.toggle");
|
|
1030
1470
|
const isControlled = collapsedProp !== void 0;
|
|
1031
1471
|
const [internalCollapsed, setInternalCollapsed] = React11.useState(defaultCollapsed);
|
|
1032
1472
|
const collapsed = isControlled ? collapsedProp : internalCollapsed;
|
|
@@ -1070,20 +1510,61 @@ var Sidebar = ({
|
|
|
1070
1510
|
);
|
|
1071
1511
|
};
|
|
1072
1512
|
var SidebarItem = (props) => {
|
|
1073
|
-
const { icon, active, trailing, as
|
|
1074
|
-
const classes = cn(
|
|
1513
|
+
const { icon, active, trailing, as, className, children, disabled, ref, ...rest } = props;
|
|
1514
|
+
const classes = cn(
|
|
1515
|
+
"sidebar_item",
|
|
1516
|
+
active && "sidebar_item_active",
|
|
1517
|
+
disabled && "sidebar_item_disabled",
|
|
1518
|
+
className
|
|
1519
|
+
);
|
|
1075
1520
|
const ariaCurrent = active ? "page" : void 0;
|
|
1521
|
+
const anchorRest = rest;
|
|
1522
|
+
const Tag = as ?? (anchorRest.href != null ? "a" : "button");
|
|
1076
1523
|
const inner = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1077
1524
|
icon && /* @__PURE__ */ jsx("span", { className: "sidebar_item_icon", "aria-hidden": "true", children: icon }),
|
|
1078
1525
|
/* @__PURE__ */ jsx("span", { className: "sidebar_item_label", children }),
|
|
1079
1526
|
trailing && /* @__PURE__ */ jsx("span", { className: "sidebar_item_trailing", children: trailing })
|
|
1080
1527
|
] });
|
|
1081
|
-
if (
|
|
1082
|
-
const {
|
|
1083
|
-
|
|
1528
|
+
if (Tag === "button") {
|
|
1529
|
+
const {
|
|
1530
|
+
type,
|
|
1531
|
+
href: _href,
|
|
1532
|
+
...buttonRest
|
|
1533
|
+
} = rest;
|
|
1534
|
+
return /* @__PURE__ */ jsx(
|
|
1535
|
+
"button",
|
|
1536
|
+
{
|
|
1537
|
+
ref,
|
|
1538
|
+
type: type ?? "button",
|
|
1539
|
+
className: classes,
|
|
1540
|
+
disabled,
|
|
1541
|
+
"aria-current": ariaCurrent,
|
|
1542
|
+
...buttonRest,
|
|
1543
|
+
children: inner
|
|
1544
|
+
}
|
|
1545
|
+
);
|
|
1084
1546
|
}
|
|
1085
|
-
const {
|
|
1086
|
-
return /* @__PURE__ */ jsx(
|
|
1547
|
+
const { onClick, tabIndex, ...tagProps } = anchorRest;
|
|
1548
|
+
return /* @__PURE__ */ jsx(
|
|
1549
|
+
Tag,
|
|
1550
|
+
{
|
|
1551
|
+
...tagProps,
|
|
1552
|
+
ref,
|
|
1553
|
+
className: classes,
|
|
1554
|
+
"aria-current": ariaCurrent,
|
|
1555
|
+
"aria-disabled": disabled || void 0,
|
|
1556
|
+
tabIndex: disabled ? -1 : tabIndex,
|
|
1557
|
+
onClick: (event) => {
|
|
1558
|
+
if (disabled) {
|
|
1559
|
+
event.preventDefault();
|
|
1560
|
+
event.stopPropagation();
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
onClick?.(event);
|
|
1564
|
+
},
|
|
1565
|
+
children: inner
|
|
1566
|
+
}
|
|
1567
|
+
);
|
|
1087
1568
|
};
|
|
1088
1569
|
var SidebarSection = ({ label, className, children, ...props }) => {
|
|
1089
1570
|
return /* @__PURE__ */ jsxs("div", { className: cn("sidebar_section", className), ...props, children: [
|
|
@@ -2103,7 +2584,8 @@ var Chip = ({
|
|
|
2103
2584
|
className,
|
|
2104
2585
|
...props
|
|
2105
2586
|
}) => {
|
|
2106
|
-
const
|
|
2587
|
+
const t = useLocaleText();
|
|
2588
|
+
const removeAriaLabel = removeLabel ?? t("chip.remove", { label: String(label) });
|
|
2107
2589
|
const [iconHovered, setIconHovered] = useState(false);
|
|
2108
2590
|
const isStatic = type === "static";
|
|
2109
2591
|
const hasLeading = !isStatic && selected;
|
|
@@ -2200,252 +2682,382 @@ var Chip = ({
|
|
|
2200
2682
|
)
|
|
2201
2683
|
] });
|
|
2202
2684
|
};
|
|
2203
|
-
var
|
|
2204
|
-
|
|
2205
|
-
return
|
|
2206
|
-
}
|
|
2207
|
-
var
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
as,
|
|
2218
|
-
className,
|
|
2219
|
-
children,
|
|
2220
|
-
ref,
|
|
2221
|
-
...rest
|
|
2222
|
-
} = props;
|
|
2223
|
-
const buttonClassName = cn(
|
|
2224
|
-
"button",
|
|
2225
|
-
`button_variant_${variant}`,
|
|
2226
|
-
`button_size_${size}`,
|
|
2227
|
-
fullWidth && "button_full_width",
|
|
2228
|
-
radius2 && `button_radius_${radius2}`,
|
|
2229
|
-
danger && "button_danger",
|
|
2230
|
-
// anchor 엔 native :disabled 가 안 먹으므로 클래스로 비활성 스타일 적용 (button 도 무해)
|
|
2231
|
-
disabled && "button_disabled",
|
|
2232
|
-
className
|
|
2233
|
-
);
|
|
2234
|
-
const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2235
|
-
leadingIcon && /* @__PURE__ */ jsx("span", { className: "button_icon", "aria-hidden": "true", children: leadingIcon }),
|
|
2236
|
-
children && /* @__PURE__ */ jsx("span", { className: "button_label", children }),
|
|
2237
|
-
trailingIcon && /* @__PURE__ */ jsx("span", { className: "button_icon", "aria-hidden": "true", children: trailingIcon })
|
|
2238
|
-
] });
|
|
2239
|
-
const anchorRest = rest;
|
|
2240
|
-
const renderAnchor = as === "a" || as === void 0 && anchorRest.href != null;
|
|
2241
|
-
if (renderAnchor) {
|
|
2242
|
-
const { onClick, tabIndex, ...anchorProps } = anchorRest;
|
|
2243
|
-
return /* @__PURE__ */ jsx(
|
|
2244
|
-
"a",
|
|
2245
|
-
{
|
|
2246
|
-
...anchorProps,
|
|
2247
|
-
ref,
|
|
2248
|
-
className: buttonClassName,
|
|
2249
|
-
"aria-disabled": disabled || void 0,
|
|
2250
|
-
tabIndex: disabled ? -1 : tabIndex,
|
|
2251
|
-
onClick: disabled ? (e) => e.preventDefault() : onClick,
|
|
2252
|
-
children: content
|
|
2253
|
-
}
|
|
2254
|
-
);
|
|
2685
|
+
var FormContext = createContext(void 0);
|
|
2686
|
+
function useFormError(name) {
|
|
2687
|
+
return useContext(FormContext)?.errors?.[name];
|
|
2688
|
+
}
|
|
2689
|
+
var Form = ({ errors, onSubmit, children, className, ...props }) => /* @__PURE__ */ jsx(FormContext.Provider, { value: { errors }, children: /* @__PURE__ */ jsx(
|
|
2690
|
+
"form",
|
|
2691
|
+
{
|
|
2692
|
+
className: cn("form", className),
|
|
2693
|
+
onSubmit: (event) => {
|
|
2694
|
+
event.preventDefault();
|
|
2695
|
+
onSubmit?.(event);
|
|
2696
|
+
},
|
|
2697
|
+
...props,
|
|
2698
|
+
children
|
|
2255
2699
|
}
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
action,
|
|
2271
|
-
variant
|
|
2272
|
-
}) => action.href ? /* @__PURE__ */ jsx(Button, { as: "a", href: action.href, size: "lg", variant, onClick: action.onClick, children: action.label }) : /* @__PURE__ */ jsx(Button, { size: "lg", variant, onClick: action.onClick, children: action.label });
|
|
2273
|
-
var Hero = ({
|
|
2274
|
-
height = "md",
|
|
2275
|
-
align = "left",
|
|
2276
|
-
backgroundImage,
|
|
2277
|
-
backgroundColor,
|
|
2278
|
-
overlay,
|
|
2279
|
-
title,
|
|
2280
|
-
subtitle,
|
|
2281
|
-
eyebrow,
|
|
2282
|
-
textColor = "auto",
|
|
2283
|
-
primaryAction,
|
|
2284
|
-
secondaryAction,
|
|
2700
|
+
) });
|
|
2701
|
+
var FormActions = ({ align = "end", children, className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("form_actions", `form_actions_${align}`, className), ...props, children });
|
|
2702
|
+
FormActions.displayName = "Form.Actions";
|
|
2703
|
+
Form.Actions = FormActions;
|
|
2704
|
+
var FieldContext = createContext(void 0);
|
|
2705
|
+
function useFieldControl() {
|
|
2706
|
+
return useContext(FieldContext);
|
|
2707
|
+
}
|
|
2708
|
+
var Field = ({
|
|
2709
|
+
name,
|
|
2710
|
+
label,
|
|
2711
|
+
required = false,
|
|
2712
|
+
help,
|
|
2713
|
+
error: errorProp,
|
|
2285
2714
|
children,
|
|
2286
2715
|
className,
|
|
2287
|
-
style,
|
|
2288
2716
|
...props
|
|
2289
2717
|
}) => {
|
|
2290
|
-
const
|
|
2291
|
-
const
|
|
2292
|
-
const
|
|
2293
|
-
const
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
/* @__PURE__ */ jsxs("
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
children
|
|
2314
|
-
] })
|
|
2315
|
-
] })
|
|
2718
|
+
const generatedId = useId();
|
|
2719
|
+
const inputId = `${name}-${generatedId}`;
|
|
2720
|
+
const formError = useFormError(name);
|
|
2721
|
+
const error = errorProp ?? formError;
|
|
2722
|
+
const labelId = label ? `${inputId}-label` : void 0;
|
|
2723
|
+
const helpId = help ? `${inputId}-help` : void 0;
|
|
2724
|
+
const errorId = error ? `${inputId}-error` : void 0;
|
|
2725
|
+
const showHelp = !error && !!help;
|
|
2726
|
+
const control = {
|
|
2727
|
+
inputId,
|
|
2728
|
+
labelId,
|
|
2729
|
+
describedBy: [errorId, showHelp ? helpId : void 0].filter(Boolean).join(" ") || void 0,
|
|
2730
|
+
invalid: !!error,
|
|
2731
|
+
required
|
|
2732
|
+
};
|
|
2733
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("field", !!error && "field_error", className), ...props, children: [
|
|
2734
|
+
label && /* @__PURE__ */ jsxs("label", { id: labelId, htmlFor: inputId, className: "field_label", children: [
|
|
2735
|
+
label,
|
|
2736
|
+
required && /* @__PURE__ */ jsx("span", { className: "field_required", "aria-hidden": "true", children: "*" })
|
|
2737
|
+
] }),
|
|
2738
|
+
/* @__PURE__ */ jsx(FieldContext.Provider, { value: control, children }),
|
|
2739
|
+
showHelp && /* @__PURE__ */ jsx("div", { id: helpId, className: "field_help", children: help }),
|
|
2740
|
+
error && /* @__PURE__ */ jsx("div", { id: errorId, className: "field_message", children: error })
|
|
2316
2741
|
] });
|
|
2317
2742
|
};
|
|
2318
|
-
var
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
IconComponent,
|
|
2322
|
-
{
|
|
2323
|
-
"aria-hidden": hasLabel ? void 0 : true,
|
|
2324
|
-
focusable: hasLabel ? void 0 : false,
|
|
2325
|
-
...props
|
|
2326
|
-
}
|
|
2327
|
-
);
|
|
2328
|
-
};
|
|
2329
|
-
Icon.displayName = "Icon";
|
|
2330
|
-
var ListItem = ({
|
|
2331
|
-
overline,
|
|
2743
|
+
var ClearIcon = () => /* @__PURE__ */ jsx(X, { size: iconSize.lg, "aria-hidden": "true" });
|
|
2744
|
+
var TextField = ({
|
|
2745
|
+
id,
|
|
2332
2746
|
label,
|
|
2747
|
+
showLabel = true,
|
|
2333
2748
|
supportingText,
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2749
|
+
error,
|
|
2750
|
+
success,
|
|
2751
|
+
identifier,
|
|
2752
|
+
leadingIcon,
|
|
2753
|
+
trailingIcon,
|
|
2754
|
+
leadingAction,
|
|
2755
|
+
trailingAction,
|
|
2756
|
+
showPasswordToggle,
|
|
2757
|
+
passwordToggleLabels,
|
|
2758
|
+
clearable,
|
|
2759
|
+
clearLabel: clearLabelProp,
|
|
2760
|
+
type,
|
|
2761
|
+
fullWidth,
|
|
2762
|
+
size = "md",
|
|
2763
|
+
variant = "outline",
|
|
2341
2764
|
className,
|
|
2765
|
+
onValueChange,
|
|
2766
|
+
onChangeAction,
|
|
2767
|
+
imeStrategy = "delayed",
|
|
2768
|
+
value,
|
|
2769
|
+
defaultValue,
|
|
2770
|
+
transformValue,
|
|
2771
|
+
ref,
|
|
2342
2772
|
...props
|
|
2343
2773
|
}) => {
|
|
2344
|
-
const
|
|
2345
|
-
const
|
|
2774
|
+
const t = useLocaleText();
|
|
2775
|
+
const clearLabel = clearLabelProp ?? t("textField.clear");
|
|
2776
|
+
const generatedId = useId();
|
|
2777
|
+
const field = useFieldControl();
|
|
2778
|
+
const inputId = id ?? field?.inputId ?? generatedId;
|
|
2779
|
+
const helperId = supportingText ? `${inputId}-help` : void 0;
|
|
2780
|
+
const describedBy = field?.describedBy ?? helperId;
|
|
2781
|
+
const isControlled = value !== void 0;
|
|
2782
|
+
const applyTransform = (nextValue) => transformValue ? transformValue(nextValue) : nextValue;
|
|
2783
|
+
const [innerValue, setInnerValue] = useState(() => applyTransform(value ?? defaultValue ?? ""));
|
|
2784
|
+
const isComposingRef = useRef(false);
|
|
2785
|
+
const lastEmittedValueRef = useRef(innerValue);
|
|
2786
|
+
const [prevValue, setPrevValue] = useState(value);
|
|
2787
|
+
if (isControlled && value !== prevValue && !isComposingRef.current) {
|
|
2788
|
+
setPrevValue(value);
|
|
2789
|
+
const nextValue = applyTransform(value ?? "");
|
|
2790
|
+
setInnerValue(nextValue);
|
|
2791
|
+
lastEmittedValueRef.current = nextValue;
|
|
2792
|
+
}
|
|
2793
|
+
const emit = useCallback(
|
|
2794
|
+
(nextValue) => {
|
|
2795
|
+
setInnerValue(nextValue);
|
|
2796
|
+
if (nextValue !== lastEmittedValueRef.current) {
|
|
2797
|
+
lastEmittedValueRef.current = nextValue;
|
|
2798
|
+
(onValueChange ?? onChangeAction)?.(nextValue);
|
|
2799
|
+
}
|
|
2800
|
+
},
|
|
2801
|
+
[onValueChange, onChangeAction]
|
|
2802
|
+
);
|
|
2803
|
+
const handleClear = useCallback(() => {
|
|
2804
|
+
emit("");
|
|
2805
|
+
}, [emit]);
|
|
2806
|
+
const [passwordRevealed, setPasswordRevealed] = useState(false);
|
|
2807
|
+
const togglePassword = useCallback(() => {
|
|
2808
|
+
setPasswordRevealed((revealed) => !revealed);
|
|
2809
|
+
}, []);
|
|
2810
|
+
let resolvedType = type;
|
|
2811
|
+
if (showPasswordToggle) {
|
|
2812
|
+
resolvedType = passwordRevealed ? "text" : type ?? "password";
|
|
2813
|
+
}
|
|
2814
|
+
const isError = !!error || !!field?.invalid;
|
|
2815
|
+
const isSuccess = !!success && !isError;
|
|
2346
2816
|
const rootClassName = cn(
|
|
2347
|
-
"
|
|
2348
|
-
`
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2817
|
+
"text_field",
|
|
2818
|
+
`text_field_variant_${variant}`,
|
|
2819
|
+
size === "sm" && "text_field_size_sm",
|
|
2820
|
+
size === "lg" && "text_field_size_lg",
|
|
2821
|
+
fullWidth && "text_field_full_width",
|
|
2822
|
+
isError && "text_field_error",
|
|
2823
|
+
isSuccess && "text_field_success",
|
|
2824
|
+
props.disabled && "text_field_disabled",
|
|
2352
2825
|
className
|
|
2353
2826
|
);
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2827
|
+
const passwordToggleLabel = passwordRevealed ? passwordToggleLabels?.hide ?? t("textField.passwordHide") : passwordToggleLabels?.show ?? t("textField.passwordShow");
|
|
2828
|
+
const resolvedTrailing = showPasswordToggle ? /* @__PURE__ */ jsx("span", { className: "text_field_icon text_field_action", children: /* @__PURE__ */ jsx(
|
|
2829
|
+
"button",
|
|
2830
|
+
{
|
|
2831
|
+
type: "button",
|
|
2832
|
+
onClick: togglePassword,
|
|
2833
|
+
"aria-label": passwordToggleLabel,
|
|
2834
|
+
disabled: props.disabled,
|
|
2835
|
+
children: passwordRevealed ? /* @__PURE__ */ jsx(EyeOff, { size: iconSize.lg, "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Eye, { size: iconSize.lg, "aria-hidden": "true" })
|
|
2836
|
+
}
|
|
2837
|
+
) }) : clearable && innerValue ? /* @__PURE__ */ jsx(
|
|
2838
|
+
"button",
|
|
2839
|
+
{
|
|
2840
|
+
type: "button",
|
|
2841
|
+
className: "text_field_clear",
|
|
2842
|
+
onClick: handleClear,
|
|
2843
|
+
"aria-label": clearLabel,
|
|
2844
|
+
disabled: props.disabled,
|
|
2845
|
+
children: /* @__PURE__ */ jsx(ClearIcon, {})
|
|
2846
|
+
}
|
|
2847
|
+
) : trailingAction ? /* @__PURE__ */ jsx("span", { className: "text_field_icon text_field_action", children: trailingAction }) : trailingIcon ? /* @__PURE__ */ jsx("span", { className: "text_field_icon", "aria-hidden": "true", children: trailingIcon }) : null;
|
|
2848
|
+
const resolvedLeading = leadingAction ? /* @__PURE__ */ jsx("span", { className: "text_field_icon text_field_action", children: leadingAction }) : leadingIcon ? /* @__PURE__ */ jsx("span", { className: "text_field_icon", "aria-hidden": "true", children: leadingIcon }) : null;
|
|
2849
|
+
return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
|
|
2850
|
+
label && showLabel && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "text_field_label", children: label }),
|
|
2851
|
+
/* @__PURE__ */ jsx("div", { className: "text_field_container", children: /* @__PURE__ */ jsxs("div", { className: "text_field_inner", children: [
|
|
2852
|
+
resolvedLeading,
|
|
2853
|
+
/* @__PURE__ */ jsx(
|
|
2854
|
+
"div",
|
|
2855
|
+
{
|
|
2856
|
+
className: cn(
|
|
2857
|
+
"text_field_input_wrap",
|
|
2858
|
+
resolvedTrailing && "text_field_input_wrap_no_pad_right"
|
|
2859
|
+
),
|
|
2860
|
+
children: /* @__PURE__ */ jsx(
|
|
2861
|
+
"input",
|
|
2862
|
+
{
|
|
2863
|
+
id: inputId,
|
|
2864
|
+
ref,
|
|
2865
|
+
className: cn("text_field_input", identifier && "text_field_input_identifier"),
|
|
2866
|
+
"aria-invalid": isError,
|
|
2867
|
+
"aria-describedby": describedBy,
|
|
2868
|
+
"aria-required": field?.required || void 0,
|
|
2869
|
+
"aria-label": !showLabel ? label : void 0,
|
|
2870
|
+
...props,
|
|
2871
|
+
type: resolvedType,
|
|
2872
|
+
value: innerValue,
|
|
2873
|
+
onCompositionStart: () => {
|
|
2874
|
+
isComposingRef.current = true;
|
|
2875
|
+
},
|
|
2876
|
+
onCompositionEnd: (event) => {
|
|
2877
|
+
isComposingRef.current = false;
|
|
2878
|
+
emit(applyTransform(event.currentTarget.value));
|
|
2879
|
+
},
|
|
2880
|
+
onChange: (event) => {
|
|
2881
|
+
const rawValue = event.target.value;
|
|
2882
|
+
if (isComposingRef.current) {
|
|
2883
|
+
setInnerValue(rawValue);
|
|
2884
|
+
if (imeStrategy === "immediate" && rawValue !== lastEmittedValueRef.current) {
|
|
2885
|
+
lastEmittedValueRef.current = rawValue;
|
|
2886
|
+
(onValueChange ?? onChangeAction)?.(rawValue);
|
|
2887
|
+
}
|
|
2888
|
+
return;
|
|
2889
|
+
}
|
|
2890
|
+
emit(applyTransform(rawValue));
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
)
|
|
2894
|
+
}
|
|
2895
|
+
),
|
|
2896
|
+
resolvedTrailing
|
|
2897
|
+
] }) }),
|
|
2898
|
+
supportingText && /* @__PURE__ */ jsx("div", { id: helperId, className: "text_field_helper", children: supportingText })
|
|
2899
|
+
] });
|
|
2386
2900
|
};
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2901
|
+
TextField.displayName = "TextField";
|
|
2902
|
+
var Button = (props) => {
|
|
2903
|
+
const {
|
|
2904
|
+
variant = "filled",
|
|
2905
|
+
size = "md",
|
|
2906
|
+
leadingIcon,
|
|
2907
|
+
trailingIcon,
|
|
2908
|
+
fullWidth = false,
|
|
2909
|
+
radius: radius2,
|
|
2910
|
+
danger = false,
|
|
2911
|
+
disabled = false,
|
|
2912
|
+
as,
|
|
2913
|
+
className,
|
|
2914
|
+
children,
|
|
2915
|
+
ref,
|
|
2916
|
+
...rest
|
|
2917
|
+
} = props;
|
|
2918
|
+
const buttonClassName = cn(
|
|
2919
|
+
"button",
|
|
2920
|
+
`button_variant_${variant}`,
|
|
2921
|
+
`button_size_${size}`,
|
|
2922
|
+
fullWidth && "button_full_width",
|
|
2923
|
+
radius2 && `button_radius_${radius2}`,
|
|
2924
|
+
danger && "button_danger",
|
|
2925
|
+
// anchor 엔 native :disabled 가 안 먹으므로 클래스로 비활성 스타일 적용 (button 도 무해)
|
|
2926
|
+
disabled && "button_disabled",
|
|
2408
2927
|
className
|
|
2409
2928
|
);
|
|
2410
|
-
const
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
/* @__PURE__ */ jsxs("div", { className: "media_card_image_wrap", style: wrapStyle, children: [
|
|
2415
|
-
/* @__PURE__ */ jsx("img", { className: "media_card_image", src: image.src, alt: image.alt, loading: "lazy" }),
|
|
2416
|
-
isOverlay && /* @__PURE__ */ jsx("div", { className: "media_card_overlay", "aria-hidden": "true" })
|
|
2417
|
-
] }),
|
|
2418
|
-
/* @__PURE__ */ jsxs("div", { className: "media_card_body", children: [
|
|
2419
|
-
eyebrow && /* @__PURE__ */ jsx("div", { className: "media_card_eyebrow", children: eyebrow }),
|
|
2420
|
-
heading && /* @__PURE__ */ jsx(HeadingTag, { className: "media_card_heading", children: heading }),
|
|
2421
|
-
children && /* @__PURE__ */ jsx("div", { className: "media_card_content", children }),
|
|
2422
|
-
meta && /* @__PURE__ */ jsx("div", { className: "media_card_meta", children: meta })
|
|
2423
|
-
] })
|
|
2929
|
+
const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2930
|
+
leadingIcon && /* @__PURE__ */ jsx("span", { className: "button_icon", "aria-hidden": "true", children: leadingIcon }),
|
|
2931
|
+
children && /* @__PURE__ */ jsx("span", { className: "button_label", children }),
|
|
2932
|
+
trailingIcon && /* @__PURE__ */ jsx("span", { className: "button_icon", "aria-hidden": "true", children: trailingIcon })
|
|
2424
2933
|
] });
|
|
2934
|
+
const anchorRest = rest;
|
|
2935
|
+
const Tag = as ?? (anchorRest.href != null ? "a" : "button");
|
|
2936
|
+
if (Tag === "button") {
|
|
2937
|
+
const {
|
|
2938
|
+
type = "button",
|
|
2939
|
+
href: _href,
|
|
2940
|
+
...buttonRest
|
|
2941
|
+
} = rest;
|
|
2942
|
+
return /* @__PURE__ */ jsx(
|
|
2943
|
+
"button",
|
|
2944
|
+
{
|
|
2945
|
+
ref,
|
|
2946
|
+
type,
|
|
2947
|
+
disabled,
|
|
2948
|
+
className: buttonClassName,
|
|
2949
|
+
...buttonRest,
|
|
2950
|
+
children: content
|
|
2951
|
+
}
|
|
2952
|
+
);
|
|
2953
|
+
}
|
|
2954
|
+
const { onClick, tabIndex, ...tagProps } = anchorRest;
|
|
2955
|
+
return /* @__PURE__ */ jsx(
|
|
2956
|
+
Tag,
|
|
2957
|
+
{
|
|
2958
|
+
...tagProps,
|
|
2959
|
+
ref,
|
|
2960
|
+
className: buttonClassName,
|
|
2961
|
+
"aria-disabled": disabled || void 0,
|
|
2962
|
+
tabIndex: disabled ? -1 : tabIndex,
|
|
2963
|
+
onClick: disabled ? (event) => {
|
|
2964
|
+
event.preventDefault();
|
|
2965
|
+
event.stopPropagation();
|
|
2966
|
+
} : onClick,
|
|
2967
|
+
children: content
|
|
2968
|
+
}
|
|
2969
|
+
);
|
|
2425
2970
|
};
|
|
2426
|
-
var
|
|
2427
|
-
const
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2971
|
+
var range = (start, end) => {
|
|
2972
|
+
const out = [];
|
|
2973
|
+
for (let i = start; i <= end; i += 1) out.push(i);
|
|
2974
|
+
return out;
|
|
2975
|
+
};
|
|
2976
|
+
var getPaginationItems = (page, totalPages) => {
|
|
2977
|
+
if (totalPages <= 7) return range(1, totalPages);
|
|
2978
|
+
const items = [];
|
|
2979
|
+
const last = totalPages;
|
|
2980
|
+
const sibling = 2;
|
|
2981
|
+
if (page <= sibling + 2) {
|
|
2982
|
+
for (const p of range(1, sibling + 3)) items.push(p);
|
|
2983
|
+
items.push("ellipsis");
|
|
2984
|
+
items.push(last);
|
|
2985
|
+
return items;
|
|
2986
|
+
}
|
|
2987
|
+
if (page >= last - sibling - 1) {
|
|
2988
|
+
items.push(1);
|
|
2989
|
+
items.push("ellipsis");
|
|
2990
|
+
for (const p of range(last - sibling - 2, last)) items.push(p);
|
|
2991
|
+
return items;
|
|
2992
|
+
}
|
|
2993
|
+
items.push(1);
|
|
2994
|
+
items.push("ellipsis");
|
|
2995
|
+
for (const p of range(page - sibling, page + sibling)) items.push(p);
|
|
2996
|
+
items.push("ellipsis");
|
|
2997
|
+
items.push(last);
|
|
2998
|
+
return items;
|
|
2999
|
+
};
|
|
3000
|
+
var Pagination = ({
|
|
3001
|
+
page,
|
|
3002
|
+
totalPages,
|
|
3003
|
+
onPageChange,
|
|
3004
|
+
onChange,
|
|
3005
|
+
prevLabel: prevLabelProp,
|
|
3006
|
+
nextLabel: nextLabelProp,
|
|
3007
|
+
navLabel: navLabelProp
|
|
3008
|
+
}) => {
|
|
3009
|
+
const t = useLocaleText();
|
|
3010
|
+
const prevLabel = prevLabelProp ?? t("pagination.prev");
|
|
3011
|
+
const nextLabel = nextLabelProp ?? t("pagination.next");
|
|
3012
|
+
const navLabel = navLabelProp ?? t("pagination.label");
|
|
3013
|
+
const emit = onPageChange ?? onChange;
|
|
3014
|
+
const prevDisabled = page <= 1;
|
|
3015
|
+
const nextDisabled = page >= totalPages;
|
|
3016
|
+
const items = React11.useMemo(() => getPaginationItems(page, totalPages), [page, totalPages]);
|
|
3017
|
+
return /* @__PURE__ */ jsxs("nav", { className: "pagination", "aria-label": navLabel, children: [
|
|
3018
|
+
/* @__PURE__ */ jsx(
|
|
3019
|
+
"button",
|
|
3020
|
+
{
|
|
3021
|
+
type: "button",
|
|
3022
|
+
className: "pagination_item",
|
|
3023
|
+
onClick: () => emit?.(page - 1),
|
|
3024
|
+
disabled: prevDisabled,
|
|
3025
|
+
"aria-label": prevLabel,
|
|
3026
|
+
children: "\u2039"
|
|
2437
3027
|
}
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
3028
|
+
),
|
|
3029
|
+
/* @__PURE__ */ jsx("ul", { className: "pagination_pages", children: items.map((it, idx) => {
|
|
3030
|
+
if (it === "ellipsis") {
|
|
3031
|
+
const prev = items[idx - 1];
|
|
3032
|
+
const next = items[idx + 1];
|
|
3033
|
+
return /* @__PURE__ */ jsx("li", { className: "pagination_ellipsis", "aria-hidden": "true", children: "\u2026" }, `e-${prev}-${next}`);
|
|
3034
|
+
}
|
|
3035
|
+
const isActive = it === page;
|
|
3036
|
+
const buttonClassName = cn("pagination_page_button", { pagination_active: isActive });
|
|
3037
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
3038
|
+
"button",
|
|
3039
|
+
{
|
|
3040
|
+
type: "button",
|
|
3041
|
+
className: buttonClassName,
|
|
3042
|
+
onClick: () => emit?.(it),
|
|
3043
|
+
"aria-current": isActive ? "page" : void 0,
|
|
3044
|
+
children: it
|
|
3045
|
+
}
|
|
3046
|
+
) }, it);
|
|
3047
|
+
}) }),
|
|
3048
|
+
/* @__PURE__ */ jsx(
|
|
3049
|
+
"button",
|
|
3050
|
+
{
|
|
3051
|
+
type: "button",
|
|
3052
|
+
className: "pagination_item",
|
|
3053
|
+
onClick: () => emit?.(page + 1),
|
|
3054
|
+
disabled: nextDisabled,
|
|
3055
|
+
"aria-label": nextLabel,
|
|
3056
|
+
children: "\u203A"
|
|
3057
|
+
}
|
|
3058
|
+
)
|
|
3059
|
+
] });
|
|
2447
3060
|
};
|
|
2448
|
-
Prose.displayName = "Prose";
|
|
2449
3061
|
var Skeleton = ({
|
|
2450
3062
|
variant = "text",
|
|
2451
3063
|
width,
|
|
@@ -2496,6 +3108,7 @@ var Checkbox = ({
|
|
|
2496
3108
|
props.disabled && "checkbox_disabled",
|
|
2497
3109
|
className
|
|
2498
3110
|
);
|
|
3111
|
+
const field = useFieldControl();
|
|
2499
3112
|
return /* @__PURE__ */ jsxs("label", { className: rootClassName, children: [
|
|
2500
3113
|
/* @__PURE__ */ jsx(
|
|
2501
3114
|
"input",
|
|
@@ -2504,6 +3117,9 @@ var Checkbox = ({
|
|
|
2504
3117
|
ref: inputRef,
|
|
2505
3118
|
type: "checkbox",
|
|
2506
3119
|
className: "checkbox_input",
|
|
3120
|
+
id: field?.inputId ?? props.id,
|
|
3121
|
+
"aria-describedby": field?.describedBy ?? props["aria-describedby"],
|
|
3122
|
+
"aria-required": field?.required || void 0,
|
|
2507
3123
|
"aria-invalid": error || void 0
|
|
2508
3124
|
}
|
|
2509
3125
|
),
|
|
@@ -2516,7 +3132,7 @@ var Table = ({
|
|
|
2516
3132
|
columns,
|
|
2517
3133
|
data,
|
|
2518
3134
|
keyExtractor,
|
|
2519
|
-
emptyMessage
|
|
3135
|
+
emptyMessage: emptyMessageProp,
|
|
2520
3136
|
isLoading = false,
|
|
2521
3137
|
skeletonRows = 5,
|
|
2522
3138
|
size = "md",
|
|
@@ -2525,16 +3141,21 @@ var Table = ({
|
|
|
2525
3141
|
ariaLabel,
|
|
2526
3142
|
className,
|
|
2527
3143
|
onRowClick,
|
|
2528
|
-
rowClickHint
|
|
3144
|
+
rowClickHint: rowClickHintProp,
|
|
2529
3145
|
sort,
|
|
2530
3146
|
onSortChange,
|
|
2531
|
-
selectAllAriaLabel
|
|
2532
|
-
selectRowAriaLabel
|
|
3147
|
+
selectAllAriaLabel: selectAllAriaLabelProp,
|
|
3148
|
+
selectRowAriaLabel: selectRowAriaLabelProp,
|
|
2533
3149
|
selectable = false,
|
|
2534
3150
|
rowKey,
|
|
2535
3151
|
selectedKeys,
|
|
2536
3152
|
onSelectionChange
|
|
2537
3153
|
}) => {
|
|
3154
|
+
const t = useLocaleText();
|
|
3155
|
+
const rowClickHint = rowClickHintProp ?? t("table.rowClickHint");
|
|
3156
|
+
const emptyMessage = emptyMessageProp === void 0 ? t("table.empty") : emptyMessageProp;
|
|
3157
|
+
const selectAllAriaLabel = selectAllAriaLabelProp ?? t("table.selectAll");
|
|
3158
|
+
const selectRowAriaLabel = selectRowAriaLabelProp ?? ((index) => t("table.selectRow", { index: index + 1 }));
|
|
2538
3159
|
const wrapperClassName = cn(
|
|
2539
3160
|
"table_wrapper",
|
|
2540
3161
|
`table_size_${size}`,
|
|
@@ -2702,10 +3323,312 @@ var Table = ({
|
|
|
2702
3323
|
);
|
|
2703
3324
|
}) })
|
|
2704
3325
|
] }),
|
|
2705
|
-
onRowClick && rowClickHint && /* @__PURE__ */ jsx("span", { id: rowClickHintId, className: "table_sr_only", children: rowClickHint }),
|
|
2706
|
-
isEmpty && /* @__PURE__ */ jsx("div", { className: "table_empty", role: "status", children: emptyMessage })
|
|
3326
|
+
onRowClick && rowClickHint && /* @__PURE__ */ jsx("span", { id: rowClickHintId, className: "table_sr_only", children: rowClickHint }),
|
|
3327
|
+
isEmpty && /* @__PURE__ */ jsx("div", { className: "table_empty", role: "status", children: emptyMessage })
|
|
3328
|
+
] });
|
|
3329
|
+
};
|
|
3330
|
+
var DataView = ({
|
|
3331
|
+
query,
|
|
3332
|
+
columns,
|
|
3333
|
+
rowKey,
|
|
3334
|
+
toolbar,
|
|
3335
|
+
selectionActions,
|
|
3336
|
+
pagination,
|
|
3337
|
+
empty,
|
|
3338
|
+
sort,
|
|
3339
|
+
onSortChange,
|
|
3340
|
+
onRowClick,
|
|
3341
|
+
ariaLabel,
|
|
3342
|
+
selectionSummary: selectionSummaryProp,
|
|
3343
|
+
clearSelectionLabel: clearSelectionLabelProp,
|
|
3344
|
+
errorTitle: errorTitleProp,
|
|
3345
|
+
retryLabel: retryLabelProp,
|
|
3346
|
+
className,
|
|
3347
|
+
...props
|
|
3348
|
+
}) => {
|
|
3349
|
+
const t = useLocaleText();
|
|
3350
|
+
const selectionSummary = selectionSummaryProp ?? ((count) => t("dataView.selectionSummary", { count }));
|
|
3351
|
+
const clearSelectionLabel = clearSelectionLabelProp ?? t("dataView.clearSelection");
|
|
3352
|
+
const errorTitle = errorTitleProp ?? t("dataView.errorTitle");
|
|
3353
|
+
const retryLabel = retryLabelProp ?? t("dataView.retry");
|
|
3354
|
+
const searchLabel = toolbar?.searchPlaceholder ?? t("dataView.search");
|
|
3355
|
+
const [selectedKeys, setSelectedKeys] = useState([]);
|
|
3356
|
+
const selectionBarId = useId();
|
|
3357
|
+
const selectable = !!selectionActions?.length;
|
|
3358
|
+
const rows = query.data ?? [];
|
|
3359
|
+
const showEmpty = !query.isLoading && !query.error && rows.length === 0;
|
|
3360
|
+
if (query.error) {
|
|
3361
|
+
return /* @__PURE__ */ jsx("div", { className: cn("data_view", className), ...props, children: /* @__PURE__ */ jsx(
|
|
3362
|
+
ErrorState,
|
|
3363
|
+
{
|
|
3364
|
+
variant: "widget",
|
|
3365
|
+
title: errorTitle,
|
|
3366
|
+
action: query.refetch ? /* @__PURE__ */ jsx(Button, { size: "sm", variant: "outline", onClick: query.refetch, children: retryLabel }) : void 0
|
|
3367
|
+
}
|
|
3368
|
+
) });
|
|
3369
|
+
}
|
|
3370
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("data_view", className), ...props, children: [
|
|
3371
|
+
toolbar && /* @__PURE__ */ jsxs("div", { className: "data_view_toolbar", children: [
|
|
3372
|
+
toolbar.search && /* @__PURE__ */ jsx("div", { className: "data_view_search", children: /* @__PURE__ */ jsx(
|
|
3373
|
+
TextField,
|
|
3374
|
+
{
|
|
3375
|
+
fullWidth: true,
|
|
3376
|
+
size: "sm",
|
|
3377
|
+
type: "search",
|
|
3378
|
+
value: toolbar.searchValue,
|
|
3379
|
+
onValueChange: toolbar.onSearchChange,
|
|
3380
|
+
placeholder: searchLabel,
|
|
3381
|
+
"aria-label": searchLabel,
|
|
3382
|
+
leadingIcon: /* @__PURE__ */ jsx(Search, { size: iconSize.sm })
|
|
3383
|
+
}
|
|
3384
|
+
) }),
|
|
3385
|
+
toolbar.filters && /* @__PURE__ */ jsx("div", { className: "data_view_filters", children: toolbar.filters })
|
|
3386
|
+
] }),
|
|
3387
|
+
selectable && selectedKeys.length > 0 && // `role="status"` - 선택이 바뀔 때마다 스크린리더가 개수를 읽는다. 액션 줄이
|
|
3388
|
+
// 시각적으로만 나타나면 키보드 사용자는 무엇이 가능해졌는지 알 수 없다.
|
|
3389
|
+
/* @__PURE__ */ jsxs("div", { id: selectionBarId, className: "data_view_selection", role: "status", children: [
|
|
3390
|
+
/* @__PURE__ */ jsx("span", { className: "data_view_selection_count", children: selectionSummary(selectedKeys.length) }),
|
|
3391
|
+
/* @__PURE__ */ jsxs("div", { className: "data_view_selection_actions", children: [
|
|
3392
|
+
selectionActions?.map((action) => /* @__PURE__ */ jsx(
|
|
3393
|
+
Button,
|
|
3394
|
+
{
|
|
3395
|
+
size: "sm",
|
|
3396
|
+
variant: "outline",
|
|
3397
|
+
danger: action.danger,
|
|
3398
|
+
onClick: () => action.onRun(selectedKeys),
|
|
3399
|
+
children: action.label
|
|
3400
|
+
},
|
|
3401
|
+
action.label
|
|
3402
|
+
)),
|
|
3403
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "text", onClick: () => setSelectedKeys([]), children: clearSelectionLabel })
|
|
3404
|
+
] })
|
|
3405
|
+
] }),
|
|
3406
|
+
showEmpty ? empty ?? /* @__PURE__ */ jsx(EmptyState, { title: t("dataView.empty") }) : selectable ? (
|
|
3407
|
+
// 판별 union 이라 조건부 스프레드로는 좁혀지지 않는다 - 분기를 명시한다.
|
|
3408
|
+
/* @__PURE__ */ jsx(
|
|
3409
|
+
Table,
|
|
3410
|
+
{
|
|
3411
|
+
columns,
|
|
3412
|
+
data: rows,
|
|
3413
|
+
keyExtractor: rowKey,
|
|
3414
|
+
isLoading: query.isLoading,
|
|
3415
|
+
sort,
|
|
3416
|
+
onSortChange,
|
|
3417
|
+
onRowClick,
|
|
3418
|
+
ariaLabel,
|
|
3419
|
+
selectable: true,
|
|
3420
|
+
rowKey,
|
|
3421
|
+
selectedKeys,
|
|
3422
|
+
onSelectionChange: setSelectedKeys
|
|
3423
|
+
}
|
|
3424
|
+
)
|
|
3425
|
+
) : /* @__PURE__ */ jsx(
|
|
3426
|
+
Table,
|
|
3427
|
+
{
|
|
3428
|
+
columns,
|
|
3429
|
+
data: rows,
|
|
3430
|
+
keyExtractor: rowKey,
|
|
3431
|
+
isLoading: query.isLoading,
|
|
3432
|
+
sort,
|
|
3433
|
+
onSortChange,
|
|
3434
|
+
onRowClick,
|
|
3435
|
+
ariaLabel
|
|
3436
|
+
}
|
|
3437
|
+
),
|
|
3438
|
+
pagination && pagination.totalPages > 1 && /* @__PURE__ */ jsx("div", { className: "data_view_pagination", children: /* @__PURE__ */ jsx(
|
|
3439
|
+
Pagination,
|
|
3440
|
+
{
|
|
3441
|
+
page: pagination.page,
|
|
3442
|
+
totalPages: pagination.totalPages,
|
|
3443
|
+
onPageChange: pagination.onPageChange
|
|
3444
|
+
}
|
|
3445
|
+
) })
|
|
3446
|
+
] });
|
|
3447
|
+
};
|
|
3448
|
+
var Divider = ({ weight = "standard", className, ...props }) => {
|
|
3449
|
+
const dividerClassName = cn("divider", `divider_weight_${weight}`, className);
|
|
3450
|
+
return /* @__PURE__ */ jsx("hr", { className: dividerClassName, ...props });
|
|
3451
|
+
};
|
|
3452
|
+
var HeroActionButton = ({
|
|
3453
|
+
action,
|
|
3454
|
+
variant
|
|
3455
|
+
}) => action.href ? /* @__PURE__ */ jsx(Button, { as: "a", href: action.href, size: "lg", variant, onClick: action.onClick, children: action.label }) : /* @__PURE__ */ jsx(Button, { size: "lg", variant, onClick: action.onClick, children: action.label });
|
|
3456
|
+
var Hero = ({
|
|
3457
|
+
height = "md",
|
|
3458
|
+
align = "left",
|
|
3459
|
+
backgroundImage,
|
|
3460
|
+
backgroundColor,
|
|
3461
|
+
overlay,
|
|
3462
|
+
title,
|
|
3463
|
+
subtitle,
|
|
3464
|
+
eyebrow,
|
|
3465
|
+
textColor = "auto",
|
|
3466
|
+
primaryAction,
|
|
3467
|
+
secondaryAction,
|
|
3468
|
+
children,
|
|
3469
|
+
className,
|
|
3470
|
+
style,
|
|
3471
|
+
...props
|
|
3472
|
+
}) => {
|
|
3473
|
+
const resolvedOverlay = overlay === true ? "dark" : overlay;
|
|
3474
|
+
const isDarkOverlay = resolvedOverlay === "dark";
|
|
3475
|
+
const resolvedTextColor = textColor === "auto" ? isDarkOverlay || backgroundImage && !resolvedOverlay ? "inverse" : "default" : textColor;
|
|
3476
|
+
const heroClassName = cn(
|
|
3477
|
+
"hero",
|
|
3478
|
+
`hero_height_${height}`,
|
|
3479
|
+
`hero_align_${align}`,
|
|
3480
|
+
resolvedOverlay && `hero_overlay_${resolvedOverlay}`,
|
|
3481
|
+
`hero_text_${resolvedTextColor}`,
|
|
3482
|
+
className
|
|
3483
|
+
);
|
|
3484
|
+
const inlineStyle = { ...style };
|
|
3485
|
+
if (backgroundImage) inlineStyle.backgroundImage = `url("${backgroundImage}")`;
|
|
3486
|
+
if (backgroundColor) inlineStyle.backgroundColor = backgroundColor;
|
|
3487
|
+
return /* @__PURE__ */ jsxs("section", { className: heroClassName, style: inlineStyle, ...props, children: [
|
|
3488
|
+
resolvedOverlay && /* @__PURE__ */ jsx("div", { className: "hero_overlay", "aria-hidden": "true" }),
|
|
3489
|
+
/* @__PURE__ */ jsxs("div", { className: "hero_content", children: [
|
|
3490
|
+
eyebrow && /* @__PURE__ */ jsx("div", { className: "hero_eyebrow", children: eyebrow }),
|
|
3491
|
+
title && /* @__PURE__ */ jsx("h1", { className: "hero_title", children: title }),
|
|
3492
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "hero_subtitle", children: subtitle }),
|
|
3493
|
+
(primaryAction || secondaryAction || children) && /* @__PURE__ */ jsxs("div", { className: "hero_actions", children: [
|
|
3494
|
+
primaryAction && /* @__PURE__ */ jsx(HeroActionButton, { action: primaryAction, variant: "filled" }),
|
|
3495
|
+
secondaryAction && /* @__PURE__ */ jsx(HeroActionButton, { action: secondaryAction, variant: "outline" }),
|
|
3496
|
+
children
|
|
3497
|
+
] })
|
|
3498
|
+
] })
|
|
3499
|
+
] });
|
|
3500
|
+
};
|
|
3501
|
+
var Icon = ({ icon: IconComponent, ...props }) => {
|
|
3502
|
+
const hasLabel = !!props["aria-label"];
|
|
3503
|
+
return /* @__PURE__ */ jsx(
|
|
3504
|
+
IconComponent,
|
|
3505
|
+
{
|
|
3506
|
+
"aria-hidden": hasLabel ? void 0 : true,
|
|
3507
|
+
focusable: hasLabel ? void 0 : false,
|
|
3508
|
+
...props
|
|
3509
|
+
}
|
|
3510
|
+
);
|
|
3511
|
+
};
|
|
3512
|
+
Icon.displayName = "Icon";
|
|
3513
|
+
var ListItem = ({
|
|
3514
|
+
overline,
|
|
3515
|
+
label,
|
|
3516
|
+
supportingText,
|
|
3517
|
+
metadata,
|
|
3518
|
+
leadingElement,
|
|
3519
|
+
trailingElement,
|
|
3520
|
+
alignment,
|
|
3521
|
+
disabled,
|
|
3522
|
+
selected,
|
|
3523
|
+
onClick,
|
|
3524
|
+
className,
|
|
3525
|
+
...props
|
|
3526
|
+
}) => {
|
|
3527
|
+
const isOneLine = !overline && !supportingText && !metadata;
|
|
3528
|
+
const effectiveAlignment = alignment ?? (isOneLine ? "middle" : "top");
|
|
3529
|
+
const rootClassName = cn(
|
|
3530
|
+
"list_item",
|
|
3531
|
+
`list_item_align_${effectiveAlignment}`,
|
|
3532
|
+
disabled && "list_item_disabled",
|
|
3533
|
+
selected && "list_item_selected",
|
|
3534
|
+
onClick && "list_item_interactive",
|
|
3535
|
+
className
|
|
3536
|
+
);
|
|
3537
|
+
return (
|
|
3538
|
+
// biome-ignore lint/a11y/noStaticElementInteractions: optional interactive list item - role=button + tabIndex set conditionally based on onClick
|
|
3539
|
+
/* @__PURE__ */ jsx(
|
|
3540
|
+
"div",
|
|
3541
|
+
{
|
|
3542
|
+
className: rootClassName,
|
|
3543
|
+
onClick: disabled ? void 0 : onClick,
|
|
3544
|
+
onKeyDown: (e) => {
|
|
3545
|
+
if (disabled || !onClick) return;
|
|
3546
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
3547
|
+
e.preventDefault();
|
|
3548
|
+
e.currentTarget.click();
|
|
3549
|
+
}
|
|
3550
|
+
},
|
|
3551
|
+
role: onClick ? "button" : void 0,
|
|
3552
|
+
tabIndex: onClick && !disabled ? 0 : void 0,
|
|
3553
|
+
"aria-disabled": disabled || void 0,
|
|
3554
|
+
"aria-pressed": onClick && selected !== void 0 ? selected : void 0,
|
|
3555
|
+
...props,
|
|
3556
|
+
children: /* @__PURE__ */ jsxs("div", { className: "list_item_state_layer", children: [
|
|
3557
|
+
leadingElement && /* @__PURE__ */ jsx("div", { className: "list_item_leading", children: leadingElement }),
|
|
3558
|
+
/* @__PURE__ */ jsxs("div", { className: "list_item_content", children: [
|
|
3559
|
+
overline && /* @__PURE__ */ jsx("div", { className: "list_item_overline", children: overline }),
|
|
3560
|
+
/* @__PURE__ */ jsx("div", { className: "list_item_label", children: label }),
|
|
3561
|
+
supportingText && /* @__PURE__ */ jsx("div", { className: "list_item_supporting", children: supportingText }),
|
|
3562
|
+
metadata && /* @__PURE__ */ jsx("div", { className: "list_item_metadata", children: metadata })
|
|
3563
|
+
] }),
|
|
3564
|
+
trailingElement && /* @__PURE__ */ jsx("div", { className: "list_item_trailing", children: trailingElement })
|
|
3565
|
+
] })
|
|
3566
|
+
}
|
|
3567
|
+
)
|
|
3568
|
+
);
|
|
3569
|
+
};
|
|
3570
|
+
var MediaCard = ({
|
|
3571
|
+
image,
|
|
3572
|
+
imagePosition = "top",
|
|
3573
|
+
aspectRatio,
|
|
3574
|
+
heading,
|
|
3575
|
+
headingAs: HeadingTag = "h3",
|
|
3576
|
+
eyebrow,
|
|
3577
|
+
shadow = "sm",
|
|
3578
|
+
bordered = false,
|
|
3579
|
+
clickable = false,
|
|
3580
|
+
meta,
|
|
3581
|
+
children,
|
|
3582
|
+
className,
|
|
3583
|
+
...props
|
|
3584
|
+
}) => {
|
|
3585
|
+
const cardClassName = cn(
|
|
3586
|
+
"media_card",
|
|
3587
|
+
`media_card_image_${imagePosition}`,
|
|
3588
|
+
`media_card_shadow_${shadow}`,
|
|
3589
|
+
bordered && "media_card_bordered",
|
|
3590
|
+
clickable && "media_card_clickable",
|
|
3591
|
+
className
|
|
3592
|
+
);
|
|
3593
|
+
const isOverlay = imagePosition === "overlay";
|
|
3594
|
+
const cardStyle = isOverlay && aspectRatio ? { aspectRatio } : void 0;
|
|
3595
|
+
const wrapStyle = !isOverlay && aspectRatio ? { aspectRatio } : void 0;
|
|
3596
|
+
return /* @__PURE__ */ jsxs("div", { className: cardClassName, style: cardStyle, ...props, children: [
|
|
3597
|
+
/* @__PURE__ */ jsxs("div", { className: "media_card_image_wrap", style: wrapStyle, children: [
|
|
3598
|
+
/* @__PURE__ */ jsx("img", { className: "media_card_image", src: image.src, alt: image.alt, loading: "lazy" }),
|
|
3599
|
+
isOverlay && /* @__PURE__ */ jsx("div", { className: "media_card_overlay", "aria-hidden": "true" })
|
|
3600
|
+
] }),
|
|
3601
|
+
/* @__PURE__ */ jsxs("div", { className: "media_card_body", children: [
|
|
3602
|
+
eyebrow && /* @__PURE__ */ jsx("div", { className: "media_card_eyebrow", children: eyebrow }),
|
|
3603
|
+
heading && /* @__PURE__ */ jsx(HeadingTag, { className: "media_card_heading", children: heading }),
|
|
3604
|
+
children && /* @__PURE__ */ jsx("div", { className: "media_card_content", children }),
|
|
3605
|
+
meta && /* @__PURE__ */ jsx("div", { className: "media_card_meta", children: meta })
|
|
3606
|
+
] })
|
|
2707
3607
|
] });
|
|
2708
3608
|
};
|
|
3609
|
+
var Prose = ({ size = "md", className, children, ref, ...props }) => {
|
|
3610
|
+
const rootRef = React11.useRef(null);
|
|
3611
|
+
React11.useImperativeHandle(ref, () => rootRef.current, []);
|
|
3612
|
+
useSafeLayoutEffect(() => {
|
|
3613
|
+
const root = rootRef.current;
|
|
3614
|
+
if (!root) return;
|
|
3615
|
+
const targets = Array.from(root.querySelectorAll("pre, table"));
|
|
3616
|
+
const sync = () => {
|
|
3617
|
+
for (const el of targets) {
|
|
3618
|
+
if (el.scrollWidth > el.clientWidth) el.setAttribute("tabindex", "0");
|
|
3619
|
+
else el.removeAttribute("tabindex");
|
|
3620
|
+
}
|
|
3621
|
+
};
|
|
3622
|
+
sync();
|
|
3623
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
3624
|
+
const observer = new ResizeObserver(sync);
|
|
3625
|
+
observer.observe(root);
|
|
3626
|
+
for (const el of targets) observer.observe(el);
|
|
3627
|
+
return () => observer.disconnect();
|
|
3628
|
+
}, [children]);
|
|
3629
|
+
return /* @__PURE__ */ jsx("div", { ref: rootRef, className: cn("prose", `prose_size_${size}`, className), ...props, children });
|
|
3630
|
+
};
|
|
3631
|
+
Prose.displayName = "Prose";
|
|
2709
3632
|
var ICONS = {
|
|
2710
3633
|
info: /* @__PURE__ */ jsx(Info, { size: iconSize.lg, "aria-hidden": "true" }),
|
|
2711
3634
|
success: /* @__PURE__ */ jsx(CheckCircle2, { size: iconSize.lg, "aria-hidden": "true" }),
|
|
@@ -2756,8 +3679,8 @@ var AlertModal = ({
|
|
|
2756
3679
|
variant = "info",
|
|
2757
3680
|
title,
|
|
2758
3681
|
message,
|
|
2759
|
-
confirmText
|
|
2760
|
-
cancelText
|
|
3682
|
+
confirmText: confirmTextProp,
|
|
3683
|
+
cancelText: cancelTextProp,
|
|
2761
3684
|
showCancel = false,
|
|
2762
3685
|
destructive = false,
|
|
2763
3686
|
actionsAlign = "right",
|
|
@@ -2767,6 +3690,9 @@ var AlertModal = ({
|
|
|
2767
3690
|
onCancel,
|
|
2768
3691
|
onClose
|
|
2769
3692
|
}) => {
|
|
3693
|
+
const t = useLocaleText();
|
|
3694
|
+
const confirmText = confirmTextProp ?? t("alert.confirm");
|
|
3695
|
+
const cancelText = cancelTextProp ?? t("alert.cancel");
|
|
2770
3696
|
const dismiss = onCancel ?? onClose;
|
|
2771
3697
|
const panelRef = React11.useRef(null);
|
|
2772
3698
|
const titleId = React11.useId();
|
|
@@ -2886,7 +3812,9 @@ var LinearProgress = ({
|
|
|
2886
3812
|
}
|
|
2887
3813
|
);
|
|
2888
3814
|
};
|
|
2889
|
-
var Spinner = ({ size = 24, ariaLabel
|
|
3815
|
+
var Spinner = ({ size = 24, ariaLabel: ariaLabelProp }) => {
|
|
3816
|
+
const t = useLocaleText();
|
|
3817
|
+
const ariaLabel = ariaLabelProp ?? t("spinner.label");
|
|
2890
3818
|
return /* @__PURE__ */ jsx(
|
|
2891
3819
|
"span",
|
|
2892
3820
|
{
|
|
@@ -2964,9 +3892,12 @@ var ToastItemComponent = ({ item, onRemove, closeAriaLabel }) => {
|
|
|
2964
3892
|
var ToastProvider = ({
|
|
2965
3893
|
children,
|
|
2966
3894
|
maxCount = 5,
|
|
2967
|
-
closeAriaLabel
|
|
2968
|
-
regionLabel
|
|
3895
|
+
closeAriaLabel: closeAriaLabelProp,
|
|
3896
|
+
regionLabel: regionLabelProp
|
|
2969
3897
|
}) => {
|
|
3898
|
+
const t = useLocaleText();
|
|
3899
|
+
const closeAriaLabel = closeAriaLabelProp ?? t("toast.close");
|
|
3900
|
+
const regionLabel = regionLabelProp ?? t("toast.region");
|
|
2970
3901
|
const [toasts, setToasts] = React11.useState([]);
|
|
2971
3902
|
const isMounted = useIsMounted();
|
|
2972
3903
|
const addToast = React11.useCallback(
|
|
@@ -2977,7 +3908,7 @@ var ToastProvider = ({
|
|
|
2977
3908
|
[maxCount]
|
|
2978
3909
|
);
|
|
2979
3910
|
const removeToast = React11.useCallback((id) => {
|
|
2980
|
-
setToasts((prev) => prev.filter((
|
|
3911
|
+
setToasts((prev) => prev.filter((t2) => t2.id !== id));
|
|
2981
3912
|
}, []);
|
|
2982
3913
|
const contextValue = React11.useMemo(() => ({ addToast }), [addToast]);
|
|
2983
3914
|
return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: contextValue, children: [
|
|
@@ -3032,8 +3963,10 @@ var TopLoading = ({
|
|
|
3032
3963
|
color,
|
|
3033
3964
|
height = 3,
|
|
3034
3965
|
isLoading = true,
|
|
3035
|
-
ariaLabel
|
|
3966
|
+
ariaLabel: ariaLabelProp
|
|
3036
3967
|
}) => {
|
|
3968
|
+
const t = useLocaleText();
|
|
3969
|
+
const ariaLabel = ariaLabelProp ?? t("topLoading.label");
|
|
3037
3970
|
if (!isLoading) return null;
|
|
3038
3971
|
const isIndeterminate = progress === void 0;
|
|
3039
3972
|
return /* @__PURE__ */ jsx(
|
|
@@ -3059,26 +3992,212 @@ var TopLoading = ({
|
|
|
3059
3992
|
}
|
|
3060
3993
|
);
|
|
3061
3994
|
};
|
|
3995
|
+
var Combobox = ({
|
|
3996
|
+
value = null,
|
|
3997
|
+
onValueChange,
|
|
3998
|
+
onSearch,
|
|
3999
|
+
defaultOptions = [],
|
|
4000
|
+
debounceMs = 250,
|
|
4001
|
+
placeholder: placeholderProp,
|
|
4002
|
+
emptyMessage: emptyMessageProp,
|
|
4003
|
+
idleMessage: idleMessageProp,
|
|
4004
|
+
size = "md",
|
|
4005
|
+
disabled = false,
|
|
4006
|
+
fullWidth = false,
|
|
4007
|
+
renderOption,
|
|
4008
|
+
ariaLabel,
|
|
4009
|
+
loadingLabel: loadingLabelProp,
|
|
4010
|
+
className,
|
|
4011
|
+
...props
|
|
4012
|
+
}) => {
|
|
4013
|
+
const t = useLocaleText();
|
|
4014
|
+
const placeholder = placeholderProp ?? t("combobox.placeholder");
|
|
4015
|
+
const emptyMessage = emptyMessageProp ?? t("combobox.empty");
|
|
4016
|
+
const idleMessage = idleMessageProp ?? t("combobox.idle");
|
|
4017
|
+
const loadingLabel = loadingLabelProp ?? t("combobox.loading");
|
|
4018
|
+
const generatedId = useId();
|
|
4019
|
+
const field = useFieldControl();
|
|
4020
|
+
const inputId = field?.inputId ?? generatedId;
|
|
4021
|
+
const listId = `${inputId}-listbox`;
|
|
4022
|
+
const [query, setQuery] = useState("");
|
|
4023
|
+
const [options, setOptions] = useState(defaultOptions);
|
|
4024
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
4025
|
+
const [hasSearched, setHasSearched] = useState(false);
|
|
4026
|
+
const requestSeq = useRef(0);
|
|
4027
|
+
const defaultOptionsRef = useRef(defaultOptions);
|
|
4028
|
+
useEffect(() => {
|
|
4029
|
+
defaultOptionsRef.current = defaultOptions;
|
|
4030
|
+
}, [defaultOptions]);
|
|
4031
|
+
const closeRef = useRef(() => {
|
|
4032
|
+
});
|
|
4033
|
+
const commit = useCallback(
|
|
4034
|
+
(option) => {
|
|
4035
|
+
onValueChange?.(option);
|
|
4036
|
+
setQuery("");
|
|
4037
|
+
closeRef.current();
|
|
4038
|
+
},
|
|
4039
|
+
[onValueChange]
|
|
4040
|
+
);
|
|
4041
|
+
const popup = useListboxPopup({
|
|
4042
|
+
items: options,
|
|
4043
|
+
onCommit: commit,
|
|
4044
|
+
disabled,
|
|
4045
|
+
// 상시 컨트롤이 입력창이라 포커스를 되돌릴 필요가 없다. triggerRef 는 장식용
|
|
4046
|
+
// chevron 버튼(tabIndex=-1)에 붙어 있어, 켜면 Escape 가 포커스를 그 숨은 버튼으로 던진다.
|
|
4047
|
+
returnFocusOnClose: false
|
|
4048
|
+
});
|
|
4049
|
+
const { isOpen, setIsOpen, close, activeIndex, setActiveIndex } = popup;
|
|
4050
|
+
closeRef.current = close;
|
|
4051
|
+
useEffect(() => {
|
|
4052
|
+
if (!isOpen) return;
|
|
4053
|
+
if (query === "") {
|
|
4054
|
+
requestSeq.current++;
|
|
4055
|
+
setOptions(defaultOptionsRef.current);
|
|
4056
|
+
setHasSearched(false);
|
|
4057
|
+
setIsLoading(false);
|
|
4058
|
+
return;
|
|
4059
|
+
}
|
|
4060
|
+
const seq = ++requestSeq.current;
|
|
4061
|
+
setIsLoading(true);
|
|
4062
|
+
const timer = setTimeout(() => {
|
|
4063
|
+
onSearch(query).then((result) => {
|
|
4064
|
+
if (seq !== requestSeq.current) return;
|
|
4065
|
+
setOptions(result);
|
|
4066
|
+
setHasSearched(true);
|
|
4067
|
+
}).catch(() => {
|
|
4068
|
+
if (seq !== requestSeq.current) return;
|
|
4069
|
+
setOptions([]);
|
|
4070
|
+
setHasSearched(true);
|
|
4071
|
+
}).finally(() => {
|
|
4072
|
+
if (seq !== requestSeq.current) return;
|
|
4073
|
+
setIsLoading(false);
|
|
4074
|
+
});
|
|
4075
|
+
}, debounceMs);
|
|
4076
|
+
return () => clearTimeout(timer);
|
|
4077
|
+
}, [query, isOpen, debounceMs, onSearch]);
|
|
4078
|
+
const rootClassName = cn(
|
|
4079
|
+
"combobox",
|
|
4080
|
+
`combobox_size_${size}`,
|
|
4081
|
+
{ combobox_full_width: fullWidth, combobox_disabled: disabled },
|
|
4082
|
+
className
|
|
4083
|
+
);
|
|
4084
|
+
const showIdle = !isLoading && !hasSearched && options.length === 0;
|
|
4085
|
+
const showEmpty = !isLoading && hasSearched && options.length === 0;
|
|
4086
|
+
const hasList = !showIdle && !showEmpty;
|
|
4087
|
+
const panelStyle = useSpringPresence({
|
|
4088
|
+
visible: isOpen,
|
|
4089
|
+
from: popup.dropUp ? "translateY(4px)" : "translateY(-4px)"
|
|
4090
|
+
});
|
|
4091
|
+
return /* @__PURE__ */ jsxs("div", { ref: popup.wrapperRef, className: rootClassName, ...props, children: [
|
|
4092
|
+
/* @__PURE__ */ jsxs("div", { className: "combobox_control", children: [
|
|
4093
|
+
/* @__PURE__ */ jsx(
|
|
4094
|
+
"input",
|
|
4095
|
+
{
|
|
4096
|
+
id: inputId,
|
|
4097
|
+
className: "combobox_input",
|
|
4098
|
+
role: "combobox",
|
|
4099
|
+
type: "text",
|
|
4100
|
+
autoComplete: "off",
|
|
4101
|
+
disabled,
|
|
4102
|
+
value: isOpen ? query : value?.label ?? "",
|
|
4103
|
+
placeholder: value ? value.label : placeholder,
|
|
4104
|
+
"aria-expanded": isOpen,
|
|
4105
|
+
"aria-controls": isOpen && hasList ? listId : void 0,
|
|
4106
|
+
"aria-autocomplete": "list",
|
|
4107
|
+
"aria-activedescendant": isOpen && activeIndex >= 0 && options[activeIndex] ? `${listId}-${options[activeIndex].value}` : void 0,
|
|
4108
|
+
"aria-labelledby": field?.labelId,
|
|
4109
|
+
"aria-label": field?.labelId ? void 0 : ariaLabel,
|
|
4110
|
+
"aria-describedby": field?.describedBy,
|
|
4111
|
+
"aria-invalid": field?.invalid || void 0,
|
|
4112
|
+
"aria-required": field?.required || void 0,
|
|
4113
|
+
onChange: (event) => {
|
|
4114
|
+
setQuery(event.target.value);
|
|
4115
|
+
if (!isOpen) setIsOpen(true);
|
|
4116
|
+
},
|
|
4117
|
+
onFocus: () => !disabled && setIsOpen(true),
|
|
4118
|
+
onKeyDown: popup.onInputKeyDown
|
|
4119
|
+
}
|
|
4120
|
+
),
|
|
4121
|
+
isLoading && /* @__PURE__ */ jsx("span", { className: "combobox_spinner", children: /* @__PURE__ */ jsx(Spinner, { size: iconSize.sm, ariaLabel: loadingLabel }) }),
|
|
4122
|
+
/* @__PURE__ */ jsx(
|
|
4123
|
+
"button",
|
|
4124
|
+
{
|
|
4125
|
+
type: "button",
|
|
4126
|
+
ref: popup.triggerRef,
|
|
4127
|
+
className: "combobox_toggle",
|
|
4128
|
+
tabIndex: -1,
|
|
4129
|
+
disabled,
|
|
4130
|
+
"aria-hidden": "true",
|
|
4131
|
+
onClick: () => isOpen ? close() : setIsOpen(true),
|
|
4132
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { size: iconSize.lg })
|
|
4133
|
+
}
|
|
4134
|
+
)
|
|
4135
|
+
] }),
|
|
4136
|
+
isOpen && /* @__PURE__ */ jsx(
|
|
4137
|
+
animated.div,
|
|
4138
|
+
{
|
|
4139
|
+
className: cn("combobox_panel", { combobox_panel_up: popup.dropUp }),
|
|
4140
|
+
style: panelStyle,
|
|
4141
|
+
children: !hasList ? /* @__PURE__ */ jsx("p", { className: "combobox_message", role: "status", children: showIdle ? idleMessage : emptyMessage }) : /* @__PURE__ */ jsx(
|
|
4142
|
+
"div",
|
|
4143
|
+
{
|
|
4144
|
+
ref: popup.listRef,
|
|
4145
|
+
id: listId,
|
|
4146
|
+
className: "combobox_list",
|
|
4147
|
+
role: "listbox",
|
|
4148
|
+
children: options.map((option, index) => (
|
|
4149
|
+
/* biome-ignore lint/a11y/useKeyWithClickEvents: 키보드는 입력의 onKeyDown 이 담당한다 - option 은 aria-activedescendant 로 가리키는 비포커스 요소다 (APG Combobox) */
|
|
4150
|
+
/* @__PURE__ */ jsx(
|
|
4151
|
+
"div",
|
|
4152
|
+
{
|
|
4153
|
+
id: `${listId}-${option.value}`,
|
|
4154
|
+
role: "option",
|
|
4155
|
+
tabIndex: -1,
|
|
4156
|
+
"aria-selected": value?.value === option.value,
|
|
4157
|
+
"aria-disabled": option.disabled || void 0,
|
|
4158
|
+
className: cn("combobox_option", {
|
|
4159
|
+
is_active: index === activeIndex,
|
|
4160
|
+
is_disabled: option.disabled
|
|
4161
|
+
}),
|
|
4162
|
+
onMouseEnter: () => !option.disabled && setActiveIndex(index),
|
|
4163
|
+
onClick: () => !option.disabled && commit(option),
|
|
4164
|
+
children: renderOption ? renderOption(option) : option.label
|
|
4165
|
+
},
|
|
4166
|
+
option.value
|
|
4167
|
+
)
|
|
4168
|
+
))
|
|
4169
|
+
}
|
|
4170
|
+
)
|
|
4171
|
+
}
|
|
4172
|
+
)
|
|
4173
|
+
] });
|
|
4174
|
+
};
|
|
3062
4175
|
var normalizeForSearch = (s) => s.toLowerCase().replace(/\s+/g, "");
|
|
3063
4176
|
var Dropdown = (props) => {
|
|
4177
|
+
const t = useLocaleText();
|
|
3064
4178
|
const {
|
|
3065
4179
|
id,
|
|
3066
4180
|
label,
|
|
3067
|
-
placeholder
|
|
4181
|
+
placeholder: placeholderProp,
|
|
3068
4182
|
options,
|
|
3069
4183
|
disabled,
|
|
3070
4184
|
size = "md",
|
|
3071
4185
|
variant = "outline",
|
|
3072
4186
|
className,
|
|
3073
4187
|
searchable = false,
|
|
3074
|
-
searchPlaceholder
|
|
3075
|
-
emptyText
|
|
3076
|
-
selectedSummary
|
|
4188
|
+
searchPlaceholder: searchPlaceholderProp,
|
|
4189
|
+
emptyText: emptyTextProp,
|
|
4190
|
+
selectedSummary: selectedSummaryProp,
|
|
3077
4191
|
name
|
|
3078
4192
|
} = props;
|
|
4193
|
+
const placeholder = placeholderProp ?? t("dropdown.placeholder");
|
|
4194
|
+
const searchPlaceholder = searchPlaceholderProp ?? t("dropdown.searchPlaceholder");
|
|
4195
|
+
const emptyText = emptyTextProp ?? t("dropdown.empty");
|
|
4196
|
+
const selectedSummary = selectedSummaryProp ?? ((count) => t("dropdown.selectedSummary", { count }));
|
|
3079
4197
|
const multiple = props.multiple === true;
|
|
3080
4198
|
const internalId = useId();
|
|
3081
|
-
const
|
|
4199
|
+
const field = useFieldControl();
|
|
4200
|
+
const dropdownId = id ?? field?.inputId ?? internalId;
|
|
3082
4201
|
const isControlled = props.value !== void 0;
|
|
3083
4202
|
const [internalSingle, setInternalSingle] = useState(
|
|
3084
4203
|
() => props.multiple === true ? null : props.defaultValue ?? null
|
|
@@ -3086,14 +4205,9 @@ var Dropdown = (props) => {
|
|
|
3086
4205
|
const [internalMulti, setInternalMulti] = useState(
|
|
3087
4206
|
() => props.multiple === true ? props.defaultValue ?? [] : []
|
|
3088
4207
|
);
|
|
3089
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
3090
|
-
const [activeIndex, setActiveIndex] = useState(-1);
|
|
3091
|
-
const [dropUp, setDropUp] = useState(false);
|
|
3092
4208
|
const [searchText, setSearchText] = useState("");
|
|
3093
4209
|
const [committedQuery, setCommittedQuery] = useState("");
|
|
3094
4210
|
const isComposingRef = useRef(false);
|
|
3095
|
-
const wrapperRef = useRef(null);
|
|
3096
|
-
const controlRef = useRef(null);
|
|
3097
4211
|
const searchRef = useRef(null);
|
|
3098
4212
|
const selectedValues = useMemo(() => {
|
|
3099
4213
|
if (multiple) {
|
|
@@ -3131,129 +4245,41 @@ var Dropdown = (props) => {
|
|
|
3131
4245
|
},
|
|
3132
4246
|
[selectedValues, options, isControlled, props.multiple, props.onValueChange, props.onChange]
|
|
3133
4247
|
);
|
|
3134
|
-
const closePanel = useCallback(() => {
|
|
3135
|
-
setIsOpen(false);
|
|
3136
|
-
if (searchable) controlRef.current?.focus();
|
|
3137
|
-
}, [searchable]);
|
|
3138
4248
|
const selectOption = useCallback(
|
|
3139
|
-
(opt) => {
|
|
3140
|
-
if (opt.disabled) return;
|
|
3141
|
-
if (multiple) {
|
|
3142
|
-
toggleMultiple(opt);
|
|
3143
|
-
} else {
|
|
3144
|
-
selectSingle(opt.value);
|
|
3145
|
-
closePanel();
|
|
3146
|
-
}
|
|
3147
|
-
},
|
|
3148
|
-
[multiple, toggleMultiple, selectSingle, closePanel]
|
|
3149
|
-
);
|
|
3150
|
-
useEffect(() => {
|
|
3151
|
-
const handleOutsideClick = (e) => {
|
|
3152
|
-
if (!wrapperRef.current?.contains(e.target)) {
|
|
3153
|
-
setIsOpen(false);
|
|
3154
|
-
}
|
|
3155
|
-
};
|
|
3156
|
-
document.addEventListener("mousedown", handleOutsideClick);
|
|
3157
|
-
return () => document.removeEventListener("mousedown", handleOutsideClick);
|
|
3158
|
-
}, []);
|
|
3159
|
-
const moveActive = useCallback(
|
|
3160
|
-
(dir) => {
|
|
3161
|
-
if (visibleOptions.length === 0) return;
|
|
3162
|
-
if (!isOpen) {
|
|
3163
|
-
setIsOpen(true);
|
|
3164
|
-
return;
|
|
3165
|
-
}
|
|
3166
|
-
let i = activeIndex;
|
|
3167
|
-
if (i === -1) {
|
|
3168
|
-
i = dir === 1 ? -1 : 0;
|
|
3169
|
-
}
|
|
3170
|
-
const len = visibleOptions.length;
|
|
3171
|
-
for (let step = 0; step < len; step++) {
|
|
3172
|
-
i = (i + dir + len) % len;
|
|
3173
|
-
if (!visibleOptions[i].disabled) {
|
|
3174
|
-
setActiveIndex(i);
|
|
3175
|
-
break;
|
|
3176
|
-
}
|
|
3177
|
-
}
|
|
3178
|
-
},
|
|
3179
|
-
[visibleOptions, isOpen, activeIndex]
|
|
3180
|
-
);
|
|
3181
|
-
const commitActive = useCallback(() => {
|
|
3182
|
-
if (activeIndex < 0 || activeIndex >= visibleOptions.length) return;
|
|
3183
|
-
selectOption(visibleOptions[activeIndex]);
|
|
3184
|
-
}, [activeIndex, visibleOptions, selectOption]);
|
|
3185
|
-
const onControlKeyDown = (e) => {
|
|
3186
|
-
if (disabled) return;
|
|
3187
|
-
switch (e.key) {
|
|
3188
|
-
case " ":
|
|
3189
|
-
case "Enter":
|
|
3190
|
-
e.preventDefault();
|
|
3191
|
-
if (!isOpen) setIsOpen(true);
|
|
3192
|
-
else commitActive();
|
|
3193
|
-
break;
|
|
3194
|
-
case "ArrowDown":
|
|
3195
|
-
e.preventDefault();
|
|
3196
|
-
moveActive(1);
|
|
3197
|
-
break;
|
|
3198
|
-
case "ArrowUp":
|
|
3199
|
-
e.preventDefault();
|
|
3200
|
-
moveActive(-1);
|
|
3201
|
-
break;
|
|
3202
|
-
case "Home":
|
|
3203
|
-
e.preventDefault();
|
|
3204
|
-
setIsOpen(true);
|
|
3205
|
-
setActiveIndex(visibleOptions.findIndex((o) => !o.disabled));
|
|
3206
|
-
break;
|
|
3207
|
-
case "End":
|
|
3208
|
-
e.preventDefault();
|
|
3209
|
-
setIsOpen(true);
|
|
3210
|
-
for (let i = visibleOptions.length - 1; i >= 0; i--) {
|
|
3211
|
-
if (!visibleOptions[i].disabled) {
|
|
3212
|
-
setActiveIndex(i);
|
|
3213
|
-
break;
|
|
3214
|
-
}
|
|
3215
|
-
}
|
|
3216
|
-
break;
|
|
3217
|
-
case "Escape":
|
|
3218
|
-
e.preventDefault();
|
|
3219
|
-
setIsOpen(false);
|
|
3220
|
-
break;
|
|
3221
|
-
case "Tab":
|
|
3222
|
-
setIsOpen(false);
|
|
3223
|
-
break;
|
|
3224
|
-
}
|
|
3225
|
-
};
|
|
3226
|
-
const onSearchKeyDown = (e) => {
|
|
3227
|
-
if (e.nativeEvent.isComposing) return;
|
|
3228
|
-
switch (e.key) {
|
|
3229
|
-
case "ArrowDown":
|
|
3230
|
-
e.preventDefault();
|
|
3231
|
-
moveActive(1);
|
|
3232
|
-
break;
|
|
3233
|
-
case "ArrowUp":
|
|
3234
|
-
e.preventDefault();
|
|
3235
|
-
moveActive(-1);
|
|
3236
|
-
break;
|
|
3237
|
-
case "Enter":
|
|
3238
|
-
e.preventDefault();
|
|
3239
|
-
commitActive();
|
|
3240
|
-
break;
|
|
3241
|
-
case "Escape":
|
|
3242
|
-
e.preventDefault();
|
|
3243
|
-
closePanel();
|
|
3244
|
-
break;
|
|
3245
|
-
case "Tab":
|
|
4249
|
+
(opt) => {
|
|
4250
|
+
if (opt.disabled) return;
|
|
4251
|
+
if (multiple) {
|
|
4252
|
+
toggleMultiple(opt);
|
|
4253
|
+
} else {
|
|
4254
|
+
selectSingle(opt.value);
|
|
3246
4255
|
closePanel();
|
|
3247
|
-
|
|
3248
|
-
}
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
4256
|
+
}
|
|
4257
|
+
},
|
|
4258
|
+
// closePanel 은 아래 훅에서 오므로 선언 순서상 참조만 한다 (렌더마다 동일 참조).
|
|
4259
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: closePanel 은 훅 결과라 아래에서 정의된다
|
|
4260
|
+
[multiple, toggleMultiple, selectSingle]
|
|
4261
|
+
);
|
|
4262
|
+
const {
|
|
4263
|
+
isOpen,
|
|
4264
|
+
setIsOpen,
|
|
4265
|
+
dropUp,
|
|
4266
|
+
activeIndex,
|
|
4267
|
+
setActiveIndex,
|
|
4268
|
+
wrapperRef,
|
|
4269
|
+
triggerRef: controlRef,
|
|
4270
|
+
listRef,
|
|
4271
|
+
close: closePanel,
|
|
4272
|
+
onTriggerKeyDown: onControlKeyDown,
|
|
4273
|
+
onInputKeyDown: onSearchKeyDown
|
|
4274
|
+
} = useListboxPopup({
|
|
4275
|
+
items: visibleOptions,
|
|
4276
|
+
onCommit: selectOption,
|
|
4277
|
+
disabled,
|
|
4278
|
+
// searchable 은 포커스가 검색 입력에 있으므로 닫을 때 트리거로 되돌린다.
|
|
4279
|
+
returnFocusOnClose: searchable,
|
|
4280
|
+
// 열릴 때는 선택된 항목을 활성으로. 없으면 훅이 첫 활성 항목을 고른다.
|
|
4281
|
+
initialActiveIndex: (opts) => opts.findIndex((o) => selectedValues.includes(o.value) && !o.disabled)
|
|
4282
|
+
});
|
|
3257
4283
|
useEffect(() => {
|
|
3258
4284
|
if (!isOpen) {
|
|
3259
4285
|
setSearchText("");
|
|
@@ -3266,14 +4292,6 @@ var Dropdown = (props) => {
|
|
|
3266
4292
|
searchRef.current?.focus();
|
|
3267
4293
|
}
|
|
3268
4294
|
}, [isOpen, searchable]);
|
|
3269
|
-
useEffect(() => {
|
|
3270
|
-
if (!isOpen || !controlRef.current) return;
|
|
3271
|
-
const rect = controlRef.current.getBoundingClientRect();
|
|
3272
|
-
const spaceBelow = window.innerHeight - rect.bottom;
|
|
3273
|
-
const spaceAbove = rect.top;
|
|
3274
|
-
const MIN_BELOW = 120;
|
|
3275
|
-
setDropUp(spaceBelow < MIN_BELOW && spaceAbove > spaceBelow);
|
|
3276
|
-
}, [isOpen]);
|
|
3277
4295
|
const currentOption = useMemo(
|
|
3278
4296
|
() => multiple ? null : options.find((o) => o.value === selectedValues[0]) ?? null,
|
|
3279
4297
|
[multiple, options, selectedValues]
|
|
@@ -3304,6 +4322,8 @@ var Dropdown = (props) => {
|
|
|
3304
4322
|
className: cn("dropdown_control", { is_disabled: disabled }),
|
|
3305
4323
|
"aria-haspopup": "listbox",
|
|
3306
4324
|
"aria-expanded": isOpen,
|
|
4325
|
+
"aria-describedby": field?.describedBy,
|
|
4326
|
+
"aria-invalid": field?.invalid || void 0,
|
|
3307
4327
|
"aria-controls": isOpen ? `${dropdownId}_listbox` : void 0,
|
|
3308
4328
|
onClick: () => !disabled && setIsOpen((o) => !o),
|
|
3309
4329
|
onKeyDown: onControlKeyDown,
|
|
@@ -3354,6 +4374,7 @@ var Dropdown = (props) => {
|
|
|
3354
4374
|
/* @__PURE__ */ jsx(
|
|
3355
4375
|
"div",
|
|
3356
4376
|
{
|
|
4377
|
+
ref: listRef,
|
|
3357
4378
|
id: `${dropdownId}_listbox`,
|
|
3358
4379
|
role: "listbox",
|
|
3359
4380
|
className: "dropdown_options",
|
|
@@ -3399,7 +4420,7 @@ var Dropdown = (props) => {
|
|
|
3399
4420
|
var pad = (n) => String(n).padStart(2, "0");
|
|
3400
4421
|
var getDaysInMonth = (year, month) => new Date(year, month, 0).getDate();
|
|
3401
4422
|
var normalizeWidth = (v) => typeof v === "number" ? `${v}px` : v;
|
|
3402
|
-
var
|
|
4423
|
+
var range2 = (start, end) => Array.from({ length: end - start + 1 }, (_, i) => start + i);
|
|
3403
4424
|
var DatePicker = ({
|
|
3404
4425
|
label,
|
|
3405
4426
|
value,
|
|
@@ -3413,12 +4434,19 @@ var DatePicker = ({
|
|
|
3413
4434
|
disabled,
|
|
3414
4435
|
fullWidth = true,
|
|
3415
4436
|
width,
|
|
3416
|
-
yearLabel
|
|
3417
|
-
monthLabel
|
|
3418
|
-
dayLabel
|
|
3419
|
-
minDateSrFormat
|
|
3420
|
-
selectableRangeUntilTodaySrText
|
|
4437
|
+
yearLabel: yearLabelProp,
|
|
4438
|
+
monthLabel: monthLabelProp,
|
|
4439
|
+
dayLabel: dayLabelProp,
|
|
4440
|
+
minDateSrFormat: minDateSrFormatProp,
|
|
4441
|
+
selectableRangeUntilTodaySrText: selectableRangeUntilTodaySrTextProp
|
|
3421
4442
|
}) => {
|
|
4443
|
+
const t = useLocaleText();
|
|
4444
|
+
const yearLabel = yearLabelProp ?? t("datePicker.year");
|
|
4445
|
+
const monthLabel = monthLabelProp ?? t("datePicker.month");
|
|
4446
|
+
const dayLabel = dayLabelProp ?? t("datePicker.day");
|
|
4447
|
+
const minDateSrFormat = minDateSrFormatProp ?? t("datePicker.minDateSr");
|
|
4448
|
+
const selectableRangeUntilTodaySrText = selectableRangeUntilTodaySrTextProp ?? t("datePicker.rangeUntilTodaySr");
|
|
4449
|
+
const field = useFieldControl();
|
|
3422
4450
|
const groupId = React11.useId();
|
|
3423
4451
|
const constraintId = React11.useId();
|
|
3424
4452
|
const { todayYear, todayMonth, todayDay } = React11.useMemo(() => {
|
|
@@ -3467,22 +4495,23 @@ var DatePicker = ({
|
|
|
3467
4495
|
}
|
|
3468
4496
|
return daysInMonth;
|
|
3469
4497
|
}, [year, month, selectableRange, todayYear, todayMonth, todayDay]);
|
|
4498
|
+
const minYear = min.year > 0 ? Math.max(startYear, min.year) : startYear;
|
|
3470
4499
|
const yearOptions = React11.useMemo(
|
|
3471
|
-
() =>
|
|
4500
|
+
() => range2(minYear, Math.max(minYear, maxYear)).map((y) => ({
|
|
3472
4501
|
value: String(y),
|
|
3473
4502
|
label: String(y)
|
|
3474
4503
|
})),
|
|
3475
|
-
[
|
|
4504
|
+
[minYear, maxYear]
|
|
3476
4505
|
);
|
|
3477
4506
|
const monthOptions = React11.useMemo(
|
|
3478
|
-
() =>
|
|
4507
|
+
() => range2(minMonth, Math.max(minMonth, maxMonth)).map((m) => ({
|
|
3479
4508
|
value: String(m),
|
|
3480
4509
|
label: pad(m)
|
|
3481
4510
|
})),
|
|
3482
4511
|
[minMonth, maxMonth]
|
|
3483
4512
|
);
|
|
3484
4513
|
const dayOptions = React11.useMemo(
|
|
3485
|
-
() =>
|
|
4514
|
+
() => range2(minDay, Math.max(minDay, maxDay)).map((d) => ({
|
|
3486
4515
|
value: String(d),
|
|
3487
4516
|
label: pad(d)
|
|
3488
4517
|
})),
|
|
@@ -3548,8 +4577,9 @@ var DatePicker = ({
|
|
|
3548
4577
|
{
|
|
3549
4578
|
className: "date_picker_fields",
|
|
3550
4579
|
role: "group",
|
|
3551
|
-
"aria-labelledby": label ? groupId : void 0,
|
|
3552
|
-
"aria-describedby": constraintDesc ? constraintId : void 0,
|
|
4580
|
+
"aria-labelledby": field?.labelId ?? (label ? groupId : void 0),
|
|
4581
|
+
"aria-describedby": [field?.describedBy, constraintDesc ? constraintId : void 0].filter(Boolean).join(" ") || void 0,
|
|
4582
|
+
"aria-invalid": field?.invalid || void 0,
|
|
3553
4583
|
children: [
|
|
3554
4584
|
/* @__PURE__ */ jsx(
|
|
3555
4585
|
Dropdown,
|
|
@@ -3595,8 +4625,83 @@ var DatePicker = ({
|
|
|
3595
4625
|
)
|
|
3596
4626
|
] });
|
|
3597
4627
|
};
|
|
4628
|
+
var DateRangePicker = ({
|
|
4629
|
+
value,
|
|
4630
|
+
onValueChange,
|
|
4631
|
+
startLabel: startLabelProp,
|
|
4632
|
+
endLabel: endLabelProp,
|
|
4633
|
+
startYear,
|
|
4634
|
+
endYear,
|
|
4635
|
+
minDate,
|
|
4636
|
+
selectableRange = "all",
|
|
4637
|
+
disabled,
|
|
4638
|
+
fullWidth = true
|
|
4639
|
+
}) => {
|
|
4640
|
+
const t = useLocaleText();
|
|
4641
|
+
const startLabel = startLabelProp ?? t("dateRange.start");
|
|
4642
|
+
const endLabel = endLabelProp ?? t("dateRange.end");
|
|
4643
|
+
const field = useFieldControl();
|
|
4644
|
+
const start = value?.start;
|
|
4645
|
+
const end = value?.end;
|
|
4646
|
+
const handleStartChange = (next) => {
|
|
4647
|
+
onValueChange({ start: next, end: end && end < next ? void 0 : end });
|
|
4648
|
+
};
|
|
4649
|
+
const handleEndChange = (next) => {
|
|
4650
|
+
onValueChange({ start, end: next });
|
|
4651
|
+
};
|
|
4652
|
+
const endMinDate = start ?? minDate;
|
|
4653
|
+
return /* @__PURE__ */ jsx(
|
|
4654
|
+
"div",
|
|
4655
|
+
{
|
|
4656
|
+
className: cn("date_range_picker", {
|
|
4657
|
+
date_range_picker_full_width: fullWidth,
|
|
4658
|
+
date_range_picker_disabled: disabled
|
|
4659
|
+
}),
|
|
4660
|
+
children: /* @__PURE__ */ jsxs(
|
|
4661
|
+
"div",
|
|
4662
|
+
{
|
|
4663
|
+
className: "date_range_picker_fields",
|
|
4664
|
+
role: "group",
|
|
4665
|
+
"aria-labelledby": field?.labelId,
|
|
4666
|
+
"aria-describedby": field?.describedBy,
|
|
4667
|
+
"aria-invalid": field?.invalid || void 0,
|
|
4668
|
+
children: [
|
|
4669
|
+
/* @__PURE__ */ jsx(
|
|
4670
|
+
DatePicker,
|
|
4671
|
+
{
|
|
4672
|
+
label: startLabel,
|
|
4673
|
+
value: start,
|
|
4674
|
+
onValueChange: handleStartChange,
|
|
4675
|
+
startYear,
|
|
4676
|
+
endYear,
|
|
4677
|
+
minDate,
|
|
4678
|
+
selectableRange,
|
|
4679
|
+
disabled,
|
|
4680
|
+
fullWidth: true
|
|
4681
|
+
}
|
|
4682
|
+
),
|
|
4683
|
+
/* @__PURE__ */ jsx(
|
|
4684
|
+
DatePicker,
|
|
4685
|
+
{
|
|
4686
|
+
label: endLabel,
|
|
4687
|
+
value: end,
|
|
4688
|
+
onValueChange: handleEndChange,
|
|
4689
|
+
startYear,
|
|
4690
|
+
endYear,
|
|
4691
|
+
minDate: endMinDate,
|
|
4692
|
+
selectableRange,
|
|
4693
|
+
disabled: disabled || !start,
|
|
4694
|
+
fullWidth: true
|
|
4695
|
+
}
|
|
4696
|
+
)
|
|
4697
|
+
]
|
|
4698
|
+
}
|
|
4699
|
+
)
|
|
4700
|
+
}
|
|
4701
|
+
);
|
|
4702
|
+
};
|
|
3598
4703
|
var FileInput = ({
|
|
3599
|
-
label
|
|
4704
|
+
label: labelProp,
|
|
3600
4705
|
onFiles,
|
|
3601
4706
|
supportingText,
|
|
3602
4707
|
preview = false,
|
|
@@ -3608,8 +4713,12 @@ var FileInput = ({
|
|
|
3608
4713
|
onChange,
|
|
3609
4714
|
...props
|
|
3610
4715
|
}) => {
|
|
3611
|
-
const
|
|
4716
|
+
const t = useLocaleText();
|
|
4717
|
+
const label = labelProp ?? t("fileInput.label");
|
|
4718
|
+
const generatedInputId = React11.useId();
|
|
3612
4719
|
const helperId = React11.useId();
|
|
4720
|
+
const field = useFieldControl();
|
|
4721
|
+
const inputId = field?.inputId ?? generatedInputId;
|
|
3613
4722
|
const inputRef = React11.useRef(null);
|
|
3614
4723
|
const [previewUrls, setPreviewUrls] = React11.useState([]);
|
|
3615
4724
|
const previewUrlsRef = React11.useRef([]);
|
|
@@ -3679,7 +4788,8 @@ var FileInput = ({
|
|
|
3679
4788
|
className: "file_input_control",
|
|
3680
4789
|
disabled,
|
|
3681
4790
|
accept: isPreviewVariant ? accept ?? "image/*" : accept,
|
|
3682
|
-
"aria-describedby": supportingText ? helperId : void 0,
|
|
4791
|
+
"aria-describedby": field?.describedBy ?? (supportingText ? helperId : void 0),
|
|
4792
|
+
"aria-invalid": field?.invalid || void 0,
|
|
3683
4793
|
onChange: handleChange
|
|
3684
4794
|
}
|
|
3685
4795
|
),
|
|
@@ -3704,7 +4814,7 @@ var FileInput = ({
|
|
|
3704
4814
|
type: "button",
|
|
3705
4815
|
className: "file_input_preview_remove",
|
|
3706
4816
|
onClick: handleRemove,
|
|
3707
|
-
"aria-label": "
|
|
4817
|
+
"aria-label": t("fileInput.removeImage"),
|
|
3708
4818
|
children: /* @__PURE__ */ jsx(X, { size: iconSize.xs, "aria-hidden": "true" })
|
|
3709
4819
|
}
|
|
3710
4820
|
),
|
|
@@ -3767,20 +4877,28 @@ function ImageCropper({
|
|
|
3767
4877
|
onReady,
|
|
3768
4878
|
onError,
|
|
3769
4879
|
className,
|
|
3770
|
-
label
|
|
3771
|
-
hint
|
|
3772
|
-
zoomOutLabel
|
|
3773
|
-
zoomLabel
|
|
3774
|
-
zoomInLabel
|
|
3775
|
-
noPanHint
|
|
4880
|
+
label: labelProp,
|
|
4881
|
+
hint: hintProp,
|
|
4882
|
+
zoomOutLabel: zoomOutLabelProp,
|
|
4883
|
+
zoomLabel: zoomLabelProp,
|
|
4884
|
+
zoomInLabel: zoomInLabelProp,
|
|
4885
|
+
noPanHint: noPanHintProp,
|
|
3776
4886
|
...rest
|
|
3777
4887
|
}) {
|
|
4888
|
+
const t = useLocaleText();
|
|
4889
|
+
const hint = hintProp ?? t("imageCropper.hint");
|
|
4890
|
+
const noPanHint = noPanHintProp ?? t("imageCropper.noPanHint");
|
|
4891
|
+
const label = labelProp ?? t("imageCropper.label");
|
|
4892
|
+
const zoomOutLabel = zoomOutLabelProp ?? t("imageCropper.zoomOut");
|
|
4893
|
+
const zoomLabel = zoomLabelProp ?? t("imageCropper.zoom");
|
|
4894
|
+
const zoomInLabel = zoomInLabelProp ?? t("imageCropper.zoomIn");
|
|
3778
4895
|
const imageRef = useRef(null);
|
|
3779
4896
|
const viewportRef = useRef(null);
|
|
3780
4897
|
const dragRef = useRef(
|
|
3781
4898
|
null
|
|
3782
4899
|
);
|
|
3783
4900
|
const hintId = useId();
|
|
4901
|
+
const field = useFieldControl();
|
|
3784
4902
|
const [previewUrl, setPreviewUrl] = useState("");
|
|
3785
4903
|
const [srcType, setSrcType] = useState("");
|
|
3786
4904
|
useEffect(() => {
|
|
@@ -3955,8 +5073,9 @@ function ImageCropper({
|
|
|
3955
5073
|
className: cn("image_cropper_viewport", dragging && "image_cropper_viewport_dragging"),
|
|
3956
5074
|
style: viewportStyle,
|
|
3957
5075
|
role: "group",
|
|
3958
|
-
"aria-
|
|
3959
|
-
"aria-
|
|
5076
|
+
"aria-labelledby": field?.labelId,
|
|
5077
|
+
"aria-label": field?.labelId ? void 0 : label,
|
|
5078
|
+
"aria-describedby": [field?.describedBy, hintId].filter(Boolean).join(" "),
|
|
3960
5079
|
tabIndex: imageSize ? 0 : -1,
|
|
3961
5080
|
onPointerDown: handlePointerDown,
|
|
3962
5081
|
onPointerMove: handlePointerMove,
|
|
@@ -4044,9 +5163,11 @@ var OtpInput = ({
|
|
|
4044
5163
|
disabled = false,
|
|
4045
5164
|
supportingText,
|
|
4046
5165
|
autoFocus = false,
|
|
4047
|
-
ariaLabel
|
|
5166
|
+
ariaLabel: ariaLabelProp,
|
|
4048
5167
|
className
|
|
4049
5168
|
}) => {
|
|
5169
|
+
const t = useLocaleText();
|
|
5170
|
+
const ariaLabel = ariaLabelProp ?? t("otpInput.label");
|
|
4050
5171
|
const inputsRef = React11.useRef([]);
|
|
4051
5172
|
const isTypingRef = React11.useRef(false);
|
|
4052
5173
|
React11.useEffect(() => {
|
|
@@ -4130,46 +5251,56 @@ var OtpInput = ({
|
|
|
4130
5251
|
};
|
|
4131
5252
|
const rootClassName = cn("otp_input", className);
|
|
4132
5253
|
const supportingId = React11.useId();
|
|
5254
|
+
const field = useFieldControl();
|
|
4133
5255
|
return (
|
|
4134
5256
|
// biome-ignore lint/a11y/useSemanticElements: <fieldset> would force border/legend styles; role=group is the WAI-ARIA equivalent for OTP grouping
|
|
4135
|
-
/* @__PURE__ */ jsxs(
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
5257
|
+
/* @__PURE__ */ jsxs(
|
|
5258
|
+
"div",
|
|
5259
|
+
{
|
|
5260
|
+
className: rootClassName,
|
|
5261
|
+
role: "group",
|
|
5262
|
+
"aria-labelledby": field?.labelId,
|
|
5263
|
+
"aria-label": field?.labelId ? void 0 : ariaLabel,
|
|
5264
|
+
children: [
|
|
5265
|
+
/* @__PURE__ */ jsx("div", { className: "otp_input_boxes", children: digits.map((digit, i) => /* @__PURE__ */ jsx(
|
|
5266
|
+
"input",
|
|
5267
|
+
{
|
|
5268
|
+
ref: (el) => {
|
|
5269
|
+
inputsRef.current[i] = el;
|
|
5270
|
+
},
|
|
5271
|
+
type: "text",
|
|
5272
|
+
inputMode: "numeric",
|
|
5273
|
+
pattern: "\\d*",
|
|
5274
|
+
maxLength: 1,
|
|
5275
|
+
autoComplete: i === 0 ? "one-time-code" : "off",
|
|
5276
|
+
value: digit,
|
|
5277
|
+
onChange: (e) => handleChange(i, e),
|
|
5278
|
+
onFocus: () => handleFocus(i),
|
|
5279
|
+
onKeyDown: (e) => handleKeyDown2(i, e),
|
|
5280
|
+
onPaste: handlePaste,
|
|
5281
|
+
disabled,
|
|
5282
|
+
"aria-label": t("otpInput.digit", { index: i + 1 }),
|
|
5283
|
+
"aria-invalid": error || field?.invalid || void 0,
|
|
5284
|
+
"aria-describedby": field?.describedBy ?? (supportingText ? supportingId : void 0),
|
|
5285
|
+
className: cn(
|
|
5286
|
+
"otp_input_box",
|
|
5287
|
+
error && "otp_input_box_error",
|
|
5288
|
+
disabled && "otp_input_box_disabled"
|
|
5289
|
+
)
|
|
5290
|
+
},
|
|
5291
|
+
i
|
|
5292
|
+
)) }),
|
|
5293
|
+
supportingText && /* @__PURE__ */ jsx(
|
|
5294
|
+
"span",
|
|
5295
|
+
{
|
|
5296
|
+
id: supportingId,
|
|
5297
|
+
className: cn("otp_input_supporting", error && "otp_input_supporting_error"),
|
|
5298
|
+
children: supportingText
|
|
5299
|
+
}
|
|
4160
5300
|
)
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
supportingText && /* @__PURE__ */ jsx(
|
|
4165
|
-
"span",
|
|
4166
|
-
{
|
|
4167
|
-
id: supportingId,
|
|
4168
|
-
className: cn("otp_input_supporting", error && "otp_input_supporting_error"),
|
|
4169
|
-
children: supportingText
|
|
4170
|
-
}
|
|
4171
|
-
)
|
|
4172
|
-
] })
|
|
5301
|
+
]
|
|
5302
|
+
}
|
|
5303
|
+
)
|
|
4173
5304
|
);
|
|
4174
5305
|
};
|
|
4175
5306
|
OtpInput.displayName = "OtpInput";
|
|
@@ -4198,6 +5329,7 @@ var RadioGroup = ({
|
|
|
4198
5329
|
const generatedName = React11.useId();
|
|
4199
5330
|
const name = nameProp ?? generatedName;
|
|
4200
5331
|
const idPrefix = React11.useId();
|
|
5332
|
+
const field = useFieldControl();
|
|
4201
5333
|
const labelId = label ? `${idPrefix}-label` : void 0;
|
|
4202
5334
|
const helperId = supportingText ? `${idPrefix}-help` : void 0;
|
|
4203
5335
|
const onChange = React11.useCallback(
|
|
@@ -4227,9 +5359,10 @@ var RadioGroup = ({
|
|
|
4227
5359
|
"div",
|
|
4228
5360
|
{
|
|
4229
5361
|
role: "radiogroup",
|
|
4230
|
-
"aria-labelledby": labelId,
|
|
4231
|
-
"aria-describedby": helperId,
|
|
4232
|
-
"aria-invalid": error || void 0,
|
|
5362
|
+
"aria-labelledby": field?.labelId ?? labelId,
|
|
5363
|
+
"aria-describedby": field?.describedBy ?? helperId,
|
|
5364
|
+
"aria-invalid": error || field?.invalid || void 0,
|
|
5365
|
+
"aria-required": field?.required || void 0,
|
|
4233
5366
|
className: "radio_group_options",
|
|
4234
5367
|
children
|
|
4235
5368
|
}
|
|
@@ -4262,6 +5395,7 @@ var Radio = ({
|
|
|
4262
5395
|
onChange?.(event);
|
|
4263
5396
|
};
|
|
4264
5397
|
const rootClassName = cn("radio", `radio_size_${size}`, disabled && "radio_disabled", className);
|
|
5398
|
+
const field = useFieldControl();
|
|
4265
5399
|
return /* @__PURE__ */ jsxs("label", { className: rootClassName, children: [
|
|
4266
5400
|
/* @__PURE__ */ jsx(
|
|
4267
5401
|
"input",
|
|
@@ -4269,6 +5403,8 @@ var Radio = ({
|
|
|
4269
5403
|
ref,
|
|
4270
5404
|
type: "radio",
|
|
4271
5405
|
className: "radio_input",
|
|
5406
|
+
id: field?.inputId ?? props.id,
|
|
5407
|
+
"aria-describedby": field?.describedBy ?? props["aria-describedby"],
|
|
4272
5408
|
value,
|
|
4273
5409
|
name,
|
|
4274
5410
|
disabled,
|
|
@@ -4282,6 +5418,149 @@ var Radio = ({
|
|
|
4282
5418
|
] });
|
|
4283
5419
|
};
|
|
4284
5420
|
Radio.displayName = "Radio";
|
|
5421
|
+
var SEPARATORS = /[,\t\n\r]+/;
|
|
5422
|
+
var splitTags = (text) => text.split(SEPARATORS).map((part) => part.trim()).filter(Boolean);
|
|
5423
|
+
var TagInput = ({
|
|
5424
|
+
value,
|
|
5425
|
+
defaultValue = [],
|
|
5426
|
+
onValueChange,
|
|
5427
|
+
placeholder: placeholderProp,
|
|
5428
|
+
maxTags,
|
|
5429
|
+
allowDuplicates = false,
|
|
5430
|
+
size = "md",
|
|
5431
|
+
disabled = false,
|
|
5432
|
+
fullWidth = false,
|
|
5433
|
+
ariaLabel,
|
|
5434
|
+
className,
|
|
5435
|
+
...props
|
|
5436
|
+
}) => {
|
|
5437
|
+
const t = useLocaleText();
|
|
5438
|
+
const placeholder = placeholderProp ?? t("tagInput.placeholder");
|
|
5439
|
+
const generatedId = useId();
|
|
5440
|
+
const field = useFieldControl();
|
|
5441
|
+
const inputId = field?.inputId ?? generatedId;
|
|
5442
|
+
const isControlled = value !== void 0;
|
|
5443
|
+
const [innerTags, setInnerTags] = useState(defaultValue);
|
|
5444
|
+
const tags = isControlled ? value : innerTags;
|
|
5445
|
+
const [draft, setDraft] = useState("");
|
|
5446
|
+
const [announcement, setAnnouncement] = useState("");
|
|
5447
|
+
const inputRef = useRef(null);
|
|
5448
|
+
const isFull = maxTags !== void 0 && tags.length >= maxTags;
|
|
5449
|
+
const setTags = (next) => {
|
|
5450
|
+
if (!isControlled) setInnerTags(next);
|
|
5451
|
+
onValueChange?.(next);
|
|
5452
|
+
};
|
|
5453
|
+
const addTags = (text) => {
|
|
5454
|
+
const candidates = splitTags(text);
|
|
5455
|
+
if (candidates.length === 0) return 0;
|
|
5456
|
+
const next = [...tags];
|
|
5457
|
+
const added = [];
|
|
5458
|
+
const duplicates = [];
|
|
5459
|
+
for (const candidate of candidates) {
|
|
5460
|
+
if (maxTags !== void 0 && next.length >= maxTags) break;
|
|
5461
|
+
if (!allowDuplicates && next.includes(candidate)) {
|
|
5462
|
+
duplicates.push(candidate);
|
|
5463
|
+
continue;
|
|
5464
|
+
}
|
|
5465
|
+
next.push(candidate);
|
|
5466
|
+
added.push(candidate);
|
|
5467
|
+
}
|
|
5468
|
+
const isAtCap = maxTags !== void 0 && next.length >= maxTags;
|
|
5469
|
+
if (added.length === 0) {
|
|
5470
|
+
if (isAtCap) {
|
|
5471
|
+
setAnnouncement(t("tagInput.atCap", { max: maxTags }));
|
|
5472
|
+
} else if (duplicates.length > 0) {
|
|
5473
|
+
setAnnouncement(t("tagInput.duplicate", { names: duplicates.join(", ") }));
|
|
5474
|
+
}
|
|
5475
|
+
return 0;
|
|
5476
|
+
}
|
|
5477
|
+
setTags(next);
|
|
5478
|
+
const notes = [
|
|
5479
|
+
duplicates.length > 0 ? t("tagInput.duplicate", { names: duplicates.join(", ") }) : "",
|
|
5480
|
+
isAtCap && maxTags !== void 0 ? t("tagInput.atCap", { max: maxTags }) : ""
|
|
5481
|
+
].filter(Boolean);
|
|
5482
|
+
setAnnouncement(
|
|
5483
|
+
notes.length > 0 ? t("tagInput.addedWithNotes", { names: added.join(", "), notes: notes.join(", ") }) : t("tagInput.added", { names: added.join(", ") })
|
|
5484
|
+
);
|
|
5485
|
+
return added.length;
|
|
5486
|
+
};
|
|
5487
|
+
const removeAt = (index) => {
|
|
5488
|
+
const removed = tags[index];
|
|
5489
|
+
setTags(tags.filter((_, i) => i !== index));
|
|
5490
|
+
setAnnouncement(t("tagInput.removed", { name: removed }));
|
|
5491
|
+
};
|
|
5492
|
+
const onKeyDown = (event) => {
|
|
5493
|
+
if (event.nativeEvent.isComposing) return;
|
|
5494
|
+
if (event.key === "Enter" || event.key === ",") {
|
|
5495
|
+
event.preventDefault();
|
|
5496
|
+
if (addTags(draft) > 0) setDraft("");
|
|
5497
|
+
return;
|
|
5498
|
+
}
|
|
5499
|
+
if (event.key === "Backspace" && draft === "" && tags.length > 0) {
|
|
5500
|
+
event.preventDefault();
|
|
5501
|
+
removeAt(tags.length - 1);
|
|
5502
|
+
}
|
|
5503
|
+
};
|
|
5504
|
+
const onPaste = (event) => {
|
|
5505
|
+
const text = event.clipboardData.getData("text");
|
|
5506
|
+
if (!SEPARATORS.test(text)) return;
|
|
5507
|
+
event.preventDefault();
|
|
5508
|
+
const input = event.currentTarget;
|
|
5509
|
+
const start = input.selectionStart ?? draft.length;
|
|
5510
|
+
const end = input.selectionEnd ?? draft.length;
|
|
5511
|
+
const merged = `${draft.slice(0, start)}${text}${draft.slice(end)}`;
|
|
5512
|
+
if (addTags(merged) > 0) setDraft("");
|
|
5513
|
+
};
|
|
5514
|
+
const rootClassName = cn(
|
|
5515
|
+
"tag_input",
|
|
5516
|
+
`tag_input_size_${size}`,
|
|
5517
|
+
{ tag_input_full_width: fullWidth, tag_input_disabled: disabled },
|
|
5518
|
+
className
|
|
5519
|
+
);
|
|
5520
|
+
return /* @__PURE__ */ jsxs("div", { className: rootClassName, ...props, children: [
|
|
5521
|
+
/* @__PURE__ */ jsxs("div", { className: "tag_input_control", onClick: () => inputRef.current?.focus(), children: [
|
|
5522
|
+
tags.length > 0 && /* @__PURE__ */ jsx("ul", { className: "tag_input_tags", children: tags.map((tag, index) => (
|
|
5523
|
+
/* biome-ignore lint/suspicious/noArrayIndexKey: allowDuplicates 면 같은 라벨이 여러 개라 값만으로는 구분되지 않는다 */
|
|
5524
|
+
/* @__PURE__ */ jsx("li", { className: "tag_input_tag", children: /* @__PURE__ */ jsx(
|
|
5525
|
+
Chip,
|
|
5526
|
+
{
|
|
5527
|
+
type: "static",
|
|
5528
|
+
size: "sm",
|
|
5529
|
+
label: tag,
|
|
5530
|
+
removable: !disabled,
|
|
5531
|
+
onRemove: () => removeAt(index)
|
|
5532
|
+
}
|
|
5533
|
+
) }, `${tag}-${index}`)
|
|
5534
|
+
)) }),
|
|
5535
|
+
/* @__PURE__ */ jsx(
|
|
5536
|
+
"input",
|
|
5537
|
+
{
|
|
5538
|
+
ref: inputRef,
|
|
5539
|
+
id: inputId,
|
|
5540
|
+
className: "tag_input_field",
|
|
5541
|
+
type: "text",
|
|
5542
|
+
autoComplete: "off",
|
|
5543
|
+
value: draft,
|
|
5544
|
+
disabled,
|
|
5545
|
+
readOnly: isFull,
|
|
5546
|
+
placeholder: isFull ? "" : placeholder,
|
|
5547
|
+
"aria-labelledby": field?.labelId,
|
|
5548
|
+
"aria-label": field?.labelId ? void 0 : ariaLabel,
|
|
5549
|
+
"aria-describedby": field?.describedBy,
|
|
5550
|
+
"aria-invalid": field?.invalid || void 0,
|
|
5551
|
+
"aria-required": field?.required || void 0,
|
|
5552
|
+
onChange: (event) => setDraft(event.target.value),
|
|
5553
|
+
onKeyDown,
|
|
5554
|
+
onPaste,
|
|
5555
|
+
onBlur: () => {
|
|
5556
|
+
if (addTags(draft) > 0) setDraft("");
|
|
5557
|
+
}
|
|
5558
|
+
}
|
|
5559
|
+
)
|
|
5560
|
+
] }),
|
|
5561
|
+
/* @__PURE__ */ jsx("span", { className: "tag_input_live", role: "status", children: announcement })
|
|
5562
|
+
] });
|
|
5563
|
+
};
|
|
4285
5564
|
var LINE_HEIGHT_PX = {
|
|
4286
5565
|
sm: 20,
|
|
4287
5566
|
md: 20,
|
|
@@ -4313,8 +5592,10 @@ var Textarea = ({
|
|
|
4313
5592
|
...props
|
|
4314
5593
|
}) => {
|
|
4315
5594
|
const generatedId = useId();
|
|
4316
|
-
const
|
|
5595
|
+
const field = useFieldControl();
|
|
5596
|
+
const inputId = id ?? field?.inputId ?? generatedId;
|
|
4317
5597
|
const helperId = supportingText ? `${inputId}-help` : void 0;
|
|
5598
|
+
const describedBy = field?.describedBy ?? helperId;
|
|
4318
5599
|
const isControlled = value !== void 0;
|
|
4319
5600
|
const applyTransform = (nextValue) => transformValue ? transformValue(nextValue) : nextValue;
|
|
4320
5601
|
const [innerValue, setInnerValue] = useState(() => applyTransform(value ?? defaultValue ?? ""));
|
|
@@ -4346,228 +5627,187 @@ var Textarea = ({
|
|
|
4346
5627
|
const maxH = maxRows ? maxRows * lh2 : Number.POSITIVE_INFINITY;
|
|
4347
5628
|
el.style.height = "auto";
|
|
4348
5629
|
const next = Math.min(Math.max(el.scrollHeight, minH), maxH);
|
|
4349
|
-
el.style.height = `${next}px`;
|
|
4350
|
-
el.style.overflowY = el.scrollHeight > maxH ? "auto" : "hidden";
|
|
4351
|
-
}, [innerValue, autoGrow, size, minRows, maxRows]);
|
|
4352
|
-
const rootClassName = cn(
|
|
4353
|
-
"textarea",
|
|
4354
|
-
size === "sm" && "textarea_size_sm",
|
|
4355
|
-
size === "lg" && "textarea_size_lg",
|
|
4356
|
-
fullWidth && "textarea_full_width",
|
|
4357
|
-
error && "textarea_error",
|
|
4358
|
-
props.disabled && "textarea_disabled",
|
|
4359
|
-
className
|
|
4360
|
-
);
|
|
4361
|
-
const counterText = showCounter && maxLength !== void 0 ? `${innerValue.length}/${maxLength}` : showCounter ? String(innerValue.length) : null;
|
|
4362
|
-
const emit = (nextValue) => {
|
|
4363
|
-
setInnerValue(nextValue);
|
|
4364
|
-
if (nextValue !== lastEmittedValueRef.current) {
|
|
4365
|
-
lastEmittedValueRef.current = nextValue;
|
|
4366
|
-
(onValueChange ?? onChangeAction)?.(nextValue);
|
|
4367
|
-
}
|
|
4368
|
-
};
|
|
4369
|
-
return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
|
|
4370
|
-
label && showLabel && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "textarea_label", children: label }),
|
|
4371
|
-
/* @__PURE__ */ jsxs("div", { className: "textarea_container", children: [
|
|
4372
|
-
toolbar && /* @__PURE__ */ jsx("div", { className: "textarea_toolbar", inert: props.disabled || void 0, children: toolbar }),
|
|
4373
|
-
/* @__PURE__ */ jsx("div", { className: "textarea_input_wrap", children: /* @__PURE__ */ jsx(
|
|
4374
|
-
"textarea",
|
|
4375
|
-
{
|
|
4376
|
-
id: inputId,
|
|
4377
|
-
ref: setRefs,
|
|
4378
|
-
className: "textarea_input",
|
|
4379
|
-
style: { resize: autoGrow ? "none" : resize },
|
|
4380
|
-
rows: autoGrow ? minRows ?? rows : rows,
|
|
4381
|
-
maxLength,
|
|
4382
|
-
"aria-invalid": !!error,
|
|
4383
|
-
"aria-describedby": helperId,
|
|
4384
|
-
"aria-label": !showLabel ? label : void 0,
|
|
4385
|
-
...props,
|
|
4386
|
-
value: innerValue,
|
|
4387
|
-
onCompositionStart: () => {
|
|
4388
|
-
isComposingRef.current = true;
|
|
4389
|
-
},
|
|
4390
|
-
onCompositionEnd: (event) => {
|
|
4391
|
-
isComposingRef.current = false;
|
|
4392
|
-
emit(applyTransform(event.currentTarget.value));
|
|
4393
|
-
},
|
|
4394
|
-
onChange: (event) => {
|
|
4395
|
-
const rawValue = event.target.value;
|
|
4396
|
-
if (isComposingRef.current) {
|
|
4397
|
-
setInnerValue(rawValue);
|
|
4398
|
-
if (imeStrategy === "immediate" && rawValue !== lastEmittedValueRef.current) {
|
|
4399
|
-
lastEmittedValueRef.current = rawValue;
|
|
4400
|
-
(onValueChange ?? onChangeAction)?.(rawValue);
|
|
4401
|
-
}
|
|
4402
|
-
return;
|
|
4403
|
-
}
|
|
4404
|
-
emit(applyTransform(rawValue));
|
|
4405
|
-
}
|
|
4406
|
-
}
|
|
4407
|
-
) })
|
|
4408
|
-
] }),
|
|
4409
|
-
(supportingText || counterText) && /* @__PURE__ */ jsxs("div", { className: "textarea_footer", children: [
|
|
4410
|
-
supportingText ? /* @__PURE__ */ jsx("div", { id: helperId, className: "textarea_helper", children: supportingText }) : /* @__PURE__ */ jsx("span", {}),
|
|
4411
|
-
counterText && /* @__PURE__ */ jsx("div", { className: "textarea_counter", "aria-hidden": "true", children: counterText })
|
|
4412
|
-
] })
|
|
4413
|
-
] });
|
|
4414
|
-
};
|
|
4415
|
-
Textarea.displayName = "Textarea";
|
|
4416
|
-
var ClearIcon = () => /* @__PURE__ */ jsx(X, { size: iconSize.lg, "aria-hidden": "true" });
|
|
4417
|
-
var DEFAULT_PASSWORD_TOGGLE_LABELS = { show: "\uBE44\uBC00\uBC88\uD638 \uD45C\uC2DC", hide: "\uBE44\uBC00\uBC88\uD638 \uC228\uAE30\uAE30" };
|
|
4418
|
-
var TextField = ({
|
|
4419
|
-
id,
|
|
4420
|
-
label,
|
|
4421
|
-
showLabel = true,
|
|
4422
|
-
supportingText,
|
|
4423
|
-
error,
|
|
4424
|
-
success,
|
|
4425
|
-
identifier,
|
|
4426
|
-
leadingIcon,
|
|
4427
|
-
trailingIcon,
|
|
4428
|
-
leadingAction,
|
|
4429
|
-
trailingAction,
|
|
4430
|
-
showPasswordToggle,
|
|
4431
|
-
passwordToggleLabels,
|
|
4432
|
-
clearable,
|
|
4433
|
-
clearLabel = "\uC9C0\uC6B0\uAE30",
|
|
4434
|
-
type,
|
|
4435
|
-
fullWidth,
|
|
4436
|
-
size = "md",
|
|
4437
|
-
variant = "outline",
|
|
4438
|
-
className,
|
|
4439
|
-
onValueChange,
|
|
4440
|
-
onChangeAction,
|
|
4441
|
-
imeStrategy = "delayed",
|
|
4442
|
-
value,
|
|
4443
|
-
defaultValue,
|
|
4444
|
-
transformValue,
|
|
4445
|
-
ref,
|
|
4446
|
-
...props
|
|
4447
|
-
}) => {
|
|
4448
|
-
const generatedId = useId();
|
|
4449
|
-
const inputId = id ?? generatedId;
|
|
4450
|
-
const helperId = supportingText ? `${inputId}-help` : void 0;
|
|
4451
|
-
const isControlled = value !== void 0;
|
|
4452
|
-
const applyTransform = (nextValue) => transformValue ? transformValue(nextValue) : nextValue;
|
|
4453
|
-
const [innerValue, setInnerValue] = useState(() => applyTransform(value ?? defaultValue ?? ""));
|
|
4454
|
-
const isComposingRef = useRef(false);
|
|
4455
|
-
const lastEmittedValueRef = useRef(innerValue);
|
|
4456
|
-
const [prevValue, setPrevValue] = useState(value);
|
|
4457
|
-
if (isControlled && value !== prevValue && !isComposingRef.current) {
|
|
4458
|
-
setPrevValue(value);
|
|
4459
|
-
const nextValue = applyTransform(value ?? "");
|
|
4460
|
-
setInnerValue(nextValue);
|
|
4461
|
-
lastEmittedValueRef.current = nextValue;
|
|
4462
|
-
}
|
|
4463
|
-
const emit = useCallback(
|
|
4464
|
-
(nextValue) => {
|
|
4465
|
-
setInnerValue(nextValue);
|
|
4466
|
-
if (nextValue !== lastEmittedValueRef.current) {
|
|
4467
|
-
lastEmittedValueRef.current = nextValue;
|
|
4468
|
-
(onValueChange ?? onChangeAction)?.(nextValue);
|
|
4469
|
-
}
|
|
4470
|
-
},
|
|
4471
|
-
[onValueChange, onChangeAction]
|
|
4472
|
-
);
|
|
4473
|
-
const handleClear = useCallback(() => {
|
|
4474
|
-
emit("");
|
|
4475
|
-
}, [emit]);
|
|
4476
|
-
const [passwordRevealed, setPasswordRevealed] = useState(false);
|
|
4477
|
-
const togglePassword = useCallback(() => {
|
|
4478
|
-
setPasswordRevealed((revealed) => !revealed);
|
|
4479
|
-
}, []);
|
|
4480
|
-
let resolvedType = type;
|
|
4481
|
-
if (showPasswordToggle) {
|
|
4482
|
-
resolvedType = passwordRevealed ? "text" : type ?? "password";
|
|
4483
|
-
}
|
|
4484
|
-
const isError = !!error;
|
|
4485
|
-
const isSuccess = !!success && !isError;
|
|
5630
|
+
el.style.height = `${next}px`;
|
|
5631
|
+
el.style.overflowY = el.scrollHeight > maxH ? "auto" : "hidden";
|
|
5632
|
+
}, [innerValue, autoGrow, size, minRows, maxRows]);
|
|
4486
5633
|
const rootClassName = cn(
|
|
4487
|
-
"
|
|
4488
|
-
|
|
4489
|
-
size === "
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
isSuccess && "text_field_success",
|
|
4494
|
-
props.disabled && "text_field_disabled",
|
|
5634
|
+
"textarea",
|
|
5635
|
+
size === "sm" && "textarea_size_sm",
|
|
5636
|
+
size === "lg" && "textarea_size_lg",
|
|
5637
|
+
fullWidth && "textarea_full_width",
|
|
5638
|
+
error && "textarea_error",
|
|
5639
|
+
props.disabled && "textarea_disabled",
|
|
4495
5640
|
className
|
|
4496
5641
|
);
|
|
4497
|
-
const
|
|
4498
|
-
const
|
|
4499
|
-
|
|
4500
|
-
{
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
"aria-label": passwordToggleLabel,
|
|
4504
|
-
disabled: props.disabled,
|
|
4505
|
-
children: passwordRevealed ? /* @__PURE__ */ jsx(EyeOff, { size: iconSize.lg, "aria-hidden": "true" }) : /* @__PURE__ */ jsx(Eye, { size: iconSize.lg, "aria-hidden": "true" })
|
|
4506
|
-
}
|
|
4507
|
-
) }) : clearable && innerValue ? /* @__PURE__ */ jsx(
|
|
4508
|
-
"button",
|
|
4509
|
-
{
|
|
4510
|
-
type: "button",
|
|
4511
|
-
className: "text_field_clear",
|
|
4512
|
-
onClick: handleClear,
|
|
4513
|
-
"aria-label": clearLabel,
|
|
4514
|
-
disabled: props.disabled,
|
|
4515
|
-
children: /* @__PURE__ */ jsx(ClearIcon, {})
|
|
5642
|
+
const counterText = showCounter && maxLength !== void 0 ? `${innerValue.length}/${maxLength}` : showCounter ? String(innerValue.length) : null;
|
|
5643
|
+
const emit = (nextValue) => {
|
|
5644
|
+
setInnerValue(nextValue);
|
|
5645
|
+
if (nextValue !== lastEmittedValueRef.current) {
|
|
5646
|
+
lastEmittedValueRef.current = nextValue;
|
|
5647
|
+
(onValueChange ?? onChangeAction)?.(nextValue);
|
|
4516
5648
|
}
|
|
4517
|
-
|
|
4518
|
-
const resolvedLeading = leadingAction ? /* @__PURE__ */ jsx("span", { className: "text_field_icon text_field_action", children: leadingAction }) : leadingIcon ? /* @__PURE__ */ jsx("span", { className: "text_field_icon", "aria-hidden": "true", children: leadingIcon }) : null;
|
|
5649
|
+
};
|
|
4519
5650
|
return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
|
|
4520
|
-
label && showLabel && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "
|
|
4521
|
-
/* @__PURE__ */
|
|
4522
|
-
|
|
4523
|
-
/* @__PURE__ */ jsx(
|
|
4524
|
-
"
|
|
5651
|
+
label && showLabel && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "textarea_label", children: label }),
|
|
5652
|
+
/* @__PURE__ */ jsxs("div", { className: "textarea_container", children: [
|
|
5653
|
+
toolbar && /* @__PURE__ */ jsx("div", { className: "textarea_toolbar", inert: props.disabled || void 0, children: toolbar }),
|
|
5654
|
+
/* @__PURE__ */ jsx("div", { className: "textarea_input_wrap", children: /* @__PURE__ */ jsx(
|
|
5655
|
+
"textarea",
|
|
4525
5656
|
{
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
setInnerValue(rawValue);
|
|
4553
|
-
if (imeStrategy === "immediate" && rawValue !== lastEmittedValueRef.current) {
|
|
4554
|
-
lastEmittedValueRef.current = rawValue;
|
|
4555
|
-
(onValueChange ?? onChangeAction)?.(rawValue);
|
|
4556
|
-
}
|
|
4557
|
-
return;
|
|
4558
|
-
}
|
|
4559
|
-
emit(applyTransform(rawValue));
|
|
5657
|
+
id: inputId,
|
|
5658
|
+
ref: setRefs,
|
|
5659
|
+
className: "textarea_input",
|
|
5660
|
+
style: { resize: autoGrow ? "none" : resize },
|
|
5661
|
+
rows: autoGrow ? minRows ?? rows : rows,
|
|
5662
|
+
maxLength,
|
|
5663
|
+
"aria-invalid": !!error || !!field?.invalid,
|
|
5664
|
+
"aria-describedby": describedBy,
|
|
5665
|
+
"aria-required": field?.required || void 0,
|
|
5666
|
+
"aria-label": !showLabel ? label : void 0,
|
|
5667
|
+
...props,
|
|
5668
|
+
value: innerValue,
|
|
5669
|
+
onCompositionStart: () => {
|
|
5670
|
+
isComposingRef.current = true;
|
|
5671
|
+
},
|
|
5672
|
+
onCompositionEnd: (event) => {
|
|
5673
|
+
isComposingRef.current = false;
|
|
5674
|
+
emit(applyTransform(event.currentTarget.value));
|
|
5675
|
+
},
|
|
5676
|
+
onChange: (event) => {
|
|
5677
|
+
const rawValue = event.target.value;
|
|
5678
|
+
if (isComposingRef.current) {
|
|
5679
|
+
setInnerValue(rawValue);
|
|
5680
|
+
if (imeStrategy === "immediate" && rawValue !== lastEmittedValueRef.current) {
|
|
5681
|
+
lastEmittedValueRef.current = rawValue;
|
|
5682
|
+
(onValueChange ?? onChangeAction)?.(rawValue);
|
|
4560
5683
|
}
|
|
5684
|
+
return;
|
|
4561
5685
|
}
|
|
4562
|
-
|
|
5686
|
+
emit(applyTransform(rawValue));
|
|
5687
|
+
}
|
|
4563
5688
|
}
|
|
4564
|
-
)
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
5689
|
+
) })
|
|
5690
|
+
] }),
|
|
5691
|
+
(supportingText || counterText) && /* @__PURE__ */ jsxs("div", { className: "textarea_footer", children: [
|
|
5692
|
+
supportingText ? /* @__PURE__ */ jsx("div", { id: helperId, className: "textarea_helper", children: supportingText }) : /* @__PURE__ */ jsx("span", {}),
|
|
5693
|
+
counterText && /* @__PURE__ */ jsx("div", { className: "textarea_counter", "aria-hidden": "true", children: counterText })
|
|
5694
|
+
] })
|
|
4568
5695
|
] });
|
|
4569
5696
|
};
|
|
4570
|
-
|
|
5697
|
+
Textarea.displayName = "Textarea";
|
|
5698
|
+
var toMinutes = (value) => {
|
|
5699
|
+
if (!value) return null;
|
|
5700
|
+
const [h, m] = value.split(":").map(Number);
|
|
5701
|
+
if (!Number.isInteger(h) || !Number.isInteger(m)) return null;
|
|
5702
|
+
if (h < 0 || h > 23 || m < 0 || m > 59) return null;
|
|
5703
|
+
return h * 60 + m;
|
|
5704
|
+
};
|
|
5705
|
+
var pad2 = (n) => String(n).padStart(2, "0");
|
|
5706
|
+
var TimePicker = ({
|
|
5707
|
+
label,
|
|
5708
|
+
value,
|
|
5709
|
+
onValueChange,
|
|
5710
|
+
minuteStep = 5,
|
|
5711
|
+
minTime,
|
|
5712
|
+
maxTime,
|
|
5713
|
+
disabled,
|
|
5714
|
+
fullWidth = true,
|
|
5715
|
+
hourLabel: hourLabelProp,
|
|
5716
|
+
minuteLabel: minuteLabelProp
|
|
5717
|
+
}) => {
|
|
5718
|
+
const t = useLocaleText();
|
|
5719
|
+
const hourLabel = hourLabelProp ?? t("timePicker.hour");
|
|
5720
|
+
const minuteLabel = minuteLabelProp ?? t("timePicker.minute");
|
|
5721
|
+
const field = useFieldControl();
|
|
5722
|
+
const groupId = React11.useId();
|
|
5723
|
+
const constraintId = React11.useId();
|
|
5724
|
+
const min = toMinutes(minTime) ?? 0;
|
|
5725
|
+
const max = toMinutes(maxTime) ?? 23 * 60 + 59;
|
|
5726
|
+
const parsed = toMinutes(value);
|
|
5727
|
+
const hour = parsed === null ? null : Math.floor(parsed / 60);
|
|
5728
|
+
const minute = parsed === null ? null : parsed % 60;
|
|
5729
|
+
const hourOptions = React11.useMemo(() => {
|
|
5730
|
+
const first = Math.floor(min / 60);
|
|
5731
|
+
const last = Math.floor(max / 60);
|
|
5732
|
+
return Array.from({ length: Math.max(0, last - first + 1) }, (_, i) => {
|
|
5733
|
+
const h = first + i;
|
|
5734
|
+
return { value: String(h), label: pad2(h) };
|
|
5735
|
+
});
|
|
5736
|
+
}, [min, max]);
|
|
5737
|
+
const minuteOptions = React11.useMemo(() => {
|
|
5738
|
+
if (hour === null) return [];
|
|
5739
|
+
const step = Math.max(1, Math.floor(minuteStep));
|
|
5740
|
+
return Array.from({ length: Math.ceil(60 / step) }, (_, i) => i * step).filter((m) => m < 60).filter((m) => hour * 60 + m >= min && hour * 60 + m <= max).map((m) => ({ value: String(m), label: pad2(m) }));
|
|
5741
|
+
}, [hour, minuteStep, min, max]);
|
|
5742
|
+
const emit = (h, m) => onValueChange(`${pad2(h)}:${pad2(m)}`);
|
|
5743
|
+
const handleHourChange = (raw) => {
|
|
5744
|
+
if (!raw) return;
|
|
5745
|
+
const h = Number(raw);
|
|
5746
|
+
const step = Math.max(1, Math.floor(minuteStep));
|
|
5747
|
+
const candidates = Array.from({ length: Math.ceil(60 / step) }, (_, i) => i * step).filter(
|
|
5748
|
+
(m) => m < 60 && h * 60 + m >= min && h * 60 + m <= max
|
|
5749
|
+
);
|
|
5750
|
+
if (candidates.length === 0) return;
|
|
5751
|
+
const keep = minute !== null && candidates.includes(minute) ? minute : candidates[0];
|
|
5752
|
+
emit(h, keep);
|
|
5753
|
+
};
|
|
5754
|
+
const handleMinuteChange = (raw) => {
|
|
5755
|
+
if (!raw || hour === null) return;
|
|
5756
|
+
emit(hour, Number(raw));
|
|
5757
|
+
};
|
|
5758
|
+
const constraint = minTime || maxTime ? t("timePicker.rangeSr", { min: minTime ?? "00:00", max: maxTime ?? "23:59" }) : "";
|
|
5759
|
+
return /* @__PURE__ */ jsxs(
|
|
5760
|
+
"div",
|
|
5761
|
+
{
|
|
5762
|
+
className: cn("time_picker", {
|
|
5763
|
+
time_picker_full_width: fullWidth,
|
|
5764
|
+
time_picker_disabled: disabled
|
|
5765
|
+
}),
|
|
5766
|
+
children: [
|
|
5767
|
+
label && /* @__PURE__ */ jsx("span", { className: "time_picker_label", id: groupId, children: label }),
|
|
5768
|
+
constraint && /* @__PURE__ */ jsx("span", { id: constraintId, className: "time_picker_sr_only", children: constraint }),
|
|
5769
|
+
/* @__PURE__ */ jsxs(
|
|
5770
|
+
"div",
|
|
5771
|
+
{
|
|
5772
|
+
className: "time_picker_fields",
|
|
5773
|
+
role: "group",
|
|
5774
|
+
"aria-labelledby": field?.labelId ?? (label ? groupId : void 0),
|
|
5775
|
+
"aria-describedby": [field?.describedBy, constraint ? constraintId : void 0].filter(Boolean).join(" ") || void 0,
|
|
5776
|
+
"aria-invalid": field?.invalid || void 0,
|
|
5777
|
+
children: [
|
|
5778
|
+
/* @__PURE__ */ jsx(
|
|
5779
|
+
Dropdown,
|
|
5780
|
+
{
|
|
5781
|
+
size: "sm",
|
|
5782
|
+
fullWidth: true,
|
|
5783
|
+
label: hourLabel,
|
|
5784
|
+
placeholder: hourLabel,
|
|
5785
|
+
options: hourOptions,
|
|
5786
|
+
value: hour === null ? null : String(hour),
|
|
5787
|
+
onValueChange: handleHourChange,
|
|
5788
|
+
disabled
|
|
5789
|
+
}
|
|
5790
|
+
),
|
|
5791
|
+
/* @__PURE__ */ jsx(
|
|
5792
|
+
Dropdown,
|
|
5793
|
+
{
|
|
5794
|
+
size: "sm",
|
|
5795
|
+
fullWidth: true,
|
|
5796
|
+
label: minuteLabel,
|
|
5797
|
+
placeholder: minuteLabel,
|
|
5798
|
+
options: minuteOptions,
|
|
5799
|
+
value: minute === null ? null : String(minute),
|
|
5800
|
+
onValueChange: handleMinuteChange,
|
|
5801
|
+
disabled: disabled || hour === null
|
|
5802
|
+
}
|
|
5803
|
+
)
|
|
5804
|
+
]
|
|
5805
|
+
}
|
|
5806
|
+
)
|
|
5807
|
+
]
|
|
5808
|
+
}
|
|
5809
|
+
);
|
|
5810
|
+
};
|
|
4571
5811
|
var Toggle = ({
|
|
4572
5812
|
checked,
|
|
4573
5813
|
defaultChecked,
|
|
@@ -4590,6 +5830,7 @@ var Toggle = ({
|
|
|
4590
5830
|
if (!isControlled) setInnerChecked(next);
|
|
4591
5831
|
(onCheckedChange ?? onChange)?.(next);
|
|
4592
5832
|
};
|
|
5833
|
+
const field = useFieldControl();
|
|
4593
5834
|
const rootClassName = cn(
|
|
4594
5835
|
"toggle",
|
|
4595
5836
|
`toggle_size_${size}`,
|
|
@@ -4604,7 +5845,10 @@ var Toggle = ({
|
|
|
4604
5845
|
type: "button",
|
|
4605
5846
|
role: "switch",
|
|
4606
5847
|
"aria-checked": isOn,
|
|
4607
|
-
|
|
5848
|
+
id: field?.inputId ?? props.id,
|
|
5849
|
+
"aria-describedby": field?.describedBy ?? props["aria-describedby"],
|
|
5850
|
+
"aria-labelledby": field?.labelId,
|
|
5851
|
+
"aria-label": field?.labelId ? void 0 : ariaLabel,
|
|
4608
5852
|
disabled,
|
|
4609
5853
|
onClick: handleToggle,
|
|
4610
5854
|
className: rootClassName,
|
|
@@ -4630,92 +5874,6 @@ var IconButton = ({
|
|
|
4630
5874
|
);
|
|
4631
5875
|
return /* @__PURE__ */ jsx("button", { ref, type, className: buttonClassName, ...props, children: /* @__PURE__ */ jsx("span", { className: "icon_button_icon", "aria-hidden": "true", children: icon }) });
|
|
4632
5876
|
};
|
|
4633
|
-
var range2 = (start, end) => {
|
|
4634
|
-
const out = [];
|
|
4635
|
-
for (let i = start; i <= end; i += 1) out.push(i);
|
|
4636
|
-
return out;
|
|
4637
|
-
};
|
|
4638
|
-
var getPaginationItems = (page, totalPages) => {
|
|
4639
|
-
if (totalPages <= 7) return range2(1, totalPages);
|
|
4640
|
-
const items = [];
|
|
4641
|
-
const last = totalPages;
|
|
4642
|
-
const sibling = 2;
|
|
4643
|
-
if (page <= sibling + 2) {
|
|
4644
|
-
for (const p of range2(1, sibling + 3)) items.push(p);
|
|
4645
|
-
items.push("ellipsis");
|
|
4646
|
-
items.push(last);
|
|
4647
|
-
return items;
|
|
4648
|
-
}
|
|
4649
|
-
if (page >= last - sibling - 1) {
|
|
4650
|
-
items.push(1);
|
|
4651
|
-
items.push("ellipsis");
|
|
4652
|
-
for (const p of range2(last - sibling - 2, last)) items.push(p);
|
|
4653
|
-
return items;
|
|
4654
|
-
}
|
|
4655
|
-
items.push(1);
|
|
4656
|
-
items.push("ellipsis");
|
|
4657
|
-
for (const p of range2(page - sibling, page + sibling)) items.push(p);
|
|
4658
|
-
items.push("ellipsis");
|
|
4659
|
-
items.push(last);
|
|
4660
|
-
return items;
|
|
4661
|
-
};
|
|
4662
|
-
var Pagination = ({
|
|
4663
|
-
page,
|
|
4664
|
-
totalPages,
|
|
4665
|
-
onPageChange,
|
|
4666
|
-
onChange,
|
|
4667
|
-
prevLabel = "\uC774\uC804 \uD398\uC774\uC9C0",
|
|
4668
|
-
nextLabel = "\uB2E4\uC74C \uD398\uC774\uC9C0",
|
|
4669
|
-
navLabel = "\uD398\uC774\uC9C0 \uC774\uB3D9"
|
|
4670
|
-
}) => {
|
|
4671
|
-
const emit = onPageChange ?? onChange;
|
|
4672
|
-
const prevDisabled = page <= 1;
|
|
4673
|
-
const nextDisabled = page >= totalPages;
|
|
4674
|
-
const items = React11.useMemo(() => getPaginationItems(page, totalPages), [page, totalPages]);
|
|
4675
|
-
return /* @__PURE__ */ jsxs("nav", { className: "pagination", "aria-label": navLabel, children: [
|
|
4676
|
-
/* @__PURE__ */ jsx(
|
|
4677
|
-
"button",
|
|
4678
|
-
{
|
|
4679
|
-
type: "button",
|
|
4680
|
-
className: "pagination_item",
|
|
4681
|
-
onClick: () => emit?.(page - 1),
|
|
4682
|
-
disabled: prevDisabled,
|
|
4683
|
-
"aria-label": prevLabel,
|
|
4684
|
-
children: "\u2039"
|
|
4685
|
-
}
|
|
4686
|
-
),
|
|
4687
|
-
/* @__PURE__ */ jsx("ul", { className: "pagination_pages", children: items.map((it, idx) => {
|
|
4688
|
-
if (it === "ellipsis") {
|
|
4689
|
-
const prev = items[idx - 1];
|
|
4690
|
-
const next = items[idx + 1];
|
|
4691
|
-
return /* @__PURE__ */ jsx("li", { className: "pagination_ellipsis", "aria-hidden": "true", children: "\u2026" }, `e-${prev}-${next}`);
|
|
4692
|
-
}
|
|
4693
|
-
const isActive = it === page;
|
|
4694
|
-
const buttonClassName = cn("pagination_page_button", { pagination_active: isActive });
|
|
4695
|
-
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
4696
|
-
"button",
|
|
4697
|
-
{
|
|
4698
|
-
type: "button",
|
|
4699
|
-
className: buttonClassName,
|
|
4700
|
-
onClick: () => emit?.(it),
|
|
4701
|
-
"aria-current": isActive ? "page" : void 0,
|
|
4702
|
-
children: it
|
|
4703
|
-
}
|
|
4704
|
-
) }, it);
|
|
4705
|
-
}) }),
|
|
4706
|
-
/* @__PURE__ */ jsx(
|
|
4707
|
-
"button",
|
|
4708
|
-
{
|
|
4709
|
-
type: "button",
|
|
4710
|
-
className: "pagination_item",
|
|
4711
|
-
onClick: () => emit?.(page + 1),
|
|
4712
|
-
disabled: nextDisabled,
|
|
4713
|
-
"aria-label": nextLabel,
|
|
4714
|
-
children: "\u203A"
|
|
4715
|
-
}
|
|
4716
|
-
)
|
|
4717
|
-
] });
|
|
4718
|
-
};
|
|
4719
5877
|
var SLIDE_FROM = {
|
|
4720
5878
|
left: "translateX(-100%)",
|
|
4721
5879
|
right: "translateX(100%)",
|
|
@@ -4731,13 +5889,15 @@ var Drawer = ({
|
|
|
4731
5889
|
closeOnOverlay = true,
|
|
4732
5890
|
dismissible,
|
|
4733
5891
|
showCloseIcon = true,
|
|
4734
|
-
closeLabel
|
|
5892
|
+
closeLabel: closeLabelProp,
|
|
4735
5893
|
ariaLabel,
|
|
4736
5894
|
onExited,
|
|
4737
5895
|
children,
|
|
4738
5896
|
className,
|
|
4739
5897
|
...props
|
|
4740
5898
|
}) => {
|
|
5899
|
+
const t = useLocaleText();
|
|
5900
|
+
const closeLabel = closeLabelProp ?? t("drawer.close");
|
|
4741
5901
|
const lastContentRef = React11.useRef({ children, title, footer });
|
|
4742
5902
|
if (open) lastContentRef.current = { children, title, footer };
|
|
4743
5903
|
const content = open ? { children, title, footer } : lastContentRef.current;
|
|
@@ -4837,13 +5997,15 @@ var Modal = ({
|
|
|
4837
5997
|
footer,
|
|
4838
5998
|
footerAlign = "end",
|
|
4839
5999
|
showCloseIcon = true,
|
|
4840
|
-
closeLabel
|
|
6000
|
+
closeLabel: closeLabelProp,
|
|
4841
6001
|
children,
|
|
4842
6002
|
className,
|
|
4843
6003
|
ariaLabel,
|
|
4844
6004
|
onExited,
|
|
4845
6005
|
...props
|
|
4846
6006
|
}) => {
|
|
6007
|
+
const t = useLocaleText();
|
|
6008
|
+
const closeLabel = closeLabelProp ?? t("modal.close");
|
|
4847
6009
|
const lastContentRef = React11.useRef({ children, title, description, footer });
|
|
4848
6010
|
if (open) lastContentRef.current = { children, title, description, footer };
|
|
4849
6011
|
const content = open ? { children, title, description, footer } : lastContentRef.current;
|
|
@@ -5010,15 +6172,39 @@ var ThemeProvider = ({
|
|
|
5010
6172
|
);
|
|
5011
6173
|
return /* @__PURE__ */ jsx(ThemeContext.Provider, { value, children });
|
|
5012
6174
|
};
|
|
6175
|
+
var AppShell = ({
|
|
6176
|
+
sidebar,
|
|
6177
|
+
header,
|
|
6178
|
+
padded = true,
|
|
6179
|
+
className,
|
|
6180
|
+
children,
|
|
6181
|
+
ref,
|
|
6182
|
+
...props
|
|
6183
|
+
}) => /* @__PURE__ */ jsxs(
|
|
6184
|
+
"div",
|
|
6185
|
+
{
|
|
6186
|
+
ref,
|
|
6187
|
+
className: cn("app_shell", { app_shell_with_sidebar: !!sidebar }, className),
|
|
6188
|
+
...props,
|
|
6189
|
+
children: [
|
|
6190
|
+
sidebar && /* @__PURE__ */ jsx("div", { className: "app_shell_sidebar", children: sidebar }),
|
|
6191
|
+
/* @__PURE__ */ jsxs("div", { className: "app_shell_body", children: [
|
|
6192
|
+
header && /* @__PURE__ */ jsx("div", { className: "app_shell_header", children: header }),
|
|
6193
|
+
/* @__PURE__ */ jsx("main", { className: cn("app_shell_main", { app_shell_main_padded: padded }), children })
|
|
6194
|
+
] })
|
|
6195
|
+
]
|
|
6196
|
+
}
|
|
6197
|
+
);
|
|
5013
6198
|
var Container = ({
|
|
5014
6199
|
size = "xl",
|
|
5015
6200
|
center = true,
|
|
5016
|
-
as
|
|
6201
|
+
as,
|
|
5017
6202
|
ref,
|
|
5018
6203
|
className,
|
|
5019
6204
|
children,
|
|
5020
6205
|
...props
|
|
5021
6206
|
}) => {
|
|
6207
|
+
const Tag = as ?? "div";
|
|
5022
6208
|
return /* @__PURE__ */ jsx(
|
|
5023
6209
|
Tag,
|
|
5024
6210
|
{
|
|
@@ -5036,7 +6222,7 @@ var Grid = ({
|
|
|
5036
6222
|
rowGap,
|
|
5037
6223
|
colGap,
|
|
5038
6224
|
singleColOnMobile = true,
|
|
5039
|
-
as
|
|
6225
|
+
as,
|
|
5040
6226
|
ref,
|
|
5041
6227
|
className,
|
|
5042
6228
|
children,
|
|
@@ -5044,6 +6230,7 @@ var Grid = ({
|
|
|
5044
6230
|
...props
|
|
5045
6231
|
}) => {
|
|
5046
6232
|
const gridTemplateColumns = cols === "auto" ? `repeat(auto-fill, minmax(${minColWidth}, 1fr))` : `repeat(${cols}, 1fr)`;
|
|
6233
|
+
const Tag = as ?? "div";
|
|
5047
6234
|
return /* @__PURE__ */ jsx(
|
|
5048
6235
|
Tag,
|
|
5049
6236
|
{
|
|
@@ -5061,15 +6248,36 @@ var Grid = ({
|
|
|
5061
6248
|
}
|
|
5062
6249
|
);
|
|
5063
6250
|
};
|
|
6251
|
+
var PageHeader = ({
|
|
6252
|
+
title,
|
|
6253
|
+
description,
|
|
6254
|
+
breadcrumb,
|
|
6255
|
+
actions,
|
|
6256
|
+
tabs,
|
|
6257
|
+
className,
|
|
6258
|
+
ref,
|
|
6259
|
+
...props
|
|
6260
|
+
}) => /* @__PURE__ */ jsxs("div", { ref, className: cn("page_header", className), ...props, children: [
|
|
6261
|
+
breadcrumb && /* @__PURE__ */ jsx("div", { className: "page_header_breadcrumb", children: breadcrumb }),
|
|
6262
|
+
/* @__PURE__ */ jsxs("div", { className: "page_header_bar", children: [
|
|
6263
|
+
/* @__PURE__ */ jsxs("div", { className: "page_header_titles", children: [
|
|
6264
|
+
/* @__PURE__ */ jsx("h1", { className: "page_header_title", children: title }),
|
|
6265
|
+
description && /* @__PURE__ */ jsx("p", { className: "page_header_description", children: description })
|
|
6266
|
+
] }),
|
|
6267
|
+
actions && /* @__PURE__ */ jsx("div", { className: "page_header_actions", children: actions })
|
|
6268
|
+
] }),
|
|
6269
|
+
tabs && /* @__PURE__ */ jsx("div", { className: "page_header_tabs", children: tabs })
|
|
6270
|
+
] });
|
|
5064
6271
|
var Section = ({
|
|
5065
6272
|
spacing: spacing2 = "md",
|
|
5066
6273
|
bg = "default",
|
|
5067
|
-
as
|
|
6274
|
+
as,
|
|
5068
6275
|
ref,
|
|
5069
6276
|
className,
|
|
5070
6277
|
children,
|
|
5071
6278
|
...props
|
|
5072
6279
|
}) => {
|
|
6280
|
+
const Tag = as ?? "section";
|
|
5073
6281
|
return /* @__PURE__ */ jsx(
|
|
5074
6282
|
Tag,
|
|
5075
6283
|
{
|
|
@@ -5086,13 +6294,14 @@ var Stack = ({
|
|
|
5086
6294
|
align,
|
|
5087
6295
|
justify,
|
|
5088
6296
|
wrap,
|
|
5089
|
-
as
|
|
6297
|
+
as,
|
|
5090
6298
|
ref,
|
|
5091
6299
|
className,
|
|
5092
6300
|
children,
|
|
5093
6301
|
style,
|
|
5094
6302
|
...props
|
|
5095
6303
|
}) => {
|
|
6304
|
+
const Tag = as ?? "div";
|
|
5096
6305
|
return /* @__PURE__ */ jsx(
|
|
5097
6306
|
Tag,
|
|
5098
6307
|
{
|
|
@@ -5112,4 +6321,4 @@ var Stack = ({
|
|
|
5112
6321
|
);
|
|
5113
6322
|
};
|
|
5114
6323
|
|
|
5115
|
-
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, Prose, 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 };
|
|
6324
|
+
export { Accordion, AlertProvider, AppShell, Avatar, Badge, BottomNav, BottomNavItem, BottomNavSpacer, Breadcrumb, Button, Card, Checkbox, Chip, Combobox, Container, DataView, DatePicker, DateRangePicker, DescriptionList, Divider, Drawer, Dropdown, EmptyState, ErrorState, Field, FileInput, Form, Grid, Hero, Icon, IconButton, ImageCropper, LinearProgress, ListItem, LocaleProvider, MediaCard, Menu, Modal, NavBar, NavLink, OtpInput, PageHeader, Pagination, Popover, Prose, Radio, RadioGroup, Section, Sidebar, SidebarItem, SidebarSection, Skeleton, Spinner, Stack, Stat, Tab, TabList, TabPanel, Table, Tabs, TagInput, TextField, Textarea, ThemeProvider, TimePicker, Timeline, ToastProvider, Toggle, Tooltip, TopLoading, a11y, baseBorderWidth, baseColors, baseTypography, borderWidth, breakpoints, catalogs, cn, colors, elevation, en, iconSize, ko, motion, opacity, radius, skeleton, spacing, typography, useAlert, useFieldControl, useFocusTrap, useListboxPopup, useLocaleName, useLocaleText, useRadioGroupContext, useReducedMotion, useSpringHover, useSpringPresence, useTheme, useToast, zIndex };
|