@x-plat/design-system 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/components/AutoResizeTextArea/index.cjs +14 -5
  2. package/dist/components/AutoResizeTextArea/index.css +15 -0
  3. package/dist/components/AutoResizeTextArea/index.d.cts +5 -0
  4. package/dist/components/AutoResizeTextArea/index.d.ts +5 -0
  5. package/dist/components/AutoResizeTextArea/index.js +14 -5
  6. package/dist/components/Badge/index.cjs +5 -1
  7. package/dist/components/Badge/index.css +1 -0
  8. package/dist/components/Badge/index.d.cts +1 -0
  9. package/dist/components/Badge/index.d.ts +1 -0
  10. package/dist/components/Badge/index.js +5 -1
  11. package/dist/components/Box/index.d.cts +3 -0
  12. package/dist/components/Box/index.d.ts +3 -0
  13. package/dist/components/Chart/index.cjs +7 -6
  14. package/dist/components/Chart/index.d.cts +12 -1
  15. package/dist/components/Chart/index.d.ts +12 -1
  16. package/dist/components/Chart/index.js +7 -6
  17. package/dist/components/ChatInput/index.cjs +20 -7
  18. package/dist/components/ChatInput/index.css +15 -0
  19. package/dist/components/ChatInput/index.d.cts +10 -0
  20. package/dist/components/ChatInput/index.d.ts +10 -0
  21. package/dist/components/ChatInput/index.js +20 -7
  22. package/dist/components/CheckBox/index.cjs +14 -5
  23. package/dist/components/CheckBox/index.css +17 -0
  24. package/dist/components/CheckBox/index.d.cts +10 -2
  25. package/dist/components/CheckBox/index.d.ts +10 -2
  26. package/dist/components/CheckBox/index.js +14 -5
  27. package/dist/components/Chip/index.d.cts +2 -0
  28. package/dist/components/Chip/index.d.ts +2 -0
  29. package/dist/components/DatePicker/index.cjs +181 -65
  30. package/dist/components/DatePicker/index.css +19 -0
  31. package/dist/components/DatePicker/index.js +181 -65
  32. package/dist/components/Drawer/index.cjs +83 -4
  33. package/dist/components/Drawer/index.d.cts +1 -0
  34. package/dist/components/Drawer/index.d.ts +1 -0
  35. package/dist/components/Drawer/index.js +83 -4
  36. package/dist/components/Dropdown/index.cjs +35 -7
  37. package/dist/components/Dropdown/index.js +35 -7
  38. package/dist/components/Editor/index.cjs +178 -21
  39. package/dist/components/Editor/index.js +178 -21
  40. package/dist/components/FieldMessage/index.cjs +8 -3
  41. package/dist/components/FieldMessage/index.css +15 -0
  42. package/dist/components/FieldMessage/index.d.cts +11 -4
  43. package/dist/components/FieldMessage/index.d.ts +11 -4
  44. package/dist/components/FieldMessage/index.js +8 -3
  45. package/dist/components/FileUpload/index.cjs +8 -3
  46. package/dist/components/FileUpload/index.css +15 -0
  47. package/dist/components/FileUpload/index.d.cts +6 -0
  48. package/dist/components/FileUpload/index.d.ts +6 -0
  49. package/dist/components/FileUpload/index.js +8 -3
  50. package/dist/components/ImageSelector/index.cjs +8 -3
  51. package/dist/components/ImageSelector/index.css +15 -0
  52. package/dist/components/ImageSelector/index.d.cts +3 -0
  53. package/dist/components/ImageSelector/index.d.ts +3 -0
  54. package/dist/components/ImageSelector/index.js +8 -3
  55. package/dist/components/Input/index.cjs +15 -5
  56. package/dist/components/Input/index.css +15 -0
  57. package/dist/components/Input/index.d.cts +8 -0
  58. package/dist/components/Input/index.d.ts +8 -0
  59. package/dist/components/Input/index.js +15 -5
  60. package/dist/components/Modal/index.cjs +84 -5
  61. package/dist/components/Modal/index.js +84 -5
  62. package/dist/components/NotificationBadge/index.cjs +5 -1
  63. package/dist/components/NotificationBadge/index.css +1 -0
  64. package/dist/components/NotificationBadge/index.d.cts +6 -2
  65. package/dist/components/NotificationBadge/index.d.ts +6 -2
  66. package/dist/components/NotificationBadge/index.js +5 -1
  67. package/dist/components/Pagination/index.cjs +6 -2
  68. package/dist/components/Pagination/index.css +1 -0
  69. package/dist/components/Pagination/index.d.cts +13 -2
  70. package/dist/components/Pagination/index.d.ts +13 -2
  71. package/dist/components/Pagination/index.js +6 -2
  72. package/dist/components/PopOver/index.cjs +34 -6
  73. package/dist/components/PopOver/index.js +34 -6
  74. package/dist/components/Progress/index.cjs +6 -2
  75. package/dist/components/Progress/index.css +1 -0
  76. package/dist/components/Progress/index.d.cts +11 -2
  77. package/dist/components/Progress/index.d.ts +11 -2
  78. package/dist/components/Progress/index.js +6 -2
  79. package/dist/components/Radio/index.cjs +14 -5
  80. package/dist/components/Radio/index.css +17 -0
  81. package/dist/components/Radio/index.d.cts +11 -2
  82. package/dist/components/Radio/index.d.ts +11 -2
  83. package/dist/components/Radio/index.js +14 -5
  84. package/dist/components/Select/index.cjs +99 -31
  85. package/dist/components/Select/index.css +54 -0
  86. package/dist/components/Select/index.d.cts +16 -1
  87. package/dist/components/Select/index.d.ts +16 -1
  88. package/dist/components/Select/index.js +99 -31
  89. package/dist/components/Skeleton/index.d.cts +3 -0
  90. package/dist/components/Skeleton/index.d.ts +3 -0
  91. package/dist/components/Spinner/index.cjs +6 -2
  92. package/dist/components/Spinner/index.css +1 -0
  93. package/dist/components/Spinner/index.d.cts +8 -2
  94. package/dist/components/Spinner/index.d.ts +8 -2
  95. package/dist/components/Spinner/index.js +6 -2
  96. package/dist/components/Stat/index.cjs +84 -0
  97. package/dist/components/Stat/index.css +96 -0
  98. package/dist/components/Stat/index.d.cts +37 -0
  99. package/dist/components/Stat/index.d.ts +37 -0
  100. package/dist/components/Stat/index.js +57 -0
  101. package/dist/components/Steps/index.cjs +6 -2
  102. package/dist/components/Steps/index.css +11 -0
  103. package/dist/components/Steps/index.d.cts +9 -2
  104. package/dist/components/Steps/index.d.ts +9 -2
  105. package/dist/components/Steps/index.js +6 -2
  106. package/dist/components/Switch/index.cjs +20 -7
  107. package/dist/components/Switch/index.css +17 -0
  108. package/dist/components/Switch/index.d.cts +15 -2
  109. package/dist/components/Switch/index.d.ts +15 -2
  110. package/dist/components/Switch/index.js +20 -7
  111. package/dist/components/Tab/index.cjs +51 -26
  112. package/dist/components/Tab/index.css +4 -0
  113. package/dist/components/Tab/index.d.cts +12 -1
  114. package/dist/components/Tab/index.d.ts +12 -1
  115. package/dist/components/Tab/index.js +51 -26
  116. package/dist/components/Tag/index.cjs +5 -3
  117. package/dist/components/Tag/index.d.cts +12 -2
  118. package/dist/components/Tag/index.d.ts +12 -2
  119. package/dist/components/Tag/index.js +5 -3
  120. package/dist/components/TextArea/index.cjs +14 -4
  121. package/dist/components/TextArea/index.css +15 -0
  122. package/dist/components/TextArea/index.d.cts +7 -0
  123. package/dist/components/TextArea/index.d.ts +7 -0
  124. package/dist/components/TextArea/index.js +14 -4
  125. package/dist/components/TimePicker/index.cjs +448 -0
  126. package/dist/components/TimePicker/index.css +172 -0
  127. package/dist/components/TimePicker/index.d.cts +42 -0
  128. package/dist/components/TimePicker/index.d.ts +42 -0
  129. package/dist/components/TimePicker/index.js +411 -0
  130. package/dist/components/Tooltip/index.cjs +4 -2
  131. package/dist/components/Tooltip/index.d.cts +11 -1
  132. package/dist/components/Tooltip/index.d.ts +11 -1
  133. package/dist/components/Tooltip/index.js +4 -2
  134. package/dist/components/index.cjs +916 -385
  135. package/dist/components/index.css +296 -0
  136. package/dist/components/index.d.cts +3 -0
  137. package/dist/components/index.d.ts +3 -0
  138. package/dist/components/index.js +914 -385
  139. package/dist/index.cjs +940 -409
  140. package/dist/index.css +296 -0
  141. package/dist/index.d.cts +3 -0
  142. package/dist/index.d.ts +3 -0
  143. package/dist/index.js +938 -409
  144. package/dist/status-njWqQWFV.d.cts +20 -0
  145. package/dist/status-njWqQWFV.d.ts +20 -0
  146. package/guidelines/AGENT_PROMPT.md +18 -3
  147. package/guidelines/Guidelines.md +3 -0
  148. package/guidelines/components/card.md +3 -3
  149. package/guidelines/components/editor.md +86 -0
  150. package/guidelines/components/feedback.md +1 -1
  151. package/guidelines/components/form.md +19 -0
  152. package/guidelines/components/navigation.md +16 -15
  153. package/guidelines/components/overlay.md +43 -4
  154. package/guidelines/components/stat.md +31 -0
  155. package/guidelines/components/time-picker.md +49 -0
  156. package/package.json +1 -1
@@ -1532,11 +1532,16 @@ var FieldMessage = (props) => {
1532
1532
  FieldMessage.displayName = "FieldMessage";
1533
1533
  var FieldMessage_default = FieldMessage;
1534
1534
  var Field = (props) => {
1535
- const { validations, children } = props;
1536
- if (!validations || validations.length === 0) return /* @__PURE__ */ jsx297(Fragment, { children });
1535
+ const { label, required = false, htmlFor, validations, children } = props;
1536
+ const hasMessages = !!validations && validations.length > 0;
1537
+ if (!label && !hasMessages) return /* @__PURE__ */ jsx297(Fragment, { children });
1537
1538
  return /* @__PURE__ */ jsxs191("div", { className: "lib-xplat-field", children: [
1539
+ label && /* @__PURE__ */ jsxs191("label", { className: "lib-xplat-field-label", htmlFor, children: [
1540
+ label,
1541
+ required && /* @__PURE__ */ jsx297("span", { className: "required", "aria-hidden": "true", children: "*" })
1542
+ ] }),
1538
1543
  children,
1539
- /* @__PURE__ */ jsx297(FieldMessage, { validations })
1544
+ hasMessages && /* @__PURE__ */ jsx297(FieldMessage, { validations })
1540
1545
  ] });
1541
1546
  };
1542
1547
  Field.displayName = "Field";
@@ -1547,7 +1552,9 @@ import { jsx as jsx298 } from "react/jsx-runtime";
1547
1552
  var MAX_HEIGHT = 400;
1548
1553
  var AutoResizeTextArea = React2.forwardRef(
1549
1554
  (props, ref) => {
1550
- const { value, className, onChange, disabled, bare = false, validations, ...textareaProps } = props;
1555
+ const { value, className, onChange, disabled, bare = false, validations, label, required, ...textareaProps } = props;
1556
+ const autoId = React2.useId();
1557
+ const fieldId = props.id ?? autoId;
1551
1558
  const localRef = React2.useRef(null);
1552
1559
  const setRefs = (el) => {
1553
1560
  localRef.current = el;
@@ -1581,6 +1588,7 @@ var AutoResizeTextArea = React2.forwardRef(
1581
1588
  "aria-invalid": hasError(validations) || void 0,
1582
1589
  ...textareaProps,
1583
1590
  ref: setRefs,
1591
+ id: fieldId,
1584
1592
  className,
1585
1593
  disabled,
1586
1594
  value,
@@ -1594,12 +1602,13 @@ var AutoResizeTextArea = React2.forwardRef(
1594
1602
  "aria-invalid": hasError(validations) || void 0,
1595
1603
  ...textareaProps,
1596
1604
  ref: setRefs,
1605
+ id: fieldId,
1597
1606
  disabled,
1598
1607
  value,
1599
1608
  onChange: handleChange
1600
1609
  }
1601
1610
  ) }) });
1602
- return /* @__PURE__ */ jsx298(Field, { validations, children: control });
1611
+ return /* @__PURE__ */ jsx298(Field, { validations, label, required, htmlFor: fieldId, children: control });
1603
1612
  }
1604
1613
  );
1605
1614
  AutoResizeTextArea.displayName = "AutoResizeTextArea";
@@ -2758,7 +2767,8 @@ var ChartLegend = ({ data, labels, type }) => {
2758
2767
  }) });
2759
2768
  };
2760
2769
  var Chart = React6.memo((props) => {
2761
- const { type, data, labels, tooltip: showTooltip = true, tooltipType = "light" } = props;
2770
+ const { variant, type, data, labels, tooltip: showTooltip = true, tooltipType = "light" } = props;
2771
+ const shape = variant ?? type ?? "line";
2762
2772
  const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
2763
2773
  const { width, height } = useChartSize(containerRef);
2764
2774
  const stableData = React6.useMemo(() => data, [JSON.stringify(data)]);
@@ -2767,11 +2777,11 @@ var Chart = React6.memo((props) => {
2767
2777
  const animate = useChartAnimation(containerRef, dataKey);
2768
2778
  const ready = width > 0 && height > 0;
2769
2779
  return /* @__PURE__ */ jsxs196("div", { className: "lib-xplat-chart", ref: containerRef, children: [
2770
- ready && type === "line" && /* @__PURE__ */ jsx306(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
2771
- ready && type === "curve" && /* @__PURE__ */ jsx306(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
2772
- ready && type === "bar" && /* @__PURE__ */ jsx306(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
2773
- ready && type === "pie" && /* @__PURE__ */ jsx306(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
2774
- ready && type === "doughnut" && /* @__PURE__ */ jsx306(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
2780
+ ready && shape === "line" && /* @__PURE__ */ jsx306(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
2781
+ ready && shape === "curve" && /* @__PURE__ */ jsx306(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
2782
+ ready && shape === "bar" && /* @__PURE__ */ jsx306(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
2783
+ ready && shape === "pie" && /* @__PURE__ */ jsx306(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
2784
+ ready && shape === "doughnut" && /* @__PURE__ */ jsx306(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
2775
2785
  ready && (type === "pie" || type === "doughnut") && /* @__PURE__ */ jsx306(ChartLegend, { data: stableData, labels: stableLabels, type }),
2776
2786
  tooltip.visible && tooltip.content && /* @__PURE__ */ jsx306(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, tooltipType, children: tooltip.content })
2777
2787
  ] });
@@ -2816,8 +2826,11 @@ var ChatInput = React7.forwardRef(
2816
2826
  buttonType = "primary",
2817
2827
  onSubmit,
2818
2828
  onChange,
2819
- validations
2829
+ validations,
2830
+ label,
2831
+ required
2820
2832
  } = props;
2833
+ const fieldId = React7.useId();
2821
2834
  const isControlled = valueProp !== void 0;
2822
2835
  const [internalValue, setInternalValue] = React7.useState("");
2823
2836
  const value = isControlled ? valueProp : internalValue;
@@ -2842,6 +2855,7 @@ var ChatInput = React7.forwardRef(
2842
2855
  /* @__PURE__ */ jsx308(
2843
2856
  AutoResizeTextArea_default,
2844
2857
  {
2858
+ id: fieldId,
2845
2859
  ref,
2846
2860
  bare: true,
2847
2861
  className: "chat-input-textarea",
@@ -2866,7 +2880,7 @@ var ChatInput = React7.forwardRef(
2866
2880
  }
2867
2881
  )
2868
2882
  ] });
2869
- return /* @__PURE__ */ jsx308(Field, { validations, children: control });
2883
+ return /* @__PURE__ */ jsx308(Field, { validations, label, required, htmlFor: fieldId, children: control });
2870
2884
  }
2871
2885
  );
2872
2886
  ChatInput.displayName = "ChatInput";
@@ -2878,6 +2892,9 @@ import { semantic } from "@x-plat/tokens-core";
2878
2892
  // src/tokens/index.ts
2879
2893
  import { cssVar } from "@x-plat/tokens-core";
2880
2894
 
2895
+ // src/tokens/interface/status.ts
2896
+ var normalizeStatus = (value) => value === "brand" ? "primary" : value;
2897
+
2881
2898
  // src/components/CheckBox/CheckBox.tsx
2882
2899
  import { jsx as jsx309, jsxs as jsxs198 } from "react/jsx-runtime";
2883
2900
  var CheckBox = (props) => {
@@ -2888,10 +2905,11 @@ var CheckBox = (props) => {
2888
2905
  onChange,
2889
2906
  disabled,
2890
2907
  size = "md",
2891
- type = "brand",
2908
+ type = "primary",
2892
2909
  validations,
2893
2910
  ...rest
2894
2911
  } = props;
2912
+ const statusType = normalizeStatus(type);
2895
2913
  const handleChange = (e) => {
2896
2914
  if (onChange) onChange(e);
2897
2915
  };
@@ -2899,7 +2917,7 @@ var CheckBox = (props) => {
2899
2917
  const checkedClasses = `checked`;
2900
2918
  const disabledClasses = "disabled";
2901
2919
  const boxClasses = disabled ? disabledClasses : checked ? checkedClasses : uncheckedClasses;
2902
- const control = /* @__PURE__ */ jsxs198("label", { className: clsx_default("lib-xplat-checkbox", size, type, className), children: [
2920
+ const control = /* @__PURE__ */ jsxs198("label", { className: clsx_default("lib-xplat-checkbox", size, statusType, className), children: [
2903
2921
  /* @__PURE__ */ jsx309(
2904
2922
  "input",
2905
2923
  {
@@ -2933,7 +2951,7 @@ Chip.displayName = "Chip";
2933
2951
  var Chip_default = Chip;
2934
2952
 
2935
2953
  // src/components/DatePicker/InputDatePicker/index.tsx
2936
- import React12 from "react";
2954
+ import React13 from "react";
2937
2955
 
2938
2956
  // src/components/Input/Input.tsx
2939
2957
  import React8 from "react";
@@ -3031,8 +3049,12 @@ var Input = React8.forwardRef((props, ref) => {
3031
3049
  suffix,
3032
3050
  disabled,
3033
3051
  validations,
3052
+ label,
3053
+ required,
3034
3054
  ...inputProps
3035
3055
  } = props;
3056
+ const autoId = React8.useId();
3057
+ const fieldId = inputProps.id ?? autoId;
3036
3058
  const localValue = formatValue(type, value);
3037
3059
  const handleChange = (e) => {
3038
3060
  let val = e.target.value;
@@ -3048,7 +3070,7 @@ var Input = React8.forwardRef((props, ref) => {
3048
3070
  onChange(event);
3049
3071
  }
3050
3072
  };
3051
- return /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
3073
+ return /* @__PURE__ */ jsx311(Field, { label, required, htmlFor: fieldId, children: /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
3052
3074
  /* @__PURE__ */ jsxs199(
3053
3075
  "div",
3054
3076
  {
@@ -3059,6 +3081,7 @@ var Input = React8.forwardRef((props, ref) => {
3059
3081
  {
3060
3082
  ...inputProps,
3061
3083
  ref,
3084
+ id: fieldId,
3062
3085
  disabled,
3063
3086
  type: type === "number" ? "text" : type,
3064
3087
  value: localValue,
@@ -3071,7 +3094,7 @@ var Input = React8.forwardRef((props, ref) => {
3071
3094
  }
3072
3095
  ),
3073
3096
  /* @__PURE__ */ jsx311(FieldMessage_default, { validations })
3074
- ] });
3097
+ ] }) });
3075
3098
  });
3076
3099
  Input.displayName = "Input";
3077
3100
  var Input_default = Input;
@@ -3101,16 +3124,96 @@ PasswordInput.displayName = "PasswordInput";
3101
3124
  var PasswordInput_default = PasswordInput;
3102
3125
 
3103
3126
  // src/components/Modal/Modal.tsx
3104
- import React10 from "react";
3127
+ import React11 from "react";
3105
3128
  import { createPortal } from "react-dom";
3129
+
3130
+ // src/tokens/hooks/useOverlayKeyboard.ts
3131
+ import React10 from "react";
3132
+ var FOCUSABLE = [
3133
+ "a[href]",
3134
+ "button:not([disabled])",
3135
+ "input:not([disabled]):not([type='hidden'])",
3136
+ "select:not([disabled])",
3137
+ "textarea:not([disabled])",
3138
+ "[tabindex]:not([tabindex='-1'])"
3139
+ ].join(",");
3140
+ var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
3141
+ // 화면에 없는 것은 제외 (display:none 등)
3142
+ (n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
3143
+ );
3144
+ var useEscapeKey = (enabled, onEscape) => {
3145
+ React10.useEffect(() => {
3146
+ if (!enabled) return;
3147
+ const onKey = (e) => {
3148
+ if (e.key !== "Escape") return;
3149
+ if (e.defaultPrevented) return;
3150
+ e.preventDefault();
3151
+ onEscape();
3152
+ };
3153
+ document.addEventListener("keydown", onKey);
3154
+ return () => document.removeEventListener("keydown", onKey);
3155
+ }, [enabled, onEscape]);
3156
+ };
3157
+ var useFocusTrap = (containerRef, enabled, options = {}) => {
3158
+ const { trap = false, initialFocus } = options;
3159
+ const restoreRef = React10.useRef(null);
3160
+ React10.useEffect(() => {
3161
+ if (!enabled) return;
3162
+ restoreRef.current = document.activeElement;
3163
+ const raf = requestAnimationFrame(() => {
3164
+ const el = containerRef.current;
3165
+ if (!el) return;
3166
+ const target = initialFocus?.current ?? focusableIn(el)[0] ?? el;
3167
+ if (!target.hasAttribute("tabindex") && !focusableIn(el).includes(target)) {
3168
+ target.setAttribute("tabindex", "-1");
3169
+ }
3170
+ target.focus({ preventScroll: true });
3171
+ });
3172
+ return () => {
3173
+ cancelAnimationFrame(raf);
3174
+ const prev = restoreRef.current;
3175
+ if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
3176
+ };
3177
+ }, [enabled, containerRef, initialFocus]);
3178
+ React10.useEffect(() => {
3179
+ if (!enabled || !trap) return;
3180
+ const onKey = (e) => {
3181
+ if (e.key !== "Tab") return;
3182
+ const el = containerRef.current;
3183
+ if (!el) return;
3184
+ const items = focusableIn(el);
3185
+ if (items.length === 0) {
3186
+ e.preventDefault();
3187
+ return;
3188
+ }
3189
+ const first = items[0];
3190
+ const last = items[items.length - 1];
3191
+ const active = document.activeElement;
3192
+ if (e.shiftKey && (active === first || !el.contains(active))) {
3193
+ e.preventDefault();
3194
+ last.focus();
3195
+ } else if (!e.shiftKey && (active === last || !el.contains(active))) {
3196
+ e.preventDefault();
3197
+ first.focus();
3198
+ }
3199
+ };
3200
+ document.addEventListener("keydown", onKey);
3201
+ return () => document.removeEventListener("keydown", onKey);
3202
+ }, [enabled, trap, containerRef]);
3203
+ };
3204
+
3205
+ // src/components/Modal/Modal.tsx
3106
3206
  import { jsx as jsx313 } from "react/jsx-runtime";
3107
3207
  var ANIMATION_DURATION_MS = 200;
3108
3208
  var Modal = (props) => {
3109
3209
  const { isOpen, onClose, children } = props;
3110
- const [mounted, setMounted] = React10.useState(false);
3111
- const [visible, setVisible] = React10.useState(false);
3112
- const [settled, setSettled] = React10.useState(false);
3113
- React10.useEffect(() => {
3210
+ const [mounted, setMounted] = React11.useState(false);
3211
+ const [visible, setVisible] = React11.useState(false);
3212
+ const [settled, setSettled] = React11.useState(false);
3213
+ const boxRef = React11.useRef(null);
3214
+ useEscapeKey(isOpen, onClose);
3215
+ useFocusTrap(boxRef, isOpen && mounted, { trap: true });
3216
+ React11.useEffect(() => {
3114
3217
  if (isOpen) {
3115
3218
  setMounted(true);
3116
3219
  const show = setTimeout(() => setVisible(true), 1);
@@ -3137,6 +3240,7 @@ var Modal = (props) => {
3137
3240
  children: /* @__PURE__ */ jsx313(
3138
3241
  "div",
3139
3242
  {
3243
+ ref: boxRef,
3140
3244
  className: clsx_default("lib-xplat-modal", "modal-box", stateClass, settled && "settled"),
3141
3245
  role: "dialog",
3142
3246
  "aria-modal": "true",
@@ -3153,9 +3257,9 @@ Modal.displayName = "Modal";
3153
3257
  var Modal_default = Modal;
3154
3258
 
3155
3259
  // src/components/DatePicker/SingleDatePicker/index.tsx
3156
- import React11 from "react";
3260
+ import React12 from "react";
3157
3261
  import { Fragment as Fragment4, jsx as jsx314, jsxs as jsxs200 } from "react/jsx-runtime";
3158
- var DayCell2 = React11.memo(
3262
+ var DayCell2 = React12.memo(
3159
3263
  ({
3160
3264
  day,
3161
3265
  disabled,
@@ -3207,26 +3311,26 @@ var SingleDatePicker = (props) => {
3207
3311
  initialYear,
3208
3312
  initialMonth
3209
3313
  );
3210
- const [pickerMode, setPickerMode] = React11.useState("days");
3211
- const [yearRangeStart, setYearRangeStart] = React11.useState(
3314
+ const [pickerMode, setPickerMode] = React12.useState("days");
3315
+ const [yearRangeStart, setYearRangeStart] = React12.useState(
3212
3316
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
3213
3317
  );
3214
- const minTime = React11.useMemo(
3318
+ const minTime = React12.useMemo(
3215
3319
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
3216
3320
  [minDate]
3217
3321
  );
3218
- const maxTime = React11.useMemo(
3322
+ const maxTime = React12.useMemo(
3219
3323
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
3220
3324
  [maxDate]
3221
3325
  );
3222
- const highlightSet = React11.useMemo(() => {
3326
+ const highlightSet = React12.useMemo(() => {
3223
3327
  const set = /* @__PURE__ */ new Set();
3224
3328
  for (const h of highlightDates) {
3225
3329
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
3226
3330
  }
3227
3331
  return set;
3228
3332
  }, [highlightDates]);
3229
- const handleSelect = React11.useCallback(
3333
+ const handleSelect = React12.useCallback(
3230
3334
  (date) => {
3231
3335
  onChange?.(date);
3232
3336
  },
@@ -3355,8 +3459,8 @@ var formatDate = (date) => {
3355
3459
  };
3356
3460
  var InputDatePicker = (props) => {
3357
3461
  const { value, onChange, minDate, maxDate, disabled, locale = "ko", placeholder } = props;
3358
- const [isOpen, setIsOpen] = React12.useState(false);
3359
- const [tempDate, setTempDate] = React12.useState(value ?? /* @__PURE__ */ new Date());
3462
+ const [isOpen, setIsOpen] = React13.useState(false);
3463
+ const [tempDate, setTempDate] = React13.useState(value ?? /* @__PURE__ */ new Date());
3360
3464
  const handleOpen = () => {
3361
3465
  if (disabled) return;
3362
3466
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -3405,23 +3509,27 @@ InputDatePicker.displayName = "InputDatePicker";
3405
3509
  var InputDatePicker_default = InputDatePicker;
3406
3510
 
3407
3511
  // src/components/DatePicker/PopupPicker/index.tsx
3408
- import React16 from "react";
3512
+ import React17 from "react";
3409
3513
 
3410
3514
  // src/components/DatePicker/RangePicker/index.tsx
3411
- import React15 from "react";
3515
+ import React16 from "react";
3412
3516
 
3413
3517
  // src/components/Tab/Tab.tsx
3414
- import React14 from "react";
3518
+ import React15 from "react";
3415
3519
 
3416
3520
  // src/components/Tab/TabItem.tsx
3417
- import React13 from "react";
3521
+ import React14 from "react";
3418
3522
  import { jsx as jsx316 } from "react/jsx-runtime";
3419
- var TabItem = React13.forwardRef((props, ref) => {
3523
+ var TabItem = React14.forwardRef((props, ref) => {
3420
3524
  const { isActive: isActive2, title, onClick } = props;
3421
3525
  return /* @__PURE__ */ jsx316(
3422
- "div",
3526
+ "button",
3423
3527
  {
3424
3528
  ref,
3529
+ type: "button",
3530
+ role: "tab",
3531
+ "aria-selected": isActive2,
3532
+ tabIndex: isActive2 ? 0 : -1,
3425
3533
  className: clsx_default("tab-item", isActive2 ? "active" : null),
3426
3534
  onClick,
3427
3535
  children: title
@@ -3434,45 +3542,66 @@ var TabItem_default = TabItem;
3434
3542
  // src/components/Tab/Tab.tsx
3435
3543
  import { jsx as jsx317, jsxs as jsxs202 } from "react/jsx-runtime";
3436
3544
  var Tab = (props) => {
3437
- const { activeIndex, onChange, tabs, type, size = "md" } = props;
3438
- const [underlineStyle, setUnderlineStyle] = React14.useState({
3545
+ const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
3546
+ const shape = variant ?? type ?? "default";
3547
+ const [underlineStyle, setUnderlineStyle] = React15.useState({
3439
3548
  left: 0,
3440
3549
  width: 0
3441
3550
  });
3442
- const itemRefs = React14.useRef([]);
3551
+ const itemRefs = React15.useRef([]);
3552
+ const handleKeyDown = (e) => {
3553
+ const last = tabs.length - 1;
3554
+ let next = null;
3555
+ if (e.key === "ArrowRight") next = activeIndex >= last ? 0 : activeIndex + 1;
3556
+ else if (e.key === "ArrowLeft") next = activeIndex <= 0 ? last : activeIndex - 1;
3557
+ else if (e.key === "Home") next = 0;
3558
+ else if (e.key === "End") next = last;
3559
+ if (next === null) return;
3560
+ e.preventDefault();
3561
+ onChange(tabs[next], next);
3562
+ itemRefs.current[next]?.focus();
3563
+ };
3443
3564
  const handleChangeActiveTab = (tabItem, tabIdx) => {
3444
3565
  onChange(tabItem, tabIdx);
3445
3566
  };
3446
- React14.useEffect(() => {
3567
+ React15.useEffect(() => {
3447
3568
  const el = itemRefs.current[activeIndex];
3448
3569
  if (el) {
3449
3570
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
3450
3571
  }
3451
3572
  }, [activeIndex, tabs.length]);
3452
- return /* @__PURE__ */ jsxs202("div", { className: clsx_default("lib-xplat-tab", `type-${type}`, size), children: [
3453
- tabs.map((tab, idx) => /* @__PURE__ */ jsx317(
3454
- TabItem_default,
3455
- {
3456
- onClick: () => handleChangeActiveTab(tab, idx),
3457
- isActive: activeIndex === idx,
3458
- ref: (el) => {
3459
- itemRefs.current[idx] = el;
3460
- },
3461
- title: tab.title
3462
- },
3463
- `${tab.value}_${idx}`
3464
- )),
3465
- type === "toggle" && /* @__PURE__ */ jsx317(
3466
- "div",
3467
- {
3468
- className: "tab-toggle-underline",
3469
- style: {
3470
- left: underlineStyle.left,
3471
- width: underlineStyle.width
3472
- }
3473
- }
3474
- )
3475
- ] });
3573
+ return /* @__PURE__ */ jsxs202(
3574
+ "div",
3575
+ {
3576
+ className: clsx_default("lib-xplat-tab", `type-${shape}`, size),
3577
+ role: "tablist",
3578
+ onKeyDown: handleKeyDown,
3579
+ children: [
3580
+ tabs.map((tab, idx) => /* @__PURE__ */ jsx317(
3581
+ TabItem_default,
3582
+ {
3583
+ onClick: () => handleChangeActiveTab(tab, idx),
3584
+ isActive: activeIndex === idx,
3585
+ ref: (el) => {
3586
+ itemRefs.current[idx] = el;
3587
+ },
3588
+ title: tab.title
3589
+ },
3590
+ `${tab.value}_${idx}`
3591
+ )),
3592
+ shape === "toggle" && /* @__PURE__ */ jsx317(
3593
+ "div",
3594
+ {
3595
+ className: "tab-toggle-underline",
3596
+ style: {
3597
+ left: underlineStyle.left,
3598
+ width: underlineStyle.width
3599
+ }
3600
+ }
3601
+ )
3602
+ ]
3603
+ }
3604
+ );
3476
3605
  };
3477
3606
  Tab.displayName = "Tab";
3478
3607
  var Tab_default = Tab;
@@ -3488,7 +3617,7 @@ var RangePicker = (props) => {
3488
3617
  maxDate,
3489
3618
  locale = "ko"
3490
3619
  } = props;
3491
- const [activeTab, setActiveTab] = React15.useState("start");
3620
+ const [activeTab, setActiveTab] = React16.useState("start");
3492
3621
  const handleStartChange = (date) => {
3493
3622
  if (!date) return;
3494
3623
  const newStart = date > endDate ? endDate : date;
@@ -3573,7 +3702,7 @@ var RangePicker_default = RangePicker;
3573
3702
  import { jsx as jsx319, jsxs as jsxs204 } from "react/jsx-runtime";
3574
3703
  var PopupPicker = (props) => {
3575
3704
  const { component, type, locale } = props;
3576
- const [isOpen, setIsOpen] = React16.useState(false);
3705
+ const [isOpen, setIsOpen] = React17.useState(false);
3577
3706
  const handleClick = () => setIsOpen(true);
3578
3707
  const handleClose = () => setIsOpen(false);
3579
3708
  const handleSingleChange = (date) => {
@@ -3582,7 +3711,7 @@ var PopupPicker = (props) => {
3582
3711
  handleClose();
3583
3712
  };
3584
3713
  return /* @__PURE__ */ jsxs204("div", { className: "lib-xplat-popup-datepicker", children: [
3585
- React16.cloneElement(component, { onClick: handleClick }),
3714
+ React17.cloneElement(component, { onClick: handleClick }),
3586
3715
  /* @__PURE__ */ jsx319(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ jsxs204("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
3587
3716
  /* @__PURE__ */ jsxs204("div", { className: "popup-datepicker-content", children: [
3588
3717
  type === "single" && /* @__PURE__ */ jsx319(
@@ -3641,15 +3770,18 @@ Divider.displayName = "Divider";
3641
3770
  var Divider_default = Divider;
3642
3771
 
3643
3772
  // src/components/Drawer/Drawer.tsx
3644
- import React17 from "react";
3773
+ import React18 from "react";
3645
3774
  import { createPortal as createPortal2 } from "react-dom";
3646
3775
  import { jsx as jsx321, jsxs as jsxs205 } from "react/jsx-runtime";
3647
3776
  var ANIMATION_DURATION_MS2 = 250;
3648
3777
  var Drawer = (props) => {
3649
3778
  const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
3650
- const [mounted, setMounted] = React17.useState(false);
3651
- const [visible, setVisible] = React17.useState(false);
3652
- React17.useEffect(() => {
3779
+ const [mounted, setMounted] = React18.useState(false);
3780
+ const [visible, setVisible] = React18.useState(false);
3781
+ const panelRef = React18.useRef(null);
3782
+ useEscapeKey(isOpen, onClose);
3783
+ useFocusTrap(panelRef, isOpen && mounted, { trap: true });
3784
+ React18.useEffect(() => {
3653
3785
  if (isOpen) {
3654
3786
  setMounted(true);
3655
3787
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -3671,6 +3803,7 @@ var Drawer = (props) => {
3671
3803
  children: /* @__PURE__ */ jsxs205(
3672
3804
  "div",
3673
3805
  {
3806
+ ref: panelRef,
3674
3807
  className: clsx_default("lib-xplat-drawer", placement, size, stateClass),
3675
3808
  role: "dialog",
3676
3809
  "aria-modal": "true",
@@ -3693,7 +3826,7 @@ Drawer.displayName = "Drawer";
3693
3826
  var Drawer_default = Drawer;
3694
3827
 
3695
3828
  // src/components/Dropdown/Dropdown.tsx
3696
- import React20 from "react";
3829
+ import React21 from "react";
3697
3830
 
3698
3831
  // src/tokens/hooks/Portal.tsx
3699
3832
  import ReactDOM from "react-dom";
@@ -3705,13 +3838,13 @@ Portal.displayName = "Portal";
3705
3838
  var Portal_default = Portal;
3706
3839
 
3707
3840
  // src/tokens/hooks/useAutoPosition.ts
3708
- import React18 from "react";
3841
+ import React19 from "react";
3709
3842
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3710
- const [position, setPosition] = React18.useState({
3843
+ const [position, setPosition] = React19.useState({
3711
3844
  position: {},
3712
3845
  direction: "bottom"
3713
3846
  });
3714
- const calculatePosition = React18.useCallback(() => {
3847
+ const calculatePosition = React19.useCallback(() => {
3715
3848
  if (!triggerRef.current || !popRef.current) return;
3716
3849
  const triggerRect = triggerRef.current.getBoundingClientRect();
3717
3850
  const popW = popRef.current.offsetWidth;
@@ -3738,13 +3871,13 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3738
3871
  direction
3739
3872
  });
3740
3873
  }, [triggerRef, popRef]);
3741
- React18.useLayoutEffect(() => {
3874
+ React19.useLayoutEffect(() => {
3742
3875
  if (!enabled) return;
3743
3876
  calculatePosition();
3744
3877
  const raf = requestAnimationFrame(calculatePosition);
3745
3878
  return () => cancelAnimationFrame(raf);
3746
3879
  }, [calculatePosition, enabled]);
3747
- React18.useEffect(() => {
3880
+ React19.useEffect(() => {
3748
3881
  if (!enabled || !popRef.current) return;
3749
3882
  const observer = new ResizeObserver(() => {
3750
3883
  calculatePosition();
@@ -3752,7 +3885,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3752
3885
  observer.observe(popRef.current);
3753
3886
  return () => observer.disconnect();
3754
3887
  }, [calculatePosition, enabled, popRef]);
3755
- React18.useEffect(() => {
3888
+ React19.useEffect(() => {
3756
3889
  if (!enabled) return;
3757
3890
  window.addEventListener("resize", calculatePosition);
3758
3891
  window.addEventListener("scroll", calculatePosition, true);
@@ -3766,9 +3899,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3766
3899
  var useAutoPosition_default = useAutoPosition;
3767
3900
 
3768
3901
  // src/tokens/hooks/useClickOutside.ts
3769
- import React19 from "react";
3902
+ import React20 from "react";
3770
3903
  var useClickOutside = (refs, handler, enabled = true) => {
3771
- React19.useEffect(() => {
3904
+ React20.useEffect(() => {
3772
3905
  if (!enabled) return;
3773
3906
  const refArray = Array.isArray(refs) ? refs : [refs];
3774
3907
  const listener = (event) => {
@@ -3794,14 +3927,18 @@ var useClickOutside_default = useClickOutside;
3794
3927
  import { jsx as jsx322, jsxs as jsxs206 } from "react/jsx-runtime";
3795
3928
  var Dropdown = (props) => {
3796
3929
  const { items, children } = props;
3797
- const [isOpen, setIsOpen] = React20.useState(false);
3798
- const [mounted, setMounted] = React20.useState(false);
3799
- const [visible, setVisible] = React20.useState(false);
3800
- const triggerRef = React20.useRef(null);
3801
- const menuRef = React20.useRef(null);
3930
+ const [isOpen, setIsOpen] = React21.useState(false);
3931
+ const [mounted, setMounted] = React21.useState(false);
3932
+ const [visible, setVisible] = React21.useState(false);
3933
+ const triggerRef = React21.useRef(null);
3934
+ const menuRef = React21.useRef(null);
3802
3935
  const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
3803
3936
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
3804
- React20.useEffect(() => {
3937
+ useEscapeKey(isOpen, () => {
3938
+ setIsOpen(false);
3939
+ triggerRef.current?.focus({ preventScroll: true });
3940
+ });
3941
+ React21.useEffect(() => {
3805
3942
  if (isOpen) {
3806
3943
  setMounted(true);
3807
3944
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -3855,7 +3992,7 @@ Dropdown.displayName = "Dropdown";
3855
3992
  var Dropdown_default = Dropdown;
3856
3993
 
3857
3994
  // src/components/Editor/Editor.tsx
3858
- import React21 from "react";
3995
+ import React22 from "react";
3859
3996
  import { jsx as jsx323, jsxs as jsxs207 } from "react/jsx-runtime";
3860
3997
  var DEFAULT_TOOLBAR = [
3861
3998
  "bold",
@@ -3905,6 +4042,15 @@ var ALLOWED_ATTRS = {
3905
4042
  a: ["href", "target", "rel"],
3906
4043
  img: ["src", "alt"]
3907
4044
  };
4045
+ var DROP_WITH_CONTENT = /* @__PURE__ */ new Set([
4046
+ "script",
4047
+ "style",
4048
+ "noscript",
4049
+ "iframe",
4050
+ "object",
4051
+ "embed",
4052
+ "template"
4053
+ ]);
3908
4054
  var sanitizeHtml = (input) => {
3909
4055
  const doc = new DOMParser().parseFromString(`<div>${input}</div>`, "text/html");
3910
4056
  const root = doc.body.firstElementChild;
@@ -3913,6 +4059,10 @@ var sanitizeHtml = (input) => {
3913
4059
  const children = Array.from(node.children);
3914
4060
  for (const child of children) {
3915
4061
  const tag = child.tagName.toLowerCase();
4062
+ if (DROP_WITH_CONTENT.has(tag)) {
4063
+ node.removeChild(child);
4064
+ continue;
4065
+ }
3916
4066
  if (!ALLOWED_TAGS.has(tag)) {
3917
4067
  while (child.firstChild) node.insertBefore(child.firstChild, child);
3918
4068
  node.removeChild(child);
@@ -3963,26 +4113,30 @@ var Editor = (props) => {
3963
4113
  onImageUpload,
3964
4114
  minHeight = 200
3965
4115
  } = props;
3966
- const editorRef = React21.useRef(null);
3967
- const lastRangeRef = React21.useRef(null);
3968
- const composingRef = React21.useRef(false);
3969
- const [isFocused, setIsFocused] = React21.useState(false);
3970
- const [isEmpty, setIsEmpty] = React21.useState(!value);
3971
- const [activeFormats, setActiveFormats] = React21.useState(/* @__PURE__ */ new Set());
3972
- const [slashOpen, setSlashOpen] = React21.useState(false);
3973
- const [slashFilter, setSlashFilter] = React21.useState("");
3974
- const [slashIdx, setSlashIdx] = React21.useState(0);
3975
- const [slashPos, setSlashPos] = React21.useState({ top: 0, left: 0 });
3976
- const slashStartRangeRef = React21.useRef(null);
3977
- const [linkOpen, setLinkOpen] = React21.useState(false);
3978
- const [linkValue, setLinkValue] = React21.useState("");
3979
- const [linkPos, setLinkPos] = React21.useState({ top: 0, left: 0 });
3980
- React21.useEffect(() => {
3981
- if (!editorRef.current) return;
3982
- if (editorRef.current.innerHTML !== value) {
3983
- editorRef.current.innerHTML = sanitizeHtml(value || "");
3984
- updateEmpty();
3985
- }
4116
+ const editorRef = React22.useRef(null);
4117
+ const lastRangeRef = React22.useRef(null);
4118
+ const composingRef = React22.useRef(false);
4119
+ const [isFocused, setIsFocused] = React22.useState(false);
4120
+ const [isEmpty, setIsEmpty] = React22.useState(!value);
4121
+ const [activeFormats, setActiveFormats] = React22.useState(/* @__PURE__ */ new Set());
4122
+ const [slashOpen, setSlashOpen] = React22.useState(false);
4123
+ const [slashFilter, setSlashFilter] = React22.useState("");
4124
+ const [slashIdx, setSlashIdx] = React22.useState(0);
4125
+ const [slashPos, setSlashPos] = React22.useState({ top: 0, left: 0 });
4126
+ const slashStartRangeRef = React22.useRef(null);
4127
+ const [linkOpen, setLinkOpen] = React22.useState(false);
4128
+ const [linkValue, setLinkValue] = React22.useState("");
4129
+ const [linkPos, setLinkPos] = React22.useState({ top: 0, left: 0 });
4130
+ const lastEmittedRef = React22.useRef(null);
4131
+ React22.useEffect(() => {
4132
+ const el = editorRef.current;
4133
+ if (!el) return;
4134
+ if (value === lastEmittedRef.current) return;
4135
+ if (el.innerHTML === value) return;
4136
+ el.innerHTML = sanitizeHtml(value || "");
4137
+ if (!el.firstChild) el.innerHTML = "<p><br></p>";
4138
+ lastEmittedRef.current = null;
4139
+ updateEmpty();
3986
4140
  }, [value]);
3987
4141
  const updateEmpty = () => {
3988
4142
  const el = editorRef.current;
@@ -3998,10 +4152,19 @@ var Editor = (props) => {
3998
4152
  }
3999
4153
  };
4000
4154
  const restoreSelection = () => {
4001
- if (!lastRangeRef.current) return;
4155
+ const range = lastRangeRef.current;
4156
+ if (!range) return;
4157
+ if (!editorRef.current?.contains(range.startContainer)) {
4158
+ lastRangeRef.current = null;
4159
+ return;
4160
+ }
4002
4161
  const sel = window.getSelection();
4003
- sel?.removeAllRanges();
4004
- sel?.addRange(lastRangeRef.current);
4162
+ try {
4163
+ sel?.removeAllRanges();
4164
+ sel?.addRange(range);
4165
+ } catch {
4166
+ lastRangeRef.current = null;
4167
+ }
4005
4168
  };
4006
4169
  const updateActiveFormats = () => {
4007
4170
  if (!editorRef.current) return;
@@ -4030,6 +4193,96 @@ var Editor = (props) => {
4030
4193
  const setBlock = (tag) => {
4031
4194
  exec("formatBlock", tag);
4032
4195
  };
4196
+ const closestPre = () => {
4197
+ const sel = window.getSelection();
4198
+ const node = sel?.anchorNode;
4199
+ if (!node || !editorRef.current?.contains(node)) return null;
4200
+ const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
4201
+ return el?.closest("pre") ?? null;
4202
+ };
4203
+ const insertCodeBlock = () => {
4204
+ const el = editorRef.current;
4205
+ const sel = window.getSelection();
4206
+ if (!el || !sel || sel.rangeCount === 0) return;
4207
+ const existing = closestPre();
4208
+ if (existing) {
4209
+ const p = document.createElement("p");
4210
+ p.textContent = existing.textContent || "";
4211
+ if (!p.textContent) p.innerHTML = "<br>";
4212
+ existing.replaceWith(p);
4213
+ placeCaretAtEnd(p);
4214
+ handleInput();
4215
+ return;
4216
+ }
4217
+ const range = sel.getRangeAt(0);
4218
+ const frag = range.cloneContents();
4219
+ const holder = document.createElement("div");
4220
+ holder.appendChild(frag);
4221
+ const BLOCK = /^(p|div|h[1-6]|li|blockquote|pre|tr)$/i;
4222
+ const linesOf = (node) => {
4223
+ const out = [];
4224
+ let cur = "";
4225
+ for (const child of Array.from(node.childNodes)) {
4226
+ if (child.nodeType === Node.TEXT_NODE) {
4227
+ cur += child.textContent || "";
4228
+ } else if (child.nodeName === "BR") {
4229
+ out.push(cur);
4230
+ cur = "";
4231
+ } else if (BLOCK.test(child.nodeName)) {
4232
+ if (cur) {
4233
+ out.push(cur);
4234
+ cur = "";
4235
+ }
4236
+ const sub = linesOf(child);
4237
+ out.push(...sub.length > 0 ? sub : [""]);
4238
+ } else {
4239
+ cur += linesOf(child).join("\n");
4240
+ }
4241
+ }
4242
+ if (cur) out.push(cur);
4243
+ return out;
4244
+ };
4245
+ const text = linesOf(holder).join("\n").replace(/\n+$/, "");
4246
+ const pre = document.createElement("pre");
4247
+ const code = document.createElement("code");
4248
+ code.textContent = text || "";
4249
+ pre.appendChild(code);
4250
+ range.deleteContents();
4251
+ range.insertNode(pre);
4252
+ ensureParagraphAfter(pre);
4253
+ placeCaretAtEnd(code);
4254
+ handleInput();
4255
+ };
4256
+ const insertTextAtCaret = (text) => {
4257
+ const sel = window.getSelection();
4258
+ if (!sel || sel.rangeCount === 0) return;
4259
+ const range = sel.getRangeAt(0);
4260
+ range.deleteContents();
4261
+ const node = document.createTextNode(text);
4262
+ range.insertNode(node);
4263
+ range.setStartAfter(node);
4264
+ range.collapse(true);
4265
+ sel.removeAllRanges();
4266
+ sel.addRange(range);
4267
+ handleInput();
4268
+ };
4269
+ const ensureParagraphAfter = (node) => {
4270
+ const next = node.nextElementSibling;
4271
+ if (next && next.tagName === "P") return;
4272
+ const p = document.createElement("p");
4273
+ p.innerHTML = "<br>";
4274
+ node.after(p);
4275
+ };
4276
+ const placeCaretAtEnd = (node) => {
4277
+ const sel = window.getSelection();
4278
+ if (!sel) return;
4279
+ const r2 = document.createRange();
4280
+ r2.selectNodeContents(node);
4281
+ r2.collapse(false);
4282
+ sel.removeAllRanges();
4283
+ sel.addRange(r2);
4284
+ editorRef.current?.focus();
4285
+ };
4033
4286
  const insertDivider = () => {
4034
4287
  exec("insertHorizontalRule");
4035
4288
  const el = editorRef.current;
@@ -4076,7 +4329,9 @@ var Editor = (props) => {
4076
4329
  const range = sel.getRangeAt(0);
4077
4330
  slashStartRangeRef.current = range.cloneRange();
4078
4331
  const rect = range.getBoundingClientRect();
4079
- const editorRect = editorRef.current.getBoundingClientRect();
4332
+ const editorEl = editorRef.current;
4333
+ if (!editorEl) return;
4334
+ const editorRect = editorEl.getBoundingClientRect();
4080
4335
  setSlashPos({
4081
4336
  top: rect.bottom - editorRect.top + 4,
4082
4337
  left: rect.left - editorRect.left
@@ -4091,7 +4346,7 @@ var Editor = (props) => {
4091
4346
  setSlashIdx(0);
4092
4347
  slashStartRangeRef.current = null;
4093
4348
  };
4094
- const filteredSlashItems = React21.useMemo(() => {
4349
+ const filteredSlashItems = React22.useMemo(() => {
4095
4350
  if (!slashFilter) return SLASH_ITEMS;
4096
4351
  const f = slashFilter.toLowerCase();
4097
4352
  return SLASH_ITEMS.filter((it) => it.label.toLowerCase().includes(f) || it.key.includes(f));
@@ -4134,7 +4389,7 @@ var Editor = (props) => {
4134
4389
  setBlock("blockquote");
4135
4390
  break;
4136
4391
  case "code-block":
4137
- setBlock("pre");
4392
+ insertCodeBlock();
4138
4393
  break;
4139
4394
  case "divider":
4140
4395
  insertDivider();
@@ -4152,7 +4407,9 @@ var Editor = (props) => {
4152
4407
  if (!sel || sel.rangeCount === 0) return;
4153
4408
  const range = sel.getRangeAt(0);
4154
4409
  const rect = range.getBoundingClientRect();
4155
- const editorRect = editorRef.current.getBoundingClientRect();
4410
+ const editorEl2 = editorRef.current;
4411
+ if (!editorEl2) return;
4412
+ const editorRect = editorEl2.getBoundingClientRect();
4156
4413
  setLinkPos({
4157
4414
  top: rect.bottom - editorRect.top + 4,
4158
4415
  left: rect.left - editorRect.left
@@ -4185,13 +4442,13 @@ var Editor = (props) => {
4185
4442
  if (node.nodeType !== Node.TEXT_NODE) return false;
4186
4443
  const text = (node.textContent || "").slice(0, range.startOffset);
4187
4444
  const patterns = [
4188
- [/^###\s$/, () => setBlock("h3")],
4189
- [/^##\s$/, () => setBlock("h2")],
4190
- [/^#\s$/, () => setBlock("h1")],
4191
- [/^-\s$/, () => exec("insertUnorderedList")],
4192
- [/^\*\s$/, () => exec("insertUnorderedList")],
4193
- [/^1\.\s$/, () => exec("insertOrderedList")],
4194
- [/^>\s$/, () => setBlock("blockquote")]
4445
+ [/^###$/, () => setBlock("h3")],
4446
+ [/^##$/, () => setBlock("h2")],
4447
+ [/^#$/, () => setBlock("h1")],
4448
+ [/^-$/, () => exec("insertUnorderedList")],
4449
+ [/^\*$/, () => exec("insertUnorderedList")],
4450
+ [/^1\.$/, () => exec("insertOrderedList")],
4451
+ [/^>$/, () => setBlock("blockquote")]
4195
4452
  ];
4196
4453
  for (const [re, fn] of patterns) {
4197
4454
  if (re.test(text)) {
@@ -4211,7 +4468,9 @@ var Editor = (props) => {
4211
4468
  if (composingRef.current) return;
4212
4469
  const el = editorRef.current;
4213
4470
  if (!el) return;
4214
- onChange?.(el.innerHTML);
4471
+ const html = el.innerHTML;
4472
+ lastEmittedRef.current = html;
4473
+ onChange?.(html);
4215
4474
  updateEmpty();
4216
4475
  updateActiveFormats();
4217
4476
  if (slashOpen) {
@@ -4239,6 +4498,31 @@ var Editor = (props) => {
4239
4498
  };
4240
4499
  const handleKeyDown = (e) => {
4241
4500
  if (readOnly) return;
4501
+ if (composingRef.current || e.nativeEvent.isComposing || e.keyCode === 229) return;
4502
+ const pre = closestPre();
4503
+ if (pre && !slashOpen) {
4504
+ if (e.key === "Enter" && !e.shiftKey) {
4505
+ const text = pre.textContent || "";
4506
+ if (text.endsWith("\n\n")) {
4507
+ e.preventDefault();
4508
+ const code = pre.querySelector("code") ?? pre;
4509
+ code.textContent = text.replace(/\n\n$/, "");
4510
+ ensureParagraphAfter(pre);
4511
+ const next = pre.nextElementSibling;
4512
+ if (next) placeCaretAtEnd(next);
4513
+ handleInput();
4514
+ return;
4515
+ }
4516
+ e.preventDefault();
4517
+ insertTextAtCaret("\n");
4518
+ return;
4519
+ }
4520
+ if (e.key === "Tab") {
4521
+ e.preventDefault();
4522
+ insertTextAtCaret(" ");
4523
+ return;
4524
+ }
4525
+ }
4242
4526
  if (slashOpen) {
4243
4527
  if (e.key === "ArrowDown") {
4244
4528
  e.preventDefault();
@@ -4285,6 +4569,7 @@ var Editor = (props) => {
4285
4569
  return;
4286
4570
  }
4287
4571
  }
4572
+ if (pre) return;
4288
4573
  if (enableSlashCommand && e.key === "/") {
4289
4574
  setTimeout(openSlashMenu, 0);
4290
4575
  }
@@ -4297,8 +4582,12 @@ var Editor = (props) => {
4297
4582
  const handlePaste = (e) => {
4298
4583
  if (readOnly) return;
4299
4584
  e.preventDefault();
4300
- const html = e.clipboardData.getData("text/html");
4301
4585
  const text = e.clipboardData.getData("text/plain");
4586
+ if (closestPre()) {
4587
+ insertTextAtCaret(text);
4588
+ return;
4589
+ }
4590
+ const html = e.clipboardData.getData("text/html");
4302
4591
  const clean = html ? sanitizeHtml(html) : escapeHtml(text);
4303
4592
  document.execCommand("insertHTML", false, clean);
4304
4593
  handleInput();
@@ -4322,6 +4611,7 @@ var Editor = (props) => {
4322
4611
  updateActiveFormats();
4323
4612
  };
4324
4613
  const onToolbarAction = (item) => {
4614
+ if (closestPre() && item !== "code-block") return;
4325
4615
  switch (item) {
4326
4616
  case "bold":
4327
4617
  exec("bold");
@@ -4363,7 +4653,7 @@ var Editor = (props) => {
4363
4653
  setBlock("blockquote");
4364
4654
  break;
4365
4655
  case "code-block":
4366
- setBlock("pre");
4656
+ insertCodeBlock();
4367
4657
  break;
4368
4658
  case "link":
4369
4659
  openLinkEditor();
@@ -4393,6 +4683,10 @@ var Editor = (props) => {
4393
4683
  ref: editorRef,
4394
4684
  contentEditable: !readOnly,
4395
4685
  suppressContentEditableWarning: true,
4686
+ role: "textbox",
4687
+ "aria-multiline": "true",
4688
+ "aria-readonly": readOnly || void 0,
4689
+ "aria-label": placeholder,
4396
4690
  className: "lib-xplat-editor__editable",
4397
4691
  onInput: handleInput,
4398
4692
  onKeyDown: handleKeyDown,
@@ -4484,7 +4778,7 @@ var EditorToolbar = ({ items, active, onAction }) => {
4484
4778
  )) });
4485
4779
  };
4486
4780
  var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
4487
- React21.useEffect(() => {
4781
+ React22.useEffect(() => {
4488
4782
  const handleClickOutside = (e) => {
4489
4783
  const target = e.target;
4490
4784
  const menu = document.querySelector(".lib-xplat-editor__slash-menu");
@@ -4518,8 +4812,8 @@ var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
4518
4812
  );
4519
4813
  };
4520
4814
  var LinkPopover = ({ position, value, onChange, onConfirm, onClose }) => {
4521
- const inputRef = React21.useRef(null);
4522
- React21.useEffect(() => {
4815
+ const inputRef = React22.useRef(null);
4816
+ React22.useEffect(() => {
4523
4817
  inputRef.current?.focus();
4524
4818
  }, []);
4525
4819
  return /* @__PURE__ */ jsxs207(
@@ -4577,7 +4871,7 @@ EmptyState.displayName = "EmptyState";
4577
4871
  var EmptyState_default = EmptyState;
4578
4872
 
4579
4873
  // src/components/FileUpload/FileUpload.tsx
4580
- import React22 from "react";
4874
+ import React23 from "react";
4581
4875
  import { jsx as jsx325, jsxs as jsxs209 } from "react/jsx-runtime";
4582
4876
  var FileUpload = (props) => {
4583
4877
  const {
@@ -4589,8 +4883,8 @@ var FileUpload = (props) => {
4589
4883
  description,
4590
4884
  validations
4591
4885
  } = props;
4592
- const [isDragOver, setIsDragOver] = React22.useState(false);
4593
- const inputRef = React22.useRef(null);
4886
+ const [isDragOver, setIsDragOver] = React23.useState(false);
4887
+ const inputRef = React23.useRef(null);
4594
4888
  const handleFiles = (fileList) => {
4595
4889
  let files = Array.from(fileList);
4596
4890
  if (maxSize) {
@@ -4652,10 +4946,10 @@ FileUpload.displayName = "FileUpload";
4652
4946
  var FileUpload_default = FileUpload;
4653
4947
 
4654
4948
  // src/components/HtmlTypeWriter/HtmlTypeWriter.tsx
4655
- import React24 from "react";
4949
+ import React25 from "react";
4656
4950
 
4657
4951
  // src/components/HtmlTypeWriter/utils.ts
4658
- import React23 from "react";
4952
+ import React24 from "react";
4659
4953
  var voidTags = /* @__PURE__ */ new Set([
4660
4954
  "br",
4661
4955
  "img",
@@ -4723,15 +5017,15 @@ var convertNodeToReactWithRange = (node, typedLen, rangeMap) => {
4723
5017
  props[attr.name] = attr.value;
4724
5018
  });
4725
5019
  if (voidTags.has(tag)) {
4726
- return React23.createElement(tag, props);
5020
+ return React24.createElement(tag, props);
4727
5021
  }
4728
5022
  const children = Array.from(element.childNodes).map((child) => convertNodeToReactWithRange(child, typedLen, rangeMap)).filter((n) => n != null);
4729
- return React23.createElement(tag, props, ...children);
5023
+ return React24.createElement(tag, props, ...children);
4730
5024
  };
4731
5025
  var htmlToReactProgressive = (root, typedLen, rangeMap) => {
4732
5026
  const nodes = Array.from(root.childNodes).map((child, idx) => {
4733
5027
  const node = convertNodeToReactWithRange(child, typedLen, rangeMap);
4734
- return node == null ? null : React23.createElement(React23.Fragment, { key: idx }, node);
5028
+ return node == null ? null : React24.createElement(React24.Fragment, { key: idx }, node);
4735
5029
  }).filter(Boolean);
4736
5030
  return nodes.length === 0 ? null : nodes;
4737
5031
  };
@@ -4744,20 +5038,20 @@ var HtmlTypeWriter = ({
4744
5038
  onDone,
4745
5039
  onChange
4746
5040
  }) => {
4747
- const [typedLen, setTypedLen] = React24.useState(0);
4748
- const doneCalledRef = React24.useRef(false);
4749
- const { doc, rangeMap, totalLength } = React24.useMemo(() => {
5041
+ const [typedLen, setTypedLen] = React25.useState(0);
5042
+ const doneCalledRef = React25.useRef(false);
5043
+ const { doc, rangeMap, totalLength } = React25.useMemo(() => {
4750
5044
  if (typeof window === "undefined") return { doc: null, rangeMap: /* @__PURE__ */ new Map(), totalLength: 0 };
4751
5045
  const decoded = decodeHtmlEntities(html);
4752
5046
  const doc2 = new DOMParser().parseFromString(decoded, "text/html");
4753
5047
  const { rangeMap: rangeMap2, totalLength: totalLength2 } = buildRangeMap(doc2.body);
4754
5048
  return { doc: doc2, rangeMap: rangeMap2, totalLength: totalLength2 };
4755
5049
  }, [html]);
4756
- React24.useEffect(() => {
5050
+ React25.useEffect(() => {
4757
5051
  setTypedLen(0);
4758
5052
  doneCalledRef.current = false;
4759
5053
  }, [html]);
4760
- React24.useEffect(() => {
5054
+ React25.useEffect(() => {
4761
5055
  if (!totalLength) return;
4762
5056
  if (typedLen >= totalLength) return;
4763
5057
  const timer = window.setInterval(() => {
@@ -4765,18 +5059,18 @@ var HtmlTypeWriter = ({
4765
5059
  }, duration);
4766
5060
  return () => window.clearInterval(timer);
4767
5061
  }, [typedLen, totalLength, duration]);
4768
- React24.useEffect(() => {
5062
+ React25.useEffect(() => {
4769
5063
  if (typedLen > 0 && typedLen < totalLength) {
4770
5064
  onChange?.();
4771
5065
  }
4772
5066
  }, [typedLen, totalLength, onChange]);
4773
- React24.useEffect(() => {
5067
+ React25.useEffect(() => {
4774
5068
  if (typedLen === totalLength && totalLength > 0 && !doneCalledRef.current) {
4775
5069
  doneCalledRef.current = true;
4776
5070
  onDone?.();
4777
5071
  }
4778
5072
  }, [typedLen, totalLength, onDone]);
4779
- const parsed = React24.useMemo(
5073
+ const parsed = React25.useMemo(
4780
5074
  () => doc ? htmlToReactProgressive(doc.body, typedLen, rangeMap) : null,
4781
5075
  [doc, typedLen, rangeMap]
4782
5076
  );
@@ -4786,12 +5080,12 @@ HtmlTypeWriter.displayName = "HtmlTypeWriter";
4786
5080
  var HtmlTypeWriter_default = HtmlTypeWriter;
4787
5081
 
4788
5082
  // src/components/ImageSelector/ImageSelector.tsx
4789
- import React25 from "react";
5083
+ import React26 from "react";
4790
5084
  import { jsx as jsx327, jsxs as jsxs210 } from "react/jsx-runtime";
4791
5085
  var ImageSelector = (props) => {
4792
5086
  const { value, label, onChange, validations } = props;
4793
- const [previewUrl, setPreviewUrl] = React25.useState();
4794
- React25.useEffect(() => {
5087
+ const [previewUrl, setPreviewUrl] = React26.useState();
5088
+ React26.useEffect(() => {
4795
5089
  if (!value) {
4796
5090
  setPreviewUrl(void 0);
4797
5091
  return;
@@ -4800,7 +5094,7 @@ var ImageSelector = (props) => {
4800
5094
  setPreviewUrl(url);
4801
5095
  return () => URL.revokeObjectURL(url);
4802
5096
  }, [value]);
4803
- const inputRef = React25.useRef(null);
5097
+ const inputRef = React26.useRef(null);
4804
5098
  const handleFileChange = (e) => {
4805
5099
  const selectedFile = e.target.files?.[0];
4806
5100
  if (selectedFile) {
@@ -4888,11 +5182,12 @@ var NotificationBadge = (props) => {
4888
5182
  dot = false,
4889
5183
  size = "md"
4890
5184
  } = props;
5185
+ const statusType = normalizeStatus(type);
4891
5186
  const showBadge = dot || count !== void 0 && count > 0;
4892
5187
  const displayCount = count !== void 0 && count > maxCount ? `${maxCount}+` : count;
4893
5188
  return /* @__PURE__ */ jsxs211("div", { className: clsx_default("lib-xplat-notification-badge", size), children: [
4894
5189
  children,
4895
- showBadge && /* @__PURE__ */ jsx330("span", { className: clsx_default("badge-indicator", type, { dot }), children: !dot && displayCount })
5190
+ showBadge && /* @__PURE__ */ jsx330("span", { className: clsx_default("badge-indicator", statusType, { dot }), children: !dot && displayCount })
4896
5191
  ] });
4897
5192
  };
4898
5193
  NotificationBadge.displayName = "NotificationBadge";
@@ -4933,8 +5228,9 @@ var Pagination = (props) => {
4933
5228
  siblingCount = 1,
4934
5229
  onChange,
4935
5230
  size = "md",
4936
- type = "brand"
5231
+ type = "primary"
4937
5232
  } = props;
5233
+ const statusType = normalizeStatus(type);
4938
5234
  const totalPages = Math.max(1, Math.ceil(total / pageSize));
4939
5235
  const pages = getPageRange(current, totalPages, siblingCount);
4940
5236
  const handleClick = (page) => {
@@ -4942,7 +5238,7 @@ var Pagination = (props) => {
4942
5238
  onChange?.(page);
4943
5239
  }
4944
5240
  };
4945
- return /* @__PURE__ */ jsxs212("nav", { className: clsx_default("lib-xplat-pagination", size, type), "aria-label": "\uD398\uC774\uC9C0 \uB124\uBE44\uAC8C\uC774\uC158", children: [
5241
+ return /* @__PURE__ */ jsxs212("nav", { className: clsx_default("lib-xplat-pagination", size, statusType), "aria-label": "\uD398\uC774\uC9C0 \uB124\uBE44\uAC8C\uC774\uC158", children: [
4946
5242
  /* @__PURE__ */ jsx331(
4947
5243
  "button",
4948
5244
  {
@@ -4981,17 +5277,21 @@ Pagination.displayName = "Pagination";
4981
5277
  var Pagination_default = Pagination;
4982
5278
 
4983
5279
  // src/components/PopOver/PopOver.tsx
4984
- import React26 from "react";
5280
+ import React27 from "react";
4985
5281
  import { jsx as jsx332, jsxs as jsxs213 } from "react/jsx-runtime";
4986
5282
  var PopOver = (props) => {
4987
5283
  const { children, isOpen, onClose, PopOverEl } = props;
4988
- const popRef = React26.useRef(null);
4989
- const triggerRef = React26.useRef(null);
4990
- const [localOpen, setLocalOpen] = React26.useState(false);
4991
- const [eventTrigger, setEventTrigger] = React26.useState(false);
5284
+ const popRef = React27.useRef(null);
5285
+ const triggerRef = React27.useRef(null);
5286
+ const [localOpen, setLocalOpen] = React27.useState(false);
5287
+ const [eventTrigger, setEventTrigger] = React27.useState(false);
4992
5288
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
5289
+ useEscapeKey(isOpen, () => {
5290
+ onClose();
5291
+ triggerRef.current?.focus({ preventScroll: true });
5292
+ });
4993
5293
  const position = useAutoPosition_default(triggerRef, popRef, localOpen);
4994
- React26.useEffect(() => {
5294
+ React27.useEffect(() => {
4995
5295
  if (isOpen) {
4996
5296
  setLocalOpen(isOpen);
4997
5297
  setTimeout(() => {
@@ -5043,11 +5343,12 @@ var Progress = (props) => {
5043
5343
  value,
5044
5344
  max = 100,
5045
5345
  size = "md",
5046
- type = "brand",
5346
+ type = "primary",
5047
5347
  showLabel = false
5048
5348
  } = props;
5349
+ const statusType = normalizeStatus(type);
5049
5350
  const percentage = Math.min(100, Math.max(0, value / max * 100));
5050
- return /* @__PURE__ */ jsxs214("div", { className: clsx_default("lib-xplat-progress", size, type), children: [
5351
+ return /* @__PURE__ */ jsxs214("div", { className: clsx_default("lib-xplat-progress", size, statusType), children: [
5051
5352
  /* @__PURE__ */ jsx333(
5052
5353
  "div",
5053
5354
  {
@@ -5075,12 +5376,12 @@ Progress.displayName = "Progress";
5075
5376
  var Progress_default = Progress;
5076
5377
 
5077
5378
  // src/components/Radio/RadioGroupContext.tsx
5078
- import React27 from "react";
5079
- var RadioGroupContext = React27.createContext(
5379
+ import React28 from "react";
5380
+ var RadioGroupContext = React28.createContext(
5080
5381
  null
5081
5382
  );
5082
5383
  var useRadioGroupContext = () => {
5083
- return React27.useContext(RadioGroupContext);
5384
+ return React28.useContext(RadioGroupContext);
5084
5385
  };
5085
5386
  var RadioGroupContext_default = RadioGroupContext;
5086
5387
 
@@ -5092,10 +5393,11 @@ var Radio = (props) => {
5092
5393
  className,
5093
5394
  value,
5094
5395
  size: sizeProp,
5095
- type = "brand",
5396
+ type = "primary",
5096
5397
  validations,
5097
5398
  ...rest
5098
5399
  } = props;
5400
+ const statusType = normalizeStatus(type);
5099
5401
  const context = useRadioGroupContext();
5100
5402
  const size = sizeProp ?? context?.size ?? "md";
5101
5403
  const isGroup = !!context;
@@ -5111,7 +5413,7 @@ var Radio = (props) => {
5111
5413
  className: clsx_default(
5112
5414
  "lib-xplat-radio",
5113
5415
  size,
5114
- type,
5416
+ statusType,
5115
5417
  localChecked ? "checked" : void 0,
5116
5418
  className
5117
5419
  ),
@@ -5155,19 +5457,19 @@ RadioGroup.displayName = "RadioGroup";
5155
5457
  var RadioGroup_default = RadioGroup;
5156
5458
 
5157
5459
  // src/components/Select/Select.tsx
5158
- import React30 from "react";
5460
+ import React31 from "react";
5159
5461
 
5160
5462
  // src/components/Select/context.ts
5161
- import React28 from "react";
5162
- var SelectContext = React28.createContext(null);
5463
+ import React29 from "react";
5464
+ var SelectContext = React29.createContext(null);
5163
5465
  var context_default = SelectContext;
5164
5466
 
5165
5467
  // src/components/Select/SelectItem.tsx
5166
- import React29 from "react";
5468
+ import React30 from "react";
5167
5469
  import { jsx as jsx336 } from "react/jsx-runtime";
5168
5470
  var SelectItem = (props) => {
5169
5471
  const { children, value, onClick, disabled = false } = props;
5170
- const ctx = React29.useContext(context_default);
5472
+ const ctx = React30.useContext(context_default);
5171
5473
  const handleClick = (e) => {
5172
5474
  e.preventDefault();
5173
5475
  e.stopPropagation();
@@ -5207,32 +5509,37 @@ var SelectRoot = (props) => {
5207
5509
  onChange,
5208
5510
  children,
5209
5511
  disabled = false,
5512
+ searchable = false,
5513
+ searchPlaceholder = "\uAC80\uC0C9",
5210
5514
  error = false,
5211
5515
  validations,
5516
+ label,
5517
+ required,
5212
5518
  size = "md"
5213
5519
  } = props;
5214
- const itemChildren = React30.Children.toArray(children).filter(
5215
- (child) => React30.isValidElement(child) && child.type === SelectItem_default
5520
+ const fieldId = React31.useId();
5521
+ const itemChildren = React31.Children.toArray(children).filter(
5522
+ (child) => React31.isValidElement(child) && child.type === SelectItem_default
5216
5523
  );
5217
5524
  const isControlled = valueProp !== void 0;
5218
- const [isOpen, setOpen] = React30.useState(false);
5219
- const [uncontrolledLabel, setUncontrolledLabel] = React30.useState(null);
5220
- const [uncontrolledValue, setUncontrolledValue] = React30.useState(void 0);
5221
- const controlledLabel = React30.useMemo(() => {
5525
+ const [isOpen, setOpen] = React31.useState(false);
5526
+ const [uncontrolledLabel, setUncontrolledLabel] = React31.useState(null);
5527
+ const [uncontrolledValue, setUncontrolledValue] = React31.useState(void 0);
5528
+ const controlledLabel = React31.useMemo(() => {
5222
5529
  if (!isControlled) return null;
5223
5530
  const match = itemChildren.find((child) => child.props.value === valueProp);
5224
5531
  return match ? match.props.children : null;
5225
5532
  }, [isControlled, valueProp, itemChildren]);
5226
5533
  const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
5227
5534
  const selectedValue = isControlled ? valueProp : uncontrolledValue;
5228
- const triggerRef = React30.useRef(null);
5229
- const contentRef = React30.useRef(null);
5230
- const [mounted, setMounted] = React30.useState(false);
5231
- const [visible, setVisible] = React30.useState(false);
5232
- React30.useEffect(() => {
5535
+ const triggerRef = React31.useRef(null);
5536
+ const contentRef = React31.useRef(null);
5537
+ const [mounted, setMounted] = React31.useState(false);
5538
+ const [visible, setVisible] = React31.useState(false);
5539
+ React31.useEffect(() => {
5233
5540
  if (disabled && isOpen) setOpen(false);
5234
5541
  }, [disabled, isOpen]);
5235
- React30.useEffect(() => {
5542
+ React31.useEffect(() => {
5236
5543
  if (isOpen) {
5237
5544
  setMounted(true);
5238
5545
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -5242,22 +5549,42 @@ var SelectRoot = (props) => {
5242
5549
  const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS3);
5243
5550
  return () => clearTimeout(t);
5244
5551
  }, [isOpen]);
5245
- const open = React30.useCallback(() => setOpen(true), []);
5246
- const close = React30.useCallback(() => setOpen(false), []);
5247
- const toggle = React30.useCallback(() => setOpen((prev) => !prev), []);
5552
+ const [query, setQuery] = React31.useState("");
5553
+ const textOf = (node) => {
5554
+ if (node === null || node === void 0 || typeof node === "boolean") return "";
5555
+ if (typeof node === "string" || typeof node === "number") return String(node);
5556
+ if (Array.isArray(node)) return node.map(textOf).join("");
5557
+ if (React31.isValidElement(node)) return textOf(node.props.children);
5558
+ return "";
5559
+ };
5560
+ const visibleItems = React31.useMemo(() => {
5561
+ if (!searchable || !query.trim()) return itemChildren;
5562
+ const q = query.trim().toLowerCase();
5563
+ return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
5564
+ }, [searchable, query, itemChildren]);
5565
+ const open = React31.useCallback(() => setOpen(true), []);
5566
+ const close = React31.useCallback(() => {
5567
+ setOpen(false);
5568
+ setQuery("");
5569
+ }, []);
5570
+ const toggle = React31.useCallback(() => setOpen((prev) => !prev), []);
5248
5571
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
5572
+ useEscapeKey(isOpen, () => {
5573
+ close();
5574
+ triggerRef.current?.focus({ preventScroll: true });
5575
+ });
5249
5576
  const position = useAutoPosition_default(triggerRef, contentRef, mounted);
5250
- const setSelected = React30.useCallback(
5251
- (label, itemValue) => {
5577
+ const setSelected = React31.useCallback(
5578
+ (label2, itemValue) => {
5252
5579
  if (!isControlled) {
5253
- setUncontrolledLabel(label);
5580
+ setUncontrolledLabel(label2);
5254
5581
  setUncontrolledValue(itemValue);
5255
5582
  }
5256
- onChange?.(itemValue, label);
5583
+ onChange?.(itemValue, label2);
5257
5584
  },
5258
5585
  [isControlled, onChange]
5259
5586
  );
5260
- const ctxValue = React30.useMemo(
5587
+ const ctxValue = React31.useMemo(
5261
5588
  () => ({
5262
5589
  isOpen,
5263
5590
  mounted,
@@ -5293,6 +5620,7 @@ var SelectRoot = (props) => {
5293
5620
  /* @__PURE__ */ jsxs216(
5294
5621
  "div",
5295
5622
  {
5623
+ id: fieldId,
5296
5624
  ref: triggerRef,
5297
5625
  className: clsx_default(
5298
5626
  "select-trigger",
@@ -5335,20 +5663,33 @@ var SelectRoot = (props) => {
5335
5663
  ]
5336
5664
  }
5337
5665
  ),
5338
- mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsx337(
5666
+ mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsxs216(
5339
5667
  "div",
5340
5668
  {
5341
5669
  className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
5342
5670
  ref: contentRef,
5343
5671
  style: { ...position.position, width: triggerRef.current?.offsetWidth },
5344
5672
  role: "listbox",
5345
- children: /* @__PURE__ */ jsx337(context_default.Provider, { value: ctxValue, children: itemChildren })
5673
+ children: [
5674
+ searchable && /* @__PURE__ */ jsx337("div", { className: "select-search", children: /* @__PURE__ */ jsx337(
5675
+ "input",
5676
+ {
5677
+ type: "text",
5678
+ value: query,
5679
+ placeholder: searchPlaceholder,
5680
+ onChange: (e) => setQuery(e.target.value),
5681
+ autoFocus: true,
5682
+ "aria-label": searchPlaceholder
5683
+ }
5684
+ ) }),
5685
+ /* @__PURE__ */ jsx337(context_default.Provider, { value: ctxValue, children: visibleItems.length > 0 ? visibleItems : /* @__PURE__ */ jsx337("div", { className: "select-empty", children: "\uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" }) })
5686
+ ]
5346
5687
  }
5347
5688
  ) })
5348
5689
  ]
5349
5690
  }
5350
5691
  ) });
5351
- return /* @__PURE__ */ jsx337(Field, { validations, children: control });
5692
+ return /* @__PURE__ */ jsx337(Field, { validations, label, required, htmlFor: fieldId, children: control });
5352
5693
  };
5353
5694
  SelectRoot.displayName = "Select";
5354
5695
  var Select = Object.assign(SelectRoot, {
@@ -5390,12 +5731,13 @@ import { jsx as jsx339, jsxs as jsxs217 } from "react/jsx-runtime";
5390
5731
  var Spinner = (props) => {
5391
5732
  const {
5392
5733
  size = "md",
5393
- type = "brand"
5734
+ type = "primary"
5394
5735
  } = props;
5736
+ const statusType = normalizeStatus(type);
5395
5737
  return /* @__PURE__ */ jsx339(
5396
5738
  "div",
5397
5739
  {
5398
- className: clsx_default("lib-xplat-spinner", size, type),
5740
+ className: clsx_default("lib-xplat-spinner", size, statusType),
5399
5741
  role: "status",
5400
5742
  "aria-label": "\uB85C\uB529 \uC911",
5401
5743
  children: /* @__PURE__ */ jsxs217("svg", { viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
@@ -5427,21 +5769,58 @@ var Spinner = (props) => {
5427
5769
  Spinner.displayName = "Spinner";
5428
5770
  var Spinner_default = Spinner;
5429
5771
 
5430
- // src/components/Steps/Steps.tsx
5772
+ // src/components/Stat/Stat.tsx
5431
5773
  import { jsx as jsx340, jsxs as jsxs218 } from "react/jsx-runtime";
5774
+ var ARROW = {
5775
+ up: "\u25B2",
5776
+ down: "\u25BC",
5777
+ flat: "\u2014"
5778
+ };
5779
+ var Stat = (props) => {
5780
+ const {
5781
+ label,
5782
+ value,
5783
+ unit,
5784
+ description,
5785
+ trend,
5786
+ icon,
5787
+ size = "md",
5788
+ type = "primary"
5789
+ } = props;
5790
+ const statusType = normalizeStatus(type);
5791
+ return /* @__PURE__ */ jsxs218("div", { className: clsx_default("lib-xplat-stat", size, statusType), children: [
5792
+ /* @__PURE__ */ jsx340("div", { className: "stat-label", children: label }),
5793
+ /* @__PURE__ */ jsxs218("div", { className: "stat-value-row", children: [
5794
+ icon && /* @__PURE__ */ jsx340("span", { className: "stat-icon", children: icon }),
5795
+ /* @__PURE__ */ jsx340("span", { className: "stat-value", children: value }),
5796
+ unit && /* @__PURE__ */ jsx340("span", { className: "stat-unit", children: unit }),
5797
+ trend && /* @__PURE__ */ jsxs218("span", { className: clsx_default("stat-trend", trend.direction), children: [
5798
+ /* @__PURE__ */ jsx340("span", { "aria-hidden": "true", children: ARROW[trend.direction] }),
5799
+ trend.value
5800
+ ] })
5801
+ ] }),
5802
+ description && /* @__PURE__ */ jsx340("div", { className: "stat-description", children: description })
5803
+ ] });
5804
+ };
5805
+ Stat.displayName = "Stat";
5806
+ var Stat_default = Stat;
5807
+
5808
+ // src/components/Steps/Steps.tsx
5809
+ import { jsx as jsx341, jsxs as jsxs219 } from "react/jsx-runtime";
5432
5810
  var Steps = (props) => {
5433
5811
  const {
5434
5812
  items,
5435
5813
  current,
5436
- type = "brand"
5814
+ type = "primary"
5437
5815
  } = props;
5438
- return /* @__PURE__ */ jsx340("div", { className: clsx_default("lib-xplat-steps", type), children: items.map((item, index) => {
5816
+ const statusType = normalizeStatus(type);
5817
+ return /* @__PURE__ */ jsx341("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
5439
5818
  const status = index < current ? "completed" : index === current ? "active" : "pending";
5440
- return /* @__PURE__ */ jsxs218("div", { className: clsx_default("step-item", status), children: [
5441
- /* @__PURE__ */ jsx340("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ jsx340(CheckIcon_default, {}) : /* @__PURE__ */ jsx340("span", { children: index + 1 }) }),
5442
- /* @__PURE__ */ jsxs218("div", { className: "step-content", children: [
5443
- /* @__PURE__ */ jsx340("span", { className: "step-title", children: item.title }),
5444
- item.description && /* @__PURE__ */ jsx340("span", { className: "step-description", children: item.description })
5819
+ return /* @__PURE__ */ jsxs219("div", { className: clsx_default("step-item", status), children: [
5820
+ /* @__PURE__ */ jsx341("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ jsx341(CheckIcon_default, {}) : /* @__PURE__ */ jsx341("span", { children: index + 1 }) }),
5821
+ /* @__PURE__ */ jsxs219("div", { className: "step-content", children: [
5822
+ /* @__PURE__ */ jsx341("span", { className: "step-title", children: item.title }),
5823
+ item.description && /* @__PURE__ */ jsx341("span", { className: "step-description", children: item.description })
5445
5824
  ] })
5446
5825
  ] }, index);
5447
5826
  }) });
@@ -5450,8 +5829,8 @@ Steps.displayName = "Steps";
5450
5829
  var Steps_default = Steps;
5451
5830
 
5452
5831
  // src/components/Swiper/Swiper.tsx
5453
- import React31 from "react";
5454
- import { jsx as jsx341, jsxs as jsxs219 } from "react/jsx-runtime";
5832
+ import React32 from "react";
5833
+ import { jsx as jsx342, jsxs as jsxs220 } from "react/jsx-runtime";
5455
5834
  var Swiper = (props) => {
5456
5835
  const {
5457
5836
  auto = false,
@@ -5475,26 +5854,26 @@ var Swiper = (props) => {
5475
5854
  const maxIndex = Math.max(0, totalSlides - viewItemCount);
5476
5855
  const useLoop = loop && canSlide;
5477
5856
  const cloneCount = useLoop ? totalSlides : 0;
5478
- const extendedItems = React31.useMemo(() => {
5857
+ const extendedItems = React32.useMemo(() => {
5479
5858
  if (!useLoop) return items;
5480
5859
  return [...items, ...items, ...items];
5481
5860
  }, [items, useLoop]);
5482
5861
  const initialIdx = Math.max(0, Math.min(indexProp ?? 0, maxIndex));
5483
- const [innerIndex, setInnerIndex] = React31.useState(
5862
+ const [innerIndex, setInnerIndex] = React32.useState(
5484
5863
  useLoop ? cloneCount + initialIdx : initialIdx
5485
5864
  );
5486
- const [isDragging, setIsDragging] = React31.useState(false);
5487
- const [dragOffset, setDragOffset] = React31.useState(0);
5488
- const [animated, setAnimated] = React31.useState(false);
5489
- const [containerWidth, setContainerWidth] = React31.useState(0);
5490
- const containerRef = React31.useRef(null);
5491
- const startXRef = React31.useRef(0);
5492
- const startTimeRef = React31.useRef(0);
5493
- const autoplayTimerRef = React31.useRef(null);
5494
- const resumeTimeoutRef = React31.useRef(null);
5495
- const [paused, setPaused] = React31.useState(false);
5496
- const initializedRef = React31.useRef(false);
5497
- React31.useEffect(() => {
5865
+ const [isDragging, setIsDragging] = React32.useState(false);
5866
+ const [dragOffset, setDragOffset] = React32.useState(0);
5867
+ const [animated, setAnimated] = React32.useState(false);
5868
+ const [containerWidth, setContainerWidth] = React32.useState(0);
5869
+ const containerRef = React32.useRef(null);
5870
+ const startXRef = React32.useRef(0);
5871
+ const startTimeRef = React32.useRef(0);
5872
+ const autoplayTimerRef = React32.useRef(null);
5873
+ const resumeTimeoutRef = React32.useRef(null);
5874
+ const [paused, setPaused] = React32.useState(false);
5875
+ const initializedRef = React32.useRef(false);
5876
+ React32.useEffect(() => {
5498
5877
  const el = containerRef.current;
5499
5878
  if (!el) return;
5500
5879
  const ro = new ResizeObserver((entries) => {
@@ -5517,7 +5896,7 @@ var Swiper = (props) => {
5517
5896
  return ((inner - cloneCount) % totalSlides + totalSlides) % totalSlides;
5518
5897
  };
5519
5898
  const realIndex = getRealIndex(innerIndex);
5520
- const moveToInner = React31.useCallback(
5899
+ const moveToInner = React32.useCallback(
5521
5900
  (idx, withAnim = true) => {
5522
5901
  if (!useLoop) {
5523
5902
  setAnimated(withAnim);
@@ -5545,7 +5924,7 @@ var Swiper = (props) => {
5545
5924
  },
5546
5925
  [useLoop, cloneCount, totalSlides]
5547
5926
  );
5548
- const handleTransitionEnd = React31.useCallback(() => {
5927
+ const handleTransitionEnd = React32.useCallback(() => {
5549
5928
  if (!useLoop) return;
5550
5929
  const real = getRealIndex(innerIndex);
5551
5930
  const canonical = cloneCount + real;
@@ -5555,7 +5934,7 @@ var Swiper = (props) => {
5555
5934
  }
5556
5935
  onChange?.(Math.min(real, maxIndex));
5557
5936
  }, [useLoop, innerIndex, cloneCount, totalSlides, maxIndex, onChange]);
5558
- const slideTo = React31.useCallback(
5937
+ const slideTo = React32.useCallback(
5559
5938
  (logicalIndex) => {
5560
5939
  if (!canSlide) return;
5561
5940
  const clamped = useLoop ? logicalIndex : Math.max(0, Math.min(logicalIndex, maxIndex));
@@ -5565,7 +5944,7 @@ var Swiper = (props) => {
5565
5944
  },
5566
5945
  [canSlide, useLoop, cloneCount, maxIndex, onChange, moveToInner]
5567
5946
  );
5568
- const slideNext = React31.useCallback(() => {
5947
+ const slideNext = React32.useCallback(() => {
5569
5948
  if (!canSlide) return;
5570
5949
  const nextInner = innerIndex + slideBy;
5571
5950
  if (useLoop) {
@@ -5574,7 +5953,7 @@ var Swiper = (props) => {
5574
5953
  moveToInner(Math.min(nextInner, maxIndex), true);
5575
5954
  }
5576
5955
  }, [canSlide, useLoop, innerIndex, slideBy, maxIndex, moveToInner]);
5577
- const slidePrev = React31.useCallback(() => {
5956
+ const slidePrev = React32.useCallback(() => {
5578
5957
  if (!canSlide) return;
5579
5958
  const prevInner = innerIndex - slideBy;
5580
5959
  if (useLoop) {
@@ -5583,7 +5962,7 @@ var Swiper = (props) => {
5583
5962
  moveToInner(Math.max(prevInner, 0), true);
5584
5963
  }
5585
5964
  }, [canSlide, useLoop, innerIndex, slideBy, moveToInner]);
5586
- React31.useEffect(() => {
5965
+ React32.useEffect(() => {
5587
5966
  if (indexProp === void 0) return;
5588
5967
  const clamped = Math.max(0, Math.min(indexProp, maxIndex));
5589
5968
  const target = useLoop ? cloneCount + clamped : clamped;
@@ -5591,12 +5970,12 @@ var Swiper = (props) => {
5591
5970
  moveToInner(target, true);
5592
5971
  }
5593
5972
  }, [indexProp]);
5594
- React31.useImperativeHandle(swiperRef, () => ({
5973
+ React32.useImperativeHandle(swiperRef, () => ({
5595
5974
  slidePrev,
5596
5975
  slideNext,
5597
5976
  slideTo
5598
5977
  }));
5599
- React31.useEffect(() => {
5978
+ React32.useEffect(() => {
5600
5979
  if (!auto || !canSlide || paused) return;
5601
5980
  autoplayTimerRef.current = setInterval(slideNext, autoplayDelay);
5602
5981
  return () => {
@@ -5622,7 +6001,7 @@ var Swiper = (props) => {
5622
6001
  resumeTimeoutRef.current = null;
5623
6002
  }, pauseOnInteraction);
5624
6003
  };
5625
- React31.useEffect(() => {
6004
+ React32.useEffect(() => {
5626
6005
  return () => {
5627
6006
  if (resumeTimeoutRef.current) clearTimeout(resumeTimeoutRef.current);
5628
6007
  };
@@ -5640,7 +6019,7 @@ var Swiper = (props) => {
5640
6019
  startXRef.current = getClientX(e);
5641
6020
  startTimeRef.current = Date.now();
5642
6021
  };
5643
- React31.useEffect(() => {
6022
+ React32.useEffect(() => {
5644
6023
  if (!isDragging) return;
5645
6024
  const handleMove = (e) => {
5646
6025
  setDragOffset(getClientX(e) - startXRef.current);
@@ -5679,8 +6058,8 @@ var Swiper = (props) => {
5679
6058
  }, [isDragging, dragOffset, innerIndex, useLoop, maxIndex, slideStep, moveToInner]);
5680
6059
  const slideWidthPercent = 100 / viewItemCount;
5681
6060
  const gapAdjust = spaceBetween * (viewItemCount - 1) / viewItemCount;
5682
- const slideElements = React31.useMemo(
5683
- () => extendedItems.map((item, idx) => /* @__PURE__ */ jsx341(
6061
+ const slideElements = React32.useMemo(
6062
+ () => extendedItems.map((item, idx) => /* @__PURE__ */ jsx342(
5684
6063
  "div",
5685
6064
  {
5686
6065
  className: "lib-xplat-swiper__slide",
@@ -5699,15 +6078,15 @@ var Swiper = (props) => {
5699
6078
  Math.floor(realIndex / slideBy),
5700
6079
  totalSteps - 1
5701
6080
  );
5702
- return /* @__PURE__ */ jsxs219("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
5703
- /* @__PURE__ */ jsx341(
6081
+ return /* @__PURE__ */ jsxs220("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
6082
+ /* @__PURE__ */ jsx342(
5704
6083
  "div",
5705
6084
  {
5706
6085
  className: "lib-xplat-swiper__viewport",
5707
6086
  onMouseDown: handleDragStart,
5708
6087
  onTouchStart: handleDragStart,
5709
6088
  onDragStart: (e) => e.preventDefault(),
5710
- children: /* @__PURE__ */ jsx341(
6089
+ children: /* @__PURE__ */ jsx342(
5711
6090
  "div",
5712
6091
  {
5713
6092
  className: clsx_default(
@@ -5725,7 +6104,7 @@ var Swiper = (props) => {
5725
6104
  )
5726
6105
  }
5727
6106
  ),
5728
- showProgress && canSlide && /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ jsx341(
6107
+ showProgress && canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ jsx342(
5729
6108
  "span",
5730
6109
  {
5731
6110
  className: "lib-xplat-swiper__progress-fill",
@@ -5735,7 +6114,7 @@ var Swiper = (props) => {
5735
6114
  }
5736
6115
  }
5737
6116
  ) }) }),
5738
- canSlide && /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ jsx341(
6117
+ canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ jsx342(
5739
6118
  "button",
5740
6119
  {
5741
6120
  className: clsx_default(
@@ -5753,21 +6132,25 @@ Swiper.displayName = "Swiper";
5753
6132
  var Swiper_default = Swiper;
5754
6133
 
5755
6134
  // src/components/Switch/Switch.tsx
5756
- import React32 from "react";
5757
- import { jsx as jsx342 } from "react/jsx-runtime";
6135
+ import React33 from "react";
6136
+ import { jsx as jsx343 } from "react/jsx-runtime";
5758
6137
  var KNOB_TRANSITION_MS = 250;
5759
6138
  var Switch = (props) => {
5760
6139
  const {
5761
6140
  value,
5762
6141
  size = "md",
5763
- type = "brand",
6142
+ type = "primary",
5764
6143
  disabled,
5765
6144
  onChange,
5766
- validations
6145
+ validations,
6146
+ label,
6147
+ required
5767
6148
  } = props;
5768
- const [isAnimating, setIsAnimating] = React32.useState(false);
5769
- const timeoutRef = React32.useRef(null);
5770
- React32.useEffect(() => {
6149
+ const fieldId = React33.useId();
6150
+ const statusType = normalizeStatus(type);
6151
+ const [isAnimating, setIsAnimating] = React33.useState(false);
6152
+ const timeoutRef = React33.useRef(null);
6153
+ React33.useEffect(() => {
5771
6154
  return () => {
5772
6155
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5773
6156
  };
@@ -5782,13 +6165,14 @@ var Switch = (props) => {
5782
6165
  timeoutRef.current = null;
5783
6166
  }, KNOB_TRANSITION_MS);
5784
6167
  };
5785
- const control = /* @__PURE__ */ jsx342(
6168
+ const control = /* @__PURE__ */ jsx343(
5786
6169
  "div",
5787
6170
  {
6171
+ id: fieldId,
5788
6172
  className: clsx_default(
5789
6173
  "lib-xplat-switch",
5790
6174
  size,
5791
- type,
6175
+ statusType,
5792
6176
  value ? "checked" : void 0,
5793
6177
  disabled && "disabled",
5794
6178
  isAnimating && "animating"
@@ -5796,26 +6180,26 @@ var Switch = (props) => {
5796
6180
  onClick: handleClick,
5797
6181
  "aria-invalid": hasError(validations) || void 0,
5798
6182
  "aria-disabled": disabled || isAnimating,
5799
- children: /* @__PURE__ */ jsx342("div", { className: clsx_default("knob", value ? "checked" : void 0) })
6183
+ children: /* @__PURE__ */ jsx343("div", { className: clsx_default("knob", value ? "checked" : void 0) })
5800
6184
  }
5801
6185
  );
5802
- return /* @__PURE__ */ jsx342(Field, { validations, children: control });
6186
+ return /* @__PURE__ */ jsx343(Field, { validations, label, required, htmlFor: fieldId, children: control });
5803
6187
  };
5804
6188
  Switch.displayName = "Switch";
5805
6189
  var Switch_default = Switch;
5806
6190
 
5807
6191
  // src/components/Table/TableContext.tsx
5808
- import React33 from "react";
5809
- var TableContext = React33.createContext(null);
6192
+ import React34 from "react";
6193
+ var TableContext = React34.createContext(null);
5810
6194
  var useTableContext = () => {
5811
- const ctx = React33.useContext(TableContext);
6195
+ const ctx = React34.useContext(TableContext);
5812
6196
  if (!ctx) throw new Error("Table components must be used inside <Table>");
5813
6197
  return ctx;
5814
6198
  };
5815
6199
  var TableContext_default = TableContext;
5816
6200
 
5817
6201
  // src/components/Table/Table.tsx
5818
- import { jsx as jsx343 } from "react/jsx-runtime";
6202
+ import { jsx as jsx344 } from "react/jsx-runtime";
5819
6203
  var Table = (props) => {
5820
6204
  const {
5821
6205
  children,
@@ -5825,7 +6209,7 @@ var Table = (props) => {
5825
6209
  headerSticky = false,
5826
6210
  stickyShadow = true
5827
6211
  } = props;
5828
- return /* @__PURE__ */ jsx343("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx343(
6212
+ return /* @__PURE__ */ jsx344("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx344(
5829
6213
  TableContext_default.Provider,
5830
6214
  {
5831
6215
  value: {
@@ -5834,7 +6218,7 @@ var Table = (props) => {
5834
6218
  headerSticky,
5835
6219
  stickyShadow
5836
6220
  },
5837
- children: /* @__PURE__ */ jsx343("table", { className: "lib-xplat-table", children })
6221
+ children: /* @__PURE__ */ jsx344("table", { className: "lib-xplat-table", children })
5838
6222
  }
5839
6223
  ) });
5840
6224
  };
@@ -5842,41 +6226,41 @@ Table.displayName = "Table";
5842
6226
  var Table_default = Table;
5843
6227
 
5844
6228
  // src/components/Table/TableBody.tsx
5845
- import { jsx as jsx344 } from "react/jsx-runtime";
6229
+ import { jsx as jsx345 } from "react/jsx-runtime";
5846
6230
  var TableBody = (props) => {
5847
6231
  const { children } = props;
5848
- return /* @__PURE__ */ jsx344("tbody", { children });
6232
+ return /* @__PURE__ */ jsx345("tbody", { children });
5849
6233
  };
5850
6234
  TableBody.displayName = "TableBody";
5851
6235
  var TableBody_default = TableBody;
5852
6236
 
5853
6237
  // src/components/Table/TableCell.tsx
5854
- import React36 from "react";
6238
+ import React37 from "react";
5855
6239
 
5856
6240
  // src/components/Table/TableHeadContext.tsx
5857
- import React34 from "react";
5858
- var TableHeadContext = React34.createContext(
6241
+ import React35 from "react";
6242
+ var TableHeadContext = React35.createContext(
5859
6243
  null
5860
6244
  );
5861
6245
  var useTableHeadContext = () => {
5862
- const ctx = React34.useContext(TableHeadContext);
6246
+ const ctx = React35.useContext(TableHeadContext);
5863
6247
  return ctx;
5864
6248
  };
5865
6249
  var TableHeadContext_default = TableHeadContext;
5866
6250
 
5867
6251
  // src/components/Table/TableRowContext.tsx
5868
- import React35 from "react";
5869
- var TableRowContext = React35.createContext(null);
6252
+ import React36 from "react";
6253
+ var TableRowContext = React36.createContext(null);
5870
6254
  var useTableRowContext = () => {
5871
- const ctx = React35.useContext(TableRowContext);
6255
+ const ctx = React36.useContext(TableRowContext);
5872
6256
  if (!ctx) throw new Error("Table components must be used inside <Table>");
5873
6257
  return ctx;
5874
6258
  };
5875
6259
  var TableRowContext_default = TableRowContext;
5876
6260
 
5877
6261
  // src/components/Table/TableCell.tsx
5878
- import { jsx as jsx345 } from "react/jsx-runtime";
5879
- var TableCell = React36.memo((props) => {
6262
+ import { jsx as jsx346 } from "react/jsx-runtime";
6263
+ var TableCell = React37.memo((props) => {
5880
6264
  const {
5881
6265
  children,
5882
6266
  align = "center",
@@ -5890,9 +6274,9 @@ var TableCell = React36.memo((props) => {
5890
6274
  const { registerStickyCell, stickyCells } = useTableRowContext();
5891
6275
  const { stickyShadow } = useTableContext();
5892
6276
  const headContext = useTableHeadContext();
5893
- const [left, setLeft] = React36.useState(0);
5894
- const cellRef = React36.useRef(null);
5895
- const calculateLeft = React36.useCallback(() => {
6277
+ const [left, setLeft] = React37.useState(0);
6278
+ const cellRef = React37.useRef(null);
6279
+ const calculateLeft = React37.useCallback(() => {
5896
6280
  if (!cellRef.current) return 0;
5897
6281
  let totalLeft = 0;
5898
6282
  for (const ref of stickyCells) {
@@ -5901,7 +6285,7 @@ var TableCell = React36.memo((props) => {
5901
6285
  }
5902
6286
  return totalLeft;
5903
6287
  }, [stickyCells]);
5904
- React36.useEffect(() => {
6288
+ React37.useEffect(() => {
5905
6289
  if (!isSticky || !cellRef.current) return;
5906
6290
  registerStickyCell(cellRef);
5907
6291
  setLeft(calculateLeft());
@@ -5920,7 +6304,7 @@ var TableCell = React36.memo((props) => {
5920
6304
  const CellTag = isHeaderCell ? "th" : "td";
5921
6305
  const isLastSticky = isSticky && stickyCells[stickyCells.length - 1] === cellRef;
5922
6306
  const enableHover = headContext && headContext.cellHover;
5923
- return /* @__PURE__ */ jsx345(
6307
+ return /* @__PURE__ */ jsx346(
5924
6308
  CellTag,
5925
6309
  {
5926
6310
  ref: cellRef,
@@ -5947,21 +6331,21 @@ TableCell.displayName = "TableCell";
5947
6331
  var TableCell_default = TableCell;
5948
6332
 
5949
6333
  // src/components/Table/TableHead.tsx
5950
- import { jsx as jsx346 } from "react/jsx-runtime";
6334
+ import { jsx as jsx347 } from "react/jsx-runtime";
5951
6335
  var TableHead = ({
5952
6336
  children,
5953
6337
  cellHover = false
5954
6338
  }) => {
5955
6339
  const { headerSticky } = useTableContext();
5956
- return /* @__PURE__ */ jsx346(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ jsx346("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
6340
+ return /* @__PURE__ */ jsx347(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ jsx347("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
5957
6341
  };
5958
6342
  TableHead.displayName = "TableHead";
5959
6343
  var TableHead_default = TableHead;
5960
6344
 
5961
6345
  // src/components/Table/TableRow.tsx
5962
- import React37 from "react";
5963
- import { jsx as jsx347 } from "react/jsx-runtime";
5964
- var TableRow = React37.memo((props) => {
6346
+ import React38 from "react";
6347
+ import { jsx as jsx348 } from "react/jsx-runtime";
6348
+ var TableRow = React38.memo((props) => {
5965
6349
  const {
5966
6350
  children,
5967
6351
  type = "secondary",
@@ -5970,14 +6354,14 @@ var TableRow = React37.memo((props) => {
5970
6354
  onClick
5971
6355
  } = props;
5972
6356
  const { rowBorderUse } = useTableContext();
5973
- const [stickyCells, setStickyCells] = React37.useState([]);
6357
+ const [stickyCells, setStickyCells] = React38.useState([]);
5974
6358
  const registerStickyCell = (ref) => {
5975
6359
  setStickyCells((prev) => {
5976
6360
  if (prev.includes(ref)) return prev;
5977
6361
  return [...prev, ref];
5978
6362
  });
5979
6363
  };
5980
- return /* @__PURE__ */ jsx347(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ jsx347(
6364
+ return /* @__PURE__ */ jsx348(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ jsx348(
5981
6365
  "tr",
5982
6366
  {
5983
6367
  className: clsx_default(
@@ -6001,29 +6385,31 @@ TableRow.displayName = "TableRow";
6001
6385
  var TableRow_default = TableRow;
6002
6386
 
6003
6387
  // src/components/Tag/Tag.tsx
6004
- import { jsx as jsx348, jsxs as jsxs220 } from "react/jsx-runtime";
6388
+ import { jsx as jsx349, jsxs as jsxs221 } from "react/jsx-runtime";
6005
6389
  var Tag = (props) => {
6006
6390
  const {
6007
6391
  children,
6008
- type = "neutral",
6392
+ variant,
6393
+ type,
6009
6394
  onClose,
6010
6395
  size = "md",
6011
6396
  disabled = false,
6012
6397
  colorIndex
6013
6398
  } = props;
6014
- return /* @__PURE__ */ jsxs220(
6399
+ const shape = variant ?? type ?? "neutral";
6400
+ return /* @__PURE__ */ jsxs221(
6015
6401
  "span",
6016
6402
  {
6017
6403
  className: clsx_default(
6018
6404
  "lib-xplat-tag",
6019
- type,
6405
+ shape,
6020
6406
  size,
6021
- type === "categorical" && colorIndex !== void 0 && `cat-${colorIndex}`,
6407
+ shape === "categorical" && colorIndex !== void 0 && `cat-${colorIndex}`,
6022
6408
  disabled && "disabled"
6023
6409
  ),
6024
6410
  children: [
6025
- /* @__PURE__ */ jsx348("span", { className: "tag-label", children }),
6026
- onClose && /* @__PURE__ */ jsx348("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ jsx348(XIcon_default, {}) })
6411
+ /* @__PURE__ */ jsx349("span", { className: "tag-label", children }),
6412
+ onClose && /* @__PURE__ */ jsx349("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ jsx349(XIcon_default, {}) })
6027
6413
  ]
6028
6414
  }
6029
6415
  );
@@ -6032,24 +6418,29 @@ Tag.displayName = "Tag";
6032
6418
  var Tag_default = Tag;
6033
6419
 
6034
6420
  // src/components/TextArea/TextArea.tsx
6035
- import React38 from "react";
6036
- import { jsx as jsx349 } from "react/jsx-runtime";
6037
- var TextArea = React38.forwardRef(
6421
+ import React39 from "react";
6422
+ import { jsx as jsx350 } from "react/jsx-runtime";
6423
+ var TextArea = React39.forwardRef(
6038
6424
  (props, ref) => {
6039
6425
  const {
6040
6426
  className,
6041
6427
  size = "md",
6042
6428
  validations,
6429
+ label,
6430
+ required,
6043
6431
  resize = "vertical",
6044
6432
  rows = 3,
6045
6433
  disabled,
6046
6434
  ...textareaProps
6047
6435
  } = props;
6048
- const control = /* @__PURE__ */ jsx349("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx349(
6436
+ const autoId = React39.useId();
6437
+ const fieldId = props.id ?? autoId;
6438
+ const control = /* @__PURE__ */ jsx350("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx350(
6049
6439
  "textarea",
6050
6440
  {
6051
6441
  ...textareaProps,
6052
6442
  ref,
6443
+ id: fieldId,
6053
6444
  rows,
6054
6445
  disabled,
6055
6446
  "aria-invalid": hasError(validations) || void 0,
@@ -6057,32 +6448,166 @@ var TextArea = React38.forwardRef(
6057
6448
  style: { resize }
6058
6449
  }
6059
6450
  ) });
6060
- return /* @__PURE__ */ jsx349(Field, { validations, children: control });
6451
+ return /* @__PURE__ */ jsx350(Field, { validations, label, required, htmlFor: fieldId, children: control });
6061
6452
  }
6062
6453
  );
6063
6454
  TextArea.displayName = "TextArea";
6064
6455
  var TextArea_default = TextArea;
6065
6456
 
6457
+ // src/components/TimePicker/TimePicker.tsx
6458
+ import React40 from "react";
6459
+ import { jsx as jsx351, jsxs as jsxs222 } from "react/jsx-runtime";
6460
+ var ANIMATION_DURATION_MS4 = 200;
6461
+ var toMinutes = (hhmm) => {
6462
+ if (!hhmm) return null;
6463
+ const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
6464
+ if (!m) return null;
6465
+ const h = Number(m[1]);
6466
+ const min = Number(m[2]);
6467
+ if (h > 23 || min > 59) return null;
6468
+ return h * 60 + min;
6469
+ };
6470
+ var toHHmm = (minutes) => `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
6471
+ var display = (hhmm, use12Hours) => {
6472
+ if (!use12Hours) return hhmm;
6473
+ const total = toMinutes(hhmm);
6474
+ if (total === null) return hhmm;
6475
+ const h24 = Math.floor(total / 60);
6476
+ const mm = String(total % 60).padStart(2, "0");
6477
+ const period = h24 < 12 ? "\uC624\uC804" : "\uC624\uD6C4";
6478
+ const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
6479
+ return `${period} ${h12}:${mm}`;
6480
+ };
6481
+ var TimePicker = (props) => {
6482
+ const {
6483
+ value,
6484
+ onChange,
6485
+ step = 30,
6486
+ min,
6487
+ max,
6488
+ use12Hours = false,
6489
+ placeholder = "\uC2DC\uAC01 \uC120\uD0DD",
6490
+ disabled = false,
6491
+ size = "md",
6492
+ label,
6493
+ required,
6494
+ validations
6495
+ } = props;
6496
+ const fieldId = React40.useId();
6497
+ const triggerRef = React40.useRef(null);
6498
+ const contentRef = React40.useRef(null);
6499
+ const [isOpen, setOpen] = React40.useState(false);
6500
+ const [mounted, setMounted] = React40.useState(false);
6501
+ const [visible, setVisible] = React40.useState(false);
6502
+ const options = React40.useMemo(() => {
6503
+ const safeStep = step > 0 && step <= 720 ? step : 30;
6504
+ const lo = toMinutes(min) ?? 0;
6505
+ const hi = toMinutes(max) ?? 24 * 60 - 1;
6506
+ const out = [];
6507
+ for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
6508
+ return out;
6509
+ }, [step, min, max]);
6510
+ const close = React40.useCallback(() => setOpen(false), []);
6511
+ useClickOutside_default([triggerRef, contentRef], close, isOpen);
6512
+ useEscapeKey(isOpen, () => {
6513
+ close();
6514
+ triggerRef.current?.focus({ preventScroll: true });
6515
+ });
6516
+ const position = useAutoPosition_default(triggerRef, contentRef, mounted);
6517
+ React40.useEffect(() => {
6518
+ if (disabled && isOpen) setOpen(false);
6519
+ }, [disabled, isOpen]);
6520
+ React40.useEffect(() => {
6521
+ if (isOpen) {
6522
+ setMounted(true);
6523
+ const t2 = setTimeout(() => setVisible(true), 1);
6524
+ return () => clearTimeout(t2);
6525
+ }
6526
+ setVisible(false);
6527
+ const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS4);
6528
+ return () => clearTimeout(t);
6529
+ }, [isOpen]);
6530
+ const pick = (hhmm) => {
6531
+ onChange?.(hhmm);
6532
+ close();
6533
+ triggerRef.current?.focus({ preventScroll: true });
6534
+ };
6535
+ const control = /* @__PURE__ */ jsxs222("div", { className: clsx_default("lib-xplat-time-picker", size, disabled && "disabled"), children: [
6536
+ /* @__PURE__ */ jsx351(
6537
+ "div",
6538
+ {
6539
+ id: fieldId,
6540
+ ref: triggerRef,
6541
+ className: clsx_default("time-picker-trigger", hasError(validations) && "error"),
6542
+ role: "combobox",
6543
+ "aria-expanded": isOpen,
6544
+ "aria-haspopup": "listbox",
6545
+ "aria-invalid": hasError(validations) || void 0,
6546
+ tabIndex: disabled ? void 0 : 0,
6547
+ onClick: () => !disabled && setOpen((p) => !p),
6548
+ onKeyDown: (e) => {
6549
+ if (disabled) return;
6550
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
6551
+ e.preventDefault();
6552
+ setOpen(true);
6553
+ }
6554
+ },
6555
+ children: /* @__PURE__ */ jsx351("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
6556
+ }
6557
+ ),
6558
+ mounted && /* @__PURE__ */ jsx351(Portal_default, { children: /* @__PURE__ */ jsx351(
6559
+ "div",
6560
+ {
6561
+ ref: contentRef,
6562
+ className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit"),
6563
+ style: { ...position.position, width: triggerRef.current?.offsetWidth },
6564
+ role: "listbox",
6565
+ children: options.map((t) => /* @__PURE__ */ jsx351(
6566
+ "div",
6567
+ {
6568
+ className: clsx_default("time-picker-item", t === value && "is-selected"),
6569
+ role: "option",
6570
+ "aria-selected": t === value,
6571
+ tabIndex: 0,
6572
+ onClick: () => pick(t),
6573
+ onKeyDown: (e) => {
6574
+ if (e.key === "Enter" || e.key === " ") {
6575
+ e.preventDefault();
6576
+ pick(t);
6577
+ }
6578
+ },
6579
+ children: display(t, use12Hours)
6580
+ },
6581
+ t
6582
+ ))
6583
+ }
6584
+ ) })
6585
+ ] });
6586
+ return /* @__PURE__ */ jsx351(Field, { validations, label, required, htmlFor: fieldId, children: control });
6587
+ };
6588
+ TimePicker.displayName = "TimePicker";
6589
+ var TimePicker_default = TimePicker;
6590
+
6066
6591
  // src/components/Toast/Toast.tsx
6067
- import React39 from "react";
6592
+ import React41 from "react";
6068
6593
  import { createPortal as createPortal3 } from "react-dom";
6069
- import { jsx as jsx350, jsxs as jsxs221 } from "react/jsx-runtime";
6070
- var ToastContext = React39.createContext(null);
6594
+ import { jsx as jsx352, jsxs as jsxs223 } from "react/jsx-runtime";
6595
+ var ToastContext = React41.createContext(null);
6071
6596
  var useToast = () => {
6072
- const ctx = React39.useContext(ToastContext);
6597
+ const ctx = React41.useContext(ToastContext);
6073
6598
  if (!ctx) throw new Error("useToast must be used within ToastProvider");
6074
6599
  return ctx;
6075
6600
  };
6076
6601
  var EXIT_DURATION = 300;
6077
6602
  var ToastItemComponent = ({ item, isExiting, onClose }) => {
6078
- const ref = React39.useRef(null);
6079
- const [height, setHeight] = React39.useState(void 0);
6080
- React39.useEffect(() => {
6603
+ const ref = React41.useRef(null);
6604
+ const [height, setHeight] = React41.useState(void 0);
6605
+ React41.useEffect(() => {
6081
6606
  if (ref.current && !isExiting) {
6082
6607
  setHeight(ref.current.offsetHeight);
6083
6608
  }
6084
6609
  }, [isExiting]);
6085
- return /* @__PURE__ */ jsx350(
6610
+ return /* @__PURE__ */ jsx352(
6086
6611
  "div",
6087
6612
  {
6088
6613
  className: clsx_default("lib-xplat-toast-wrapper", { exit: isExiting }),
@@ -6090,15 +6615,15 @@ var ToastItemComponent = ({ item, isExiting, onClose }) => {
6090
6615
  maxHeight: isExiting ? 0 : height ?? "none",
6091
6616
  marginBottom: isExiting ? 0 : void 0
6092
6617
  },
6093
- children: /* @__PURE__ */ jsxs221(
6618
+ children: /* @__PURE__ */ jsxs223(
6094
6619
  "div",
6095
6620
  {
6096
6621
  ref,
6097
6622
  className: clsx_default("lib-xplat-toast", item.type, { exit: isExiting }),
6098
6623
  role: "alert",
6099
6624
  children: [
6100
- /* @__PURE__ */ jsx350("span", { className: "message", children: item.message }),
6101
- /* @__PURE__ */ jsx350("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
6625
+ /* @__PURE__ */ jsx352("span", { className: "message", children: item.message }),
6626
+ /* @__PURE__ */ jsx352("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
6102
6627
  ]
6103
6628
  }
6104
6629
  )
@@ -6109,13 +6634,13 @@ var ToastProvider = ({
6109
6634
  children,
6110
6635
  position = "top-right"
6111
6636
  }) => {
6112
- const [toasts, setToasts] = React39.useState([]);
6113
- const [removing, setRemoving] = React39.useState(/* @__PURE__ */ new Set());
6114
- const [mounted, setMounted] = React39.useState(false);
6115
- React39.useEffect(() => {
6637
+ const [toasts, setToasts] = React41.useState([]);
6638
+ const [removing, setRemoving] = React41.useState(/* @__PURE__ */ new Set());
6639
+ const [mounted, setMounted] = React41.useState(false);
6640
+ React41.useEffect(() => {
6116
6641
  setMounted(true);
6117
6642
  }, []);
6118
- const remove = React39.useCallback((id) => {
6643
+ const remove = React41.useCallback((id) => {
6119
6644
  setRemoving((prev) => new Set(prev).add(id));
6120
6645
  setTimeout(() => {
6121
6646
  setToasts((prev) => prev.filter((t) => t.id !== id));
@@ -6126,7 +6651,7 @@ var ToastProvider = ({
6126
6651
  });
6127
6652
  }, EXIT_DURATION);
6128
6653
  }, []);
6129
- const toast = React39.useCallback(
6654
+ const toast = React41.useCallback(
6130
6655
  (type, message, duration = 3e3) => {
6131
6656
  const id = `${Date.now()}-${Math.random()}`;
6132
6657
  setToasts((prev) => [...prev, { id, type, message }]);
@@ -6136,10 +6661,10 @@ var ToastProvider = ({
6136
6661
  },
6137
6662
  [remove]
6138
6663
  );
6139
- return /* @__PURE__ */ jsxs221(ToastContext.Provider, { value: { toast }, children: [
6664
+ return /* @__PURE__ */ jsxs223(ToastContext.Provider, { value: { toast }, children: [
6140
6665
  children,
6141
6666
  mounted && createPortal3(
6142
- /* @__PURE__ */ jsx350("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ jsx350(
6667
+ /* @__PURE__ */ jsx352("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ jsx352(
6143
6668
  ToastItemComponent,
6144
6669
  {
6145
6670
  item: t,
@@ -6155,8 +6680,8 @@ var ToastProvider = ({
6155
6680
  ToastProvider.displayName = "ToastProvider";
6156
6681
 
6157
6682
  // src/components/Tooltip/Tooltip.tsx
6158
- import React40 from "react";
6159
- import { Fragment as Fragment6, jsx as jsx351, jsxs as jsxs222 } from "react/jsx-runtime";
6683
+ import React42 from "react";
6684
+ import { Fragment as Fragment6, jsx as jsx353, jsxs as jsxs224 } from "react/jsx-runtime";
6160
6685
  var OFFSET = 12;
6161
6686
  var GAP = 8;
6162
6687
  var SHOW_DELAY = 300;
@@ -6165,18 +6690,20 @@ var Tooltip = (props) => {
6165
6690
  children,
6166
6691
  title,
6167
6692
  description,
6168
- type = "dark",
6693
+ variant,
6694
+ type,
6169
6695
  follow = false,
6170
6696
  disabled = false
6171
6697
  } = props;
6172
- const triggerRef = React40.useRef(null);
6173
- const tooltipRef = React40.useRef(null);
6174
- const [visible, setVisible] = React40.useState(false);
6175
- const [pos, setPos] = React40.useState({ left: 0, top: 0 });
6176
- const delayTimer = React40.useRef(0);
6177
- const rafRef = React40.useRef(0);
6178
- const cursor = React40.useRef(null);
6179
- const clamp = React40.useCallback((left, top, w, h) => {
6698
+ const shape = variant ?? type ?? "dark";
6699
+ const triggerRef = React42.useRef(null);
6700
+ const tooltipRef = React42.useRef(null);
6701
+ const [visible, setVisible] = React42.useState(false);
6702
+ const [pos, setPos] = React42.useState({ left: 0, top: 0 });
6703
+ const delayTimer = React42.useRef(0);
6704
+ const rafRef = React42.useRef(0);
6705
+ const cursor = React42.useRef(null);
6706
+ const clamp = React42.useCallback((left, top, w, h) => {
6180
6707
  const vw = window.innerWidth;
6181
6708
  const vh = window.innerHeight;
6182
6709
  return {
@@ -6184,7 +6711,7 @@ var Tooltip = (props) => {
6184
6711
  top: Math.min(Math.max(GAP, top), Math.max(GAP, vh - h - GAP))
6185
6712
  };
6186
6713
  }, []);
6187
- const placeAtCursor = React40.useCallback((x, y) => {
6714
+ const placeAtCursor = React42.useCallback((x, y) => {
6188
6715
  const el = tooltipRef.current;
6189
6716
  if (!el) return;
6190
6717
  const w = el.offsetWidth;
@@ -6195,7 +6722,7 @@ var Tooltip = (props) => {
6195
6722
  if (top < GAP) top = y + OFFSET;
6196
6723
  setPos(clamp(left, top, w, h));
6197
6724
  }, [clamp]);
6198
- const placeAtTrigger = React40.useCallback(() => {
6725
+ const placeAtTrigger = React42.useCallback(() => {
6199
6726
  const el = tooltipRef.current;
6200
6727
  const trigger = triggerRef.current;
6201
6728
  if (!el || !trigger) return;
@@ -6207,19 +6734,19 @@ var Tooltip = (props) => {
6207
6734
  const left = rect.left + rect.width / 2 - w / 2;
6208
6735
  setPos(clamp(left, top, w, h));
6209
6736
  }, [clamp]);
6210
- const reposition = React40.useCallback(() => {
6737
+ const reposition = React42.useCallback(() => {
6211
6738
  if (follow && cursor.current) {
6212
6739
  placeAtCursor(cursor.current.x, cursor.current.y);
6213
6740
  } else {
6214
6741
  placeAtTrigger();
6215
6742
  }
6216
6743
  }, [follow, placeAtCursor, placeAtTrigger]);
6217
- const handleMouseEnter = React40.useCallback((e) => {
6744
+ const handleMouseEnter = React42.useCallback((e) => {
6218
6745
  if (disabled) return;
6219
6746
  cursor.current = { x: e.clientX, y: e.clientY };
6220
6747
  delayTimer.current = window.setTimeout(() => setVisible(true), SHOW_DELAY);
6221
6748
  }, [disabled]);
6222
- const handleMouseMove = React40.useCallback((e) => {
6749
+ const handleMouseMove = React42.useCallback((e) => {
6223
6750
  cursor.current = { x: e.clientX, y: e.clientY };
6224
6751
  if (!visible || !follow) return;
6225
6752
  cancelAnimationFrame(rafRef.current);
@@ -6227,25 +6754,25 @@ var Tooltip = (props) => {
6227
6754
  if (cursor.current) placeAtCursor(cursor.current.x, cursor.current.y);
6228
6755
  });
6229
6756
  }, [visible, follow, placeAtCursor]);
6230
- const close = React40.useCallback(() => {
6757
+ const close = React42.useCallback(() => {
6231
6758
  window.clearTimeout(delayTimer.current);
6232
6759
  cancelAnimationFrame(rafRef.current);
6233
6760
  setVisible(false);
6234
6761
  }, []);
6235
- const handleMouseLeave = React40.useCallback(() => {
6762
+ const handleMouseLeave = React42.useCallback(() => {
6236
6763
  cursor.current = null;
6237
6764
  close();
6238
6765
  }, [close]);
6239
- const handleFocus = React40.useCallback(() => {
6766
+ const handleFocus = React42.useCallback(() => {
6240
6767
  if (disabled) return;
6241
6768
  cursor.current = null;
6242
6769
  setVisible(true);
6243
6770
  }, [disabled]);
6244
- React40.useLayoutEffect(() => {
6771
+ React42.useLayoutEffect(() => {
6245
6772
  if (!visible) return;
6246
6773
  reposition();
6247
6774
  }, [visible, reposition]);
6248
- React40.useEffect(() => {
6775
+ React42.useEffect(() => {
6249
6776
  if (!visible || follow) return;
6250
6777
  const onChange = () => placeAtTrigger();
6251
6778
  window.addEventListener("scroll", onChange, true);
@@ -6255,12 +6782,12 @@ var Tooltip = (props) => {
6255
6782
  window.removeEventListener("resize", onChange);
6256
6783
  };
6257
6784
  }, [visible, follow, placeAtTrigger]);
6258
- React40.useEffect(() => () => {
6785
+ React42.useEffect(() => () => {
6259
6786
  window.clearTimeout(delayTimer.current);
6260
6787
  cancelAnimationFrame(rafRef.current);
6261
6788
  }, []);
6262
- if (!title && !description) return /* @__PURE__ */ jsx351(Fragment6, { children });
6263
- return /* @__PURE__ */ jsxs222(
6789
+ if (!title && !description) return /* @__PURE__ */ jsx353(Fragment6, { children });
6790
+ return /* @__PURE__ */ jsxs224(
6264
6791
  "div",
6265
6792
  {
6266
6793
  ref: triggerRef,
@@ -6273,16 +6800,16 @@ var Tooltip = (props) => {
6273
6800
  onBlur: close,
6274
6801
  children: [
6275
6802
  children,
6276
- visible && /* @__PURE__ */ jsx351(Portal_default, { children: /* @__PURE__ */ jsxs222(
6803
+ visible && /* @__PURE__ */ jsx353(Portal_default, { children: /* @__PURE__ */ jsxs224(
6277
6804
  "div",
6278
6805
  {
6279
6806
  ref: tooltipRef,
6280
6807
  role: "tooltip",
6281
- className: clsx_default("lib-xplat-tooltip", type),
6808
+ className: clsx_default("lib-xplat-tooltip", shape),
6282
6809
  style: { position: "fixed", left: pos.left, top: pos.top },
6283
6810
  children: [
6284
- title && /* @__PURE__ */ jsx351("div", { className: "tooltip-title", children: title }),
6285
- description && /* @__PURE__ */ jsx351("div", { className: "tooltip-desc", children: description })
6811
+ title && /* @__PURE__ */ jsx353("div", { className: "tooltip-title", children: title }),
6812
+ description && /* @__PURE__ */ jsx353("div", { className: "tooltip-desc", children: description })
6286
6813
  ]
6287
6814
  }
6288
6815
  ) })
@@ -6294,11 +6821,11 @@ Tooltip.displayName = "Tooltip";
6294
6821
  var Tooltip_default = Tooltip;
6295
6822
 
6296
6823
  // src/components/Video/Video.tsx
6297
- import React41 from "react";
6298
- import { jsx as jsx352, jsxs as jsxs223 } from "react/jsx-runtime";
6299
- var PipIcon = () => /* @__PURE__ */ jsxs223("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
6300
- /* @__PURE__ */ jsx352("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
6301
- /* @__PURE__ */ jsx352("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
6824
+ import React43 from "react";
6825
+ import { jsx as jsx354, jsxs as jsxs225 } from "react/jsx-runtime";
6826
+ var PipIcon = () => /* @__PURE__ */ jsxs225("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
6827
+ /* @__PURE__ */ jsx354("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
6828
+ /* @__PURE__ */ jsx354("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
6302
6829
  ] });
6303
6830
  var formatTime = (sec) => {
6304
6831
  if (!Number.isFinite(sec) || sec < 0) return "0:00";
@@ -6306,7 +6833,7 @@ var formatTime = (sec) => {
6306
6833
  const s = Math.floor(sec % 60);
6307
6834
  return `${m}:${s.toString().padStart(2, "0")}`;
6308
6835
  };
6309
- var Video = React41.forwardRef((props, ref) => {
6836
+ var Video = React43.forwardRef((props, ref) => {
6310
6837
  const {
6311
6838
  src,
6312
6839
  poster,
@@ -6330,21 +6857,21 @@ var Video = React41.forwardRef((props, ref) => {
6330
6857
  children,
6331
6858
  ...rest
6332
6859
  } = props;
6333
- const containerRef = React41.useRef(null);
6334
- const videoRef = React41.useRef(null);
6335
- const [isPlaying, setIsPlaying] = React41.useState(Boolean(autoPlay));
6336
- const [isLoaded, setIsLoaded] = React41.useState(false);
6337
- const [currentTime, setCurrentTime] = React41.useState(0);
6338
- const [duration, setDuration] = React41.useState(0);
6339
- const [buffered, setBuffered] = React41.useState(0);
6340
- const [volume, setVolume] = React41.useState(1);
6341
- const [isMuted, setIsMuted] = React41.useState(Boolean(muted));
6342
- const [isFullscreen, setIsFullscreen] = React41.useState(false);
6343
- const [playbackRate, setPlaybackRate] = React41.useState(1);
6344
- const [rateMenuOpen, setRateMenuOpen] = React41.useState(false);
6345
- const [captionsOn, setCaptionsOn] = React41.useState(false);
6346
- const [isPip, setIsPip] = React41.useState(false);
6347
- const setRefs = React41.useCallback(
6860
+ const containerRef = React43.useRef(null);
6861
+ const videoRef = React43.useRef(null);
6862
+ const [isPlaying, setIsPlaying] = React43.useState(Boolean(autoPlay));
6863
+ const [isLoaded, setIsLoaded] = React43.useState(false);
6864
+ const [currentTime, setCurrentTime] = React43.useState(0);
6865
+ const [duration, setDuration] = React43.useState(0);
6866
+ const [buffered, setBuffered] = React43.useState(0);
6867
+ const [volume, setVolume] = React43.useState(1);
6868
+ const [isMuted, setIsMuted] = React43.useState(Boolean(muted));
6869
+ const [isFullscreen, setIsFullscreen] = React43.useState(false);
6870
+ const [playbackRate, setPlaybackRate] = React43.useState(1);
6871
+ const [rateMenuOpen, setRateMenuOpen] = React43.useState(false);
6872
+ const [captionsOn, setCaptionsOn] = React43.useState(false);
6873
+ const [isPip, setIsPip] = React43.useState(false);
6874
+ const setRefs = React43.useCallback(
6348
6875
  (el) => {
6349
6876
  videoRef.current = el;
6350
6877
  if (typeof ref === "function") ref(el);
@@ -6352,14 +6879,14 @@ var Video = React41.forwardRef((props, ref) => {
6352
6879
  },
6353
6880
  [ref]
6354
6881
  );
6355
- React41.useEffect(() => {
6882
+ React43.useEffect(() => {
6356
6883
  const onFsChange = () => {
6357
6884
  setIsFullscreen(document.fullscreenElement === containerRef.current);
6358
6885
  };
6359
6886
  document.addEventListener("fullscreenchange", onFsChange);
6360
6887
  return () => document.removeEventListener("fullscreenchange", onFsChange);
6361
6888
  }, []);
6362
- React41.useEffect(() => {
6889
+ React43.useEffect(() => {
6363
6890
  const v = videoRef.current;
6364
6891
  if (!v) return;
6365
6892
  const onEnter = () => setIsPip(true);
@@ -6473,13 +7000,13 @@ var Video = React41.forwardRef((props, ref) => {
6473
7000
  const volumePct = (isMuted ? 0 : volume) * 100;
6474
7001
  const VolumeGlyph = isMuted || volume === 0 ? VolumeXIcon_default : volume < 0.5 ? VolumeIcon_default : Volume2Icon_default;
6475
7002
  const pipSupported = typeof document !== "undefined" && "pictureInPictureEnabled" in document && document.pictureInPictureEnabled;
6476
- return /* @__PURE__ */ jsxs223(
7003
+ return /* @__PURE__ */ jsxs225(
6477
7004
  "div",
6478
7005
  {
6479
7006
  ref: containerRef,
6480
7007
  className: clsx_default("lib-xplat-video", showControls && "has-controls"),
6481
7008
  children: [
6482
- /* @__PURE__ */ jsx352(
7009
+ /* @__PURE__ */ jsx354(
6483
7010
  "video",
6484
7011
  {
6485
7012
  ref: setRefs,
@@ -6500,7 +7027,7 @@ var Video = React41.forwardRef((props, ref) => {
6500
7027
  children
6501
7028
  }
6502
7029
  ),
6503
- showCenterPlay && /* @__PURE__ */ jsx352(
7030
+ showCenterPlay && /* @__PURE__ */ jsx354(
6504
7031
  "button",
6505
7032
  {
6506
7033
  type: "button",
@@ -6512,11 +7039,11 @@ var Video = React41.forwardRef((props, ref) => {
6512
7039
  onClick: togglePlay,
6513
7040
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
6514
7041
  tabIndex: -1,
6515
- children: /* @__PURE__ */ jsx352("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx352(PlayCircleIcon_default, {}) })
7042
+ children: /* @__PURE__ */ jsx354("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx354(PlayCircleIcon_default, {}) })
6516
7043
  }
6517
7044
  ),
6518
- showControls && /* @__PURE__ */ jsxs223("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
6519
- /* @__PURE__ */ jsx352(
7045
+ showControls && /* @__PURE__ */ jsxs225("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
7046
+ /* @__PURE__ */ jsx354(
6520
7047
  "input",
6521
7048
  {
6522
7049
  type: "range",
@@ -6533,29 +7060,29 @@ var Video = React41.forwardRef((props, ref) => {
6533
7060
  }
6534
7061
  }
6535
7062
  ),
6536
- /* @__PURE__ */ jsxs223("div", { className: "controls-row", children: [
6537
- /* @__PURE__ */ jsx352(
7063
+ /* @__PURE__ */ jsxs225("div", { className: "controls-row", children: [
7064
+ /* @__PURE__ */ jsx354(
6538
7065
  "button",
6539
7066
  {
6540
7067
  type: "button",
6541
7068
  className: "control-btn",
6542
7069
  onClick: togglePlay,
6543
7070
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
6544
- children: isPlaying ? /* @__PURE__ */ jsx352(PauseIcon_default, {}) : /* @__PURE__ */ jsx352(PlayIcon_default, {})
7071
+ children: isPlaying ? /* @__PURE__ */ jsx354(PauseIcon_default, {}) : /* @__PURE__ */ jsx354(PlayIcon_default, {})
6545
7072
  }
6546
7073
  ),
6547
- /* @__PURE__ */ jsxs223("div", { className: "volume-group", children: [
6548
- /* @__PURE__ */ jsx352(
7074
+ /* @__PURE__ */ jsxs225("div", { className: "volume-group", children: [
7075
+ /* @__PURE__ */ jsx354(
6549
7076
  "button",
6550
7077
  {
6551
7078
  type: "button",
6552
7079
  className: "control-btn",
6553
7080
  onClick: toggleMute,
6554
7081
  "aria-label": isMuted ? "\uC74C\uC18C\uAC70 \uD574\uC81C" : "\uC74C\uC18C\uAC70",
6555
- children: /* @__PURE__ */ jsx352(VolumeGlyph, {})
7082
+ children: /* @__PURE__ */ jsx354(VolumeGlyph, {})
6556
7083
  }
6557
7084
  ),
6558
- /* @__PURE__ */ jsx352(
7085
+ /* @__PURE__ */ jsx354(
6559
7086
  "input",
6560
7087
  {
6561
7088
  type: "range",
@@ -6570,14 +7097,14 @@ var Video = React41.forwardRef((props, ref) => {
6570
7097
  }
6571
7098
  )
6572
7099
  ] }),
6573
- /* @__PURE__ */ jsxs223("span", { className: "time", children: [
7100
+ /* @__PURE__ */ jsxs225("span", { className: "time", children: [
6574
7101
  formatTime(currentTime),
6575
7102
  " / ",
6576
7103
  formatTime(duration)
6577
7104
  ] }),
6578
- /* @__PURE__ */ jsx352("div", { className: "controls-spacer" }),
6579
- playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs223("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
6580
- /* @__PURE__ */ jsxs223(
7105
+ /* @__PURE__ */ jsx354("div", { className: "controls-spacer" }),
7106
+ playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs225("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
7107
+ /* @__PURE__ */ jsxs225(
6581
7108
  "button",
6582
7109
  {
6583
7110
  type: "button",
@@ -6591,7 +7118,7 @@ var Video = React41.forwardRef((props, ref) => {
6591
7118
  ]
6592
7119
  }
6593
7120
  ),
6594
- rateMenuOpen && /* @__PURE__ */ jsx352("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx352("li", { children: /* @__PURE__ */ jsxs223(
7121
+ rateMenuOpen && /* @__PURE__ */ jsx354("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx354("li", { children: /* @__PURE__ */ jsxs225(
6595
7122
  "button",
6596
7123
  {
6597
7124
  type: "button",
@@ -6605,7 +7132,7 @@ var Video = React41.forwardRef((props, ref) => {
6605
7132
  }
6606
7133
  ) }, r2)) })
6607
7134
  ] }),
6608
- showCaptions && /* @__PURE__ */ jsx352(
7135
+ showCaptions && /* @__PURE__ */ jsx354(
6609
7136
  "button",
6610
7137
  {
6611
7138
  type: "button",
@@ -6613,37 +7140,37 @@ var Video = React41.forwardRef((props, ref) => {
6613
7140
  onClick: toggleCaptions,
6614
7141
  "aria-label": captionsOn ? "\uC790\uB9C9 \uB044\uAE30" : "\uC790\uB9C9 \uCF1C\uAE30",
6615
7142
  "aria-pressed": captionsOn,
6616
- children: /* @__PURE__ */ jsx352(TypeIcon_default, {})
7143
+ children: /* @__PURE__ */ jsx354(TypeIcon_default, {})
6617
7144
  }
6618
7145
  ),
6619
- showPip && pipSupported && /* @__PURE__ */ jsx352(
7146
+ showPip && pipSupported && /* @__PURE__ */ jsx354(
6620
7147
  "button",
6621
7148
  {
6622
7149
  type: "button",
6623
7150
  className: clsx_default("control-btn", isPip && "is-active"),
6624
7151
  onClick: togglePip,
6625
7152
  "aria-label": isPip ? "PIP \uC885\uB8CC" : "PIP",
6626
- children: /* @__PURE__ */ jsx352(PipIcon, {})
7153
+ children: /* @__PURE__ */ jsx354(PipIcon, {})
6627
7154
  }
6628
7155
  ),
6629
- showDownload && /* @__PURE__ */ jsx352(
7156
+ showDownload && /* @__PURE__ */ jsx354(
6630
7157
  "a",
6631
7158
  {
6632
7159
  className: "control-btn",
6633
7160
  href: src,
6634
7161
  download: downloadFileName ?? true,
6635
7162
  "aria-label": "\uB2E4\uC6B4\uB85C\uB4DC",
6636
- children: /* @__PURE__ */ jsx352(DownloadIcon_default, {})
7163
+ children: /* @__PURE__ */ jsx354(DownloadIcon_default, {})
6637
7164
  }
6638
7165
  ),
6639
- /* @__PURE__ */ jsx352(
7166
+ /* @__PURE__ */ jsx354(
6640
7167
  "button",
6641
7168
  {
6642
7169
  type: "button",
6643
7170
  className: "control-btn",
6644
7171
  onClick: toggleFullscreen,
6645
7172
  "aria-label": isFullscreen ? "\uC804\uCCB4\uD654\uBA74 \uC885\uB8CC" : "\uC804\uCCB4\uD654\uBA74",
6646
- children: isFullscreen ? /* @__PURE__ */ jsx352(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx352(MaximizeIcon_default, {})
7173
+ children: isFullscreen ? /* @__PURE__ */ jsx354(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx354(MaximizeIcon_default, {})
6647
7174
  }
6648
7175
  )
6649
7176
  ] })
@@ -6700,6 +7227,7 @@ export {
6700
7227
  SingleDatePicker_default as SingleDatePicker,
6701
7228
  Skeleton_default as Skeleton,
6702
7229
  Spinner_default as Spinner,
7230
+ Stat_default as Stat,
6703
7231
  Steps_default as Steps,
6704
7232
  Swiper_default as Swiper,
6705
7233
  Switch_default as Switch,
@@ -6711,6 +7239,7 @@ export {
6711
7239
  TableRow_default as TableRow,
6712
7240
  Tag_default as Tag,
6713
7241
  TextArea_default as TextArea,
7242
+ TimePicker_default as TimePicker,
6714
7243
  ToastProvider,
6715
7244
  Tooltip_default as Tooltip,
6716
7245
  Video_default as Video,