@x-plat/design-system 0.10.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 (110) 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 +4 -0
  4. package/dist/components/AutoResizeTextArea/index.d.ts +4 -0
  5. package/dist/components/AutoResizeTextArea/index.js +14 -5
  6. package/dist/components/Badge/index.d.cts +1 -1
  7. package/dist/components/Badge/index.d.ts +1 -1
  8. package/dist/components/ChatInput/index.cjs +20 -7
  9. package/dist/components/ChatInput/index.css +15 -0
  10. package/dist/components/ChatInput/index.d.cts +4 -0
  11. package/dist/components/ChatInput/index.d.ts +4 -0
  12. package/dist/components/ChatInput/index.js +20 -7
  13. package/dist/components/CheckBox/index.cjs +8 -3
  14. package/dist/components/CheckBox/index.css +15 -0
  15. package/dist/components/CheckBox/index.d.cts +1 -1
  16. package/dist/components/CheckBox/index.d.ts +1 -1
  17. package/dist/components/CheckBox/index.js +8 -3
  18. package/dist/components/DatePicker/index.cjs +179 -64
  19. package/dist/components/DatePicker/index.css +19 -0
  20. package/dist/components/DatePicker/index.js +179 -64
  21. package/dist/components/Drawer/index.cjs +83 -4
  22. package/dist/components/Drawer/index.js +83 -4
  23. package/dist/components/Dropdown/index.cjs +35 -7
  24. package/dist/components/Dropdown/index.js +35 -7
  25. package/dist/components/Editor/index.cjs +178 -21
  26. package/dist/components/Editor/index.js +178 -21
  27. package/dist/components/FieldMessage/index.cjs +8 -3
  28. package/dist/components/FieldMessage/index.css +15 -0
  29. package/dist/components/FieldMessage/index.d.cts +11 -4
  30. package/dist/components/FieldMessage/index.d.ts +11 -4
  31. package/dist/components/FieldMessage/index.js +8 -3
  32. package/dist/components/FileUpload/index.cjs +8 -3
  33. package/dist/components/FileUpload/index.css +15 -0
  34. package/dist/components/FileUpload/index.js +8 -3
  35. package/dist/components/ImageSelector/index.cjs +8 -3
  36. package/dist/components/ImageSelector/index.css +15 -0
  37. package/dist/components/ImageSelector/index.js +8 -3
  38. package/dist/components/Input/index.cjs +15 -5
  39. package/dist/components/Input/index.css +15 -0
  40. package/dist/components/Input/index.d.cts +4 -0
  41. package/dist/components/Input/index.d.ts +4 -0
  42. package/dist/components/Input/index.js +15 -5
  43. package/dist/components/Modal/index.cjs +84 -5
  44. package/dist/components/Modal/index.js +84 -5
  45. package/dist/components/NotificationBadge/index.d.cts +1 -1
  46. package/dist/components/NotificationBadge/index.d.ts +1 -1
  47. package/dist/components/Pagination/index.d.cts +1 -1
  48. package/dist/components/Pagination/index.d.ts +1 -1
  49. package/dist/components/PopOver/index.cjs +34 -6
  50. package/dist/components/PopOver/index.js +34 -6
  51. package/dist/components/Progress/index.d.cts +1 -1
  52. package/dist/components/Progress/index.d.ts +1 -1
  53. package/dist/components/Radio/index.cjs +8 -3
  54. package/dist/components/Radio/index.css +15 -0
  55. package/dist/components/Radio/index.d.cts +1 -1
  56. package/dist/components/Radio/index.d.ts +1 -1
  57. package/dist/components/Radio/index.js +8 -3
  58. package/dist/components/Select/index.cjs +99 -31
  59. package/dist/components/Select/index.css +54 -0
  60. package/dist/components/Select/index.d.cts +11 -0
  61. package/dist/components/Select/index.d.ts +11 -0
  62. package/dist/components/Select/index.js +99 -31
  63. package/dist/components/Spinner/index.d.cts +1 -1
  64. package/dist/components/Spinner/index.d.ts +1 -1
  65. package/dist/components/Stat/index.cjs +84 -0
  66. package/dist/components/Stat/index.css +96 -0
  67. package/dist/components/Stat/index.d.cts +37 -0
  68. package/dist/components/Stat/index.d.ts +37 -0
  69. package/dist/components/Stat/index.js +57 -0
  70. package/dist/components/Steps/index.d.cts +1 -1
  71. package/dist/components/Steps/index.d.ts +1 -1
  72. package/dist/components/Switch/index.cjs +14 -5
  73. package/dist/components/Switch/index.css +15 -0
  74. package/dist/components/Switch/index.d.cts +6 -1
  75. package/dist/components/Switch/index.d.ts +6 -1
  76. package/dist/components/Switch/index.js +14 -5
  77. package/dist/components/Tab/index.cjs +49 -25
  78. package/dist/components/Tab/index.css +4 -0
  79. package/dist/components/Tab/index.js +49 -25
  80. package/dist/components/TextArea/index.cjs +14 -4
  81. package/dist/components/TextArea/index.css +15 -0
  82. package/dist/components/TextArea/index.d.cts +4 -0
  83. package/dist/components/TextArea/index.d.ts +4 -0
  84. package/dist/components/TextArea/index.js +14 -4
  85. package/dist/components/TimePicker/index.cjs +448 -0
  86. package/dist/components/TimePicker/index.css +172 -0
  87. package/dist/components/TimePicker/index.d.cts +42 -0
  88. package/dist/components/TimePicker/index.d.ts +42 -0
  89. package/dist/components/TimePicker/index.js +411 -0
  90. package/dist/components/index.cjs +873 -359
  91. package/dist/components/index.css +275 -0
  92. package/dist/components/index.d.cts +3 -1
  93. package/dist/components/index.d.ts +3 -1
  94. package/dist/components/index.js +871 -359
  95. package/dist/index.cjs +897 -383
  96. package/dist/index.css +275 -0
  97. package/dist/index.d.cts +3 -1
  98. package/dist/index.d.ts +3 -1
  99. package/dist/index.js +895 -383
  100. package/dist/status-njWqQWFV.d.cts +20 -0
  101. package/dist/status-njWqQWFV.d.ts +20 -0
  102. package/guidelines/AGENT_PROMPT.md +3 -3
  103. package/guidelines/Guidelines.md +3 -0
  104. package/guidelines/components/editor.md +86 -0
  105. package/guidelines/components/form.md +19 -0
  106. package/guidelines/components/stat.md +31 -0
  107. package/guidelines/components/time-picker.md +49 -0
  108. package/package.json +1 -1
  109. package/dist/status-g_KP3qT6.d.cts +0 -8
  110. package/dist/status-g_KP3qT6.d.ts +0 -8
@@ -75,6 +75,7 @@ __export(components_exports, {
75
75
  SingleDatePicker: () => SingleDatePicker_default,
76
76
  Skeleton: () => Skeleton_default,
77
77
  Spinner: () => Spinner_default,
78
+ Stat: () => Stat_default,
78
79
  Steps: () => Steps_default,
79
80
  Swiper: () => Swiper_default,
80
81
  Switch: () => Switch_default,
@@ -86,6 +87,7 @@ __export(components_exports, {
86
87
  TableRow: () => TableRow_default,
87
88
  Tag: () => Tag_default,
88
89
  TextArea: () => TextArea_default,
90
+ TimePicker: () => TimePicker_default,
89
91
  ToastProvider: () => ToastProvider,
90
92
  Tooltip: () => Tooltip_default,
91
93
  Video: () => Video_default,
@@ -1631,11 +1633,16 @@ var FieldMessage = (props) => {
1631
1633
  FieldMessage.displayName = "FieldMessage";
1632
1634
  var FieldMessage_default = FieldMessage;
1633
1635
  var Field = (props) => {
1634
- const { validations, children } = props;
1635
- if (!validations || validations.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(import_jsx_runtime297.Fragment, { children });
1636
+ const { label, required = false, htmlFor, validations, children } = props;
1637
+ const hasMessages = !!validations && validations.length > 0;
1638
+ if (!label && !hasMessages) return /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(import_jsx_runtime297.Fragment, { children });
1636
1639
  return /* @__PURE__ */ (0, import_jsx_runtime297.jsxs)("div", { className: "lib-xplat-field", children: [
1640
+ label && /* @__PURE__ */ (0, import_jsx_runtime297.jsxs)("label", { className: "lib-xplat-field-label", htmlFor, children: [
1641
+ label,
1642
+ required && /* @__PURE__ */ (0, import_jsx_runtime297.jsx)("span", { className: "required", "aria-hidden": "true", children: "*" })
1643
+ ] }),
1637
1644
  children,
1638
- /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(FieldMessage, { validations })
1645
+ hasMessages && /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(FieldMessage, { validations })
1639
1646
  ] });
1640
1647
  };
1641
1648
  Field.displayName = "Field";
@@ -1646,7 +1653,9 @@ var import_jsx_runtime298 = require("react/jsx-runtime");
1646
1653
  var MAX_HEIGHT = 400;
1647
1654
  var AutoResizeTextArea = import_react2.default.forwardRef(
1648
1655
  (props, ref) => {
1649
- const { value, className, onChange, disabled, bare = false, validations, ...textareaProps } = props;
1656
+ const { value, className, onChange, disabled, bare = false, validations, label, required, ...textareaProps } = props;
1657
+ const autoId = import_react2.default.useId();
1658
+ const fieldId = props.id ?? autoId;
1650
1659
  const localRef = import_react2.default.useRef(null);
1651
1660
  const setRefs = (el) => {
1652
1661
  localRef.current = el;
@@ -1680,6 +1689,7 @@ var AutoResizeTextArea = import_react2.default.forwardRef(
1680
1689
  "aria-invalid": hasError(validations) || void 0,
1681
1690
  ...textareaProps,
1682
1691
  ref: setRefs,
1692
+ id: fieldId,
1683
1693
  className,
1684
1694
  disabled,
1685
1695
  value,
@@ -1693,12 +1703,13 @@ var AutoResizeTextArea = import_react2.default.forwardRef(
1693
1703
  "aria-invalid": hasError(validations) || void 0,
1694
1704
  ...textareaProps,
1695
1705
  ref: setRefs,
1706
+ id: fieldId,
1696
1707
  disabled,
1697
1708
  value,
1698
1709
  onChange: handleChange
1699
1710
  }
1700
1711
  ) }) });
1701
- return /* @__PURE__ */ (0, import_jsx_runtime298.jsx)(Field, { validations, children: control });
1712
+ return /* @__PURE__ */ (0, import_jsx_runtime298.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
1702
1713
  }
1703
1714
  );
1704
1715
  AutoResizeTextArea.displayName = "AutoResizeTextArea";
@@ -2916,8 +2927,11 @@ var ChatInput = import_react7.default.forwardRef(
2916
2927
  buttonType = "primary",
2917
2928
  onSubmit,
2918
2929
  onChange,
2919
- validations
2930
+ validations,
2931
+ label,
2932
+ required
2920
2933
  } = props;
2934
+ const fieldId = import_react7.default.useId();
2921
2935
  const isControlled = valueProp !== void 0;
2922
2936
  const [internalValue, setInternalValue] = import_react7.default.useState("");
2923
2937
  const value = isControlled ? valueProp : internalValue;
@@ -2942,6 +2956,7 @@ var ChatInput = import_react7.default.forwardRef(
2942
2956
  /* @__PURE__ */ (0, import_jsx_runtime308.jsx)(
2943
2957
  AutoResizeTextArea_default,
2944
2958
  {
2959
+ id: fieldId,
2945
2960
  ref,
2946
2961
  bare: true,
2947
2962
  className: "chat-input-textarea",
@@ -2966,7 +2981,7 @@ var ChatInput = import_react7.default.forwardRef(
2966
2981
  }
2967
2982
  )
2968
2983
  ] });
2969
- return /* @__PURE__ */ (0, import_jsx_runtime308.jsx)(Field, { validations, children: control });
2984
+ return /* @__PURE__ */ (0, import_jsx_runtime308.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
2970
2985
  }
2971
2986
  );
2972
2987
  ChatInput.displayName = "ChatInput";
@@ -3037,7 +3052,7 @@ Chip.displayName = "Chip";
3037
3052
  var Chip_default = Chip;
3038
3053
 
3039
3054
  // src/components/DatePicker/InputDatePicker/index.tsx
3040
- var import_react12 = __toESM(require("react"), 1);
3055
+ var import_react13 = __toESM(require("react"), 1);
3041
3056
 
3042
3057
  // src/components/Input/Input.tsx
3043
3058
  var import_react8 = __toESM(require("react"), 1);
@@ -3135,8 +3150,12 @@ var Input = import_react8.default.forwardRef((props, ref) => {
3135
3150
  suffix,
3136
3151
  disabled,
3137
3152
  validations,
3153
+ label,
3154
+ required,
3138
3155
  ...inputProps
3139
3156
  } = props;
3157
+ const autoId = import_react8.default.useId();
3158
+ const fieldId = inputProps.id ?? autoId;
3140
3159
  const localValue = formatValue(type, value);
3141
3160
  const handleChange = (e) => {
3142
3161
  let val = e.target.value;
@@ -3152,7 +3171,7 @@ var Input = import_react8.default.forwardRef((props, ref) => {
3152
3171
  onChange(event);
3153
3172
  }
3154
3173
  };
3155
- return /* @__PURE__ */ (0, import_jsx_runtime311.jsxs)("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
3174
+ return /* @__PURE__ */ (0, import_jsx_runtime311.jsx)(Field, { label, required, htmlFor: fieldId, children: /* @__PURE__ */ (0, import_jsx_runtime311.jsxs)("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
3156
3175
  /* @__PURE__ */ (0, import_jsx_runtime311.jsxs)(
3157
3176
  "div",
3158
3177
  {
@@ -3163,6 +3182,7 @@ var Input = import_react8.default.forwardRef((props, ref) => {
3163
3182
  {
3164
3183
  ...inputProps,
3165
3184
  ref,
3185
+ id: fieldId,
3166
3186
  disabled,
3167
3187
  type: type === "number" ? "text" : type,
3168
3188
  value: localValue,
@@ -3175,7 +3195,7 @@ var Input = import_react8.default.forwardRef((props, ref) => {
3175
3195
  }
3176
3196
  ),
3177
3197
  /* @__PURE__ */ (0, import_jsx_runtime311.jsx)(FieldMessage_default, { validations })
3178
- ] });
3198
+ ] }) });
3179
3199
  });
3180
3200
  Input.displayName = "Input";
3181
3201
  var Input_default = Input;
@@ -3205,16 +3225,96 @@ PasswordInput.displayName = "PasswordInput";
3205
3225
  var PasswordInput_default = PasswordInput;
3206
3226
 
3207
3227
  // src/components/Modal/Modal.tsx
3208
- var import_react10 = __toESM(require("react"), 1);
3228
+ var import_react11 = __toESM(require("react"), 1);
3209
3229
  var import_react_dom = require("react-dom");
3230
+
3231
+ // src/tokens/hooks/useOverlayKeyboard.ts
3232
+ var import_react10 = __toESM(require("react"), 1);
3233
+ var FOCUSABLE = [
3234
+ "a[href]",
3235
+ "button:not([disabled])",
3236
+ "input:not([disabled]):not([type='hidden'])",
3237
+ "select:not([disabled])",
3238
+ "textarea:not([disabled])",
3239
+ "[tabindex]:not([tabindex='-1'])"
3240
+ ].join(",");
3241
+ var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
3242
+ // 화면에 없는 것은 제외 (display:none 등)
3243
+ (n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
3244
+ );
3245
+ var useEscapeKey = (enabled, onEscape) => {
3246
+ import_react10.default.useEffect(() => {
3247
+ if (!enabled) return;
3248
+ const onKey = (e) => {
3249
+ if (e.key !== "Escape") return;
3250
+ if (e.defaultPrevented) return;
3251
+ e.preventDefault();
3252
+ onEscape();
3253
+ };
3254
+ document.addEventListener("keydown", onKey);
3255
+ return () => document.removeEventListener("keydown", onKey);
3256
+ }, [enabled, onEscape]);
3257
+ };
3258
+ var useFocusTrap = (containerRef, enabled, options = {}) => {
3259
+ const { trap = false, initialFocus } = options;
3260
+ const restoreRef = import_react10.default.useRef(null);
3261
+ import_react10.default.useEffect(() => {
3262
+ if (!enabled) return;
3263
+ restoreRef.current = document.activeElement;
3264
+ const raf = requestAnimationFrame(() => {
3265
+ const el = containerRef.current;
3266
+ if (!el) return;
3267
+ const target = initialFocus?.current ?? focusableIn(el)[0] ?? el;
3268
+ if (!target.hasAttribute("tabindex") && !focusableIn(el).includes(target)) {
3269
+ target.setAttribute("tabindex", "-1");
3270
+ }
3271
+ target.focus({ preventScroll: true });
3272
+ });
3273
+ return () => {
3274
+ cancelAnimationFrame(raf);
3275
+ const prev = restoreRef.current;
3276
+ if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
3277
+ };
3278
+ }, [enabled, containerRef, initialFocus]);
3279
+ import_react10.default.useEffect(() => {
3280
+ if (!enabled || !trap) return;
3281
+ const onKey = (e) => {
3282
+ if (e.key !== "Tab") return;
3283
+ const el = containerRef.current;
3284
+ if (!el) return;
3285
+ const items = focusableIn(el);
3286
+ if (items.length === 0) {
3287
+ e.preventDefault();
3288
+ return;
3289
+ }
3290
+ const first = items[0];
3291
+ const last = items[items.length - 1];
3292
+ const active = document.activeElement;
3293
+ if (e.shiftKey && (active === first || !el.contains(active))) {
3294
+ e.preventDefault();
3295
+ last.focus();
3296
+ } else if (!e.shiftKey && (active === last || !el.contains(active))) {
3297
+ e.preventDefault();
3298
+ first.focus();
3299
+ }
3300
+ };
3301
+ document.addEventListener("keydown", onKey);
3302
+ return () => document.removeEventListener("keydown", onKey);
3303
+ }, [enabled, trap, containerRef]);
3304
+ };
3305
+
3306
+ // src/components/Modal/Modal.tsx
3210
3307
  var import_jsx_runtime313 = require("react/jsx-runtime");
3211
3308
  var ANIMATION_DURATION_MS = 200;
3212
3309
  var Modal = (props) => {
3213
3310
  const { isOpen, onClose, children } = props;
3214
- const [mounted, setMounted] = import_react10.default.useState(false);
3215
- const [visible, setVisible] = import_react10.default.useState(false);
3216
- const [settled, setSettled] = import_react10.default.useState(false);
3217
- import_react10.default.useEffect(() => {
3311
+ const [mounted, setMounted] = import_react11.default.useState(false);
3312
+ const [visible, setVisible] = import_react11.default.useState(false);
3313
+ const [settled, setSettled] = import_react11.default.useState(false);
3314
+ const boxRef = import_react11.default.useRef(null);
3315
+ useEscapeKey(isOpen, onClose);
3316
+ useFocusTrap(boxRef, isOpen && mounted, { trap: true });
3317
+ import_react11.default.useEffect(() => {
3218
3318
  if (isOpen) {
3219
3319
  setMounted(true);
3220
3320
  const show = setTimeout(() => setVisible(true), 1);
@@ -3241,6 +3341,7 @@ var Modal = (props) => {
3241
3341
  children: /* @__PURE__ */ (0, import_jsx_runtime313.jsx)(
3242
3342
  "div",
3243
3343
  {
3344
+ ref: boxRef,
3244
3345
  className: clsx_default("lib-xplat-modal", "modal-box", stateClass, settled && "settled"),
3245
3346
  role: "dialog",
3246
3347
  "aria-modal": "true",
@@ -3257,9 +3358,9 @@ Modal.displayName = "Modal";
3257
3358
  var Modal_default = Modal;
3258
3359
 
3259
3360
  // src/components/DatePicker/SingleDatePicker/index.tsx
3260
- var import_react11 = __toESM(require("react"), 1);
3361
+ var import_react12 = __toESM(require("react"), 1);
3261
3362
  var import_jsx_runtime314 = require("react/jsx-runtime");
3262
- var DayCell2 = import_react11.default.memo(
3363
+ var DayCell2 = import_react12.default.memo(
3263
3364
  ({
3264
3365
  day,
3265
3366
  disabled,
@@ -3311,26 +3412,26 @@ var SingleDatePicker = (props) => {
3311
3412
  initialYear,
3312
3413
  initialMonth
3313
3414
  );
3314
- const [pickerMode, setPickerMode] = import_react11.default.useState("days");
3315
- const [yearRangeStart, setYearRangeStart] = import_react11.default.useState(
3415
+ const [pickerMode, setPickerMode] = import_react12.default.useState("days");
3416
+ const [yearRangeStart, setYearRangeStart] = import_react12.default.useState(
3316
3417
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
3317
3418
  );
3318
- const minTime = import_react11.default.useMemo(
3419
+ const minTime = import_react12.default.useMemo(
3319
3420
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
3320
3421
  [minDate]
3321
3422
  );
3322
- const maxTime = import_react11.default.useMemo(
3423
+ const maxTime = import_react12.default.useMemo(
3323
3424
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
3324
3425
  [maxDate]
3325
3426
  );
3326
- const highlightSet = import_react11.default.useMemo(() => {
3427
+ const highlightSet = import_react12.default.useMemo(() => {
3327
3428
  const set = /* @__PURE__ */ new Set();
3328
3429
  for (const h of highlightDates) {
3329
3430
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
3330
3431
  }
3331
3432
  return set;
3332
3433
  }, [highlightDates]);
3333
- const handleSelect = import_react11.default.useCallback(
3434
+ const handleSelect = import_react12.default.useCallback(
3334
3435
  (date) => {
3335
3436
  onChange?.(date);
3336
3437
  },
@@ -3459,8 +3560,8 @@ var formatDate = (date) => {
3459
3560
  };
3460
3561
  var InputDatePicker = (props) => {
3461
3562
  const { value, onChange, minDate, maxDate, disabled, locale = "ko", placeholder } = props;
3462
- const [isOpen, setIsOpen] = import_react12.default.useState(false);
3463
- const [tempDate, setTempDate] = import_react12.default.useState(value ?? /* @__PURE__ */ new Date());
3563
+ const [isOpen, setIsOpen] = import_react13.default.useState(false);
3564
+ const [tempDate, setTempDate] = import_react13.default.useState(value ?? /* @__PURE__ */ new Date());
3464
3565
  const handleOpen = () => {
3465
3566
  if (disabled) return;
3466
3567
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -3509,23 +3610,27 @@ InputDatePicker.displayName = "InputDatePicker";
3509
3610
  var InputDatePicker_default = InputDatePicker;
3510
3611
 
3511
3612
  // src/components/DatePicker/PopupPicker/index.tsx
3512
- var import_react16 = __toESM(require("react"), 1);
3613
+ var import_react17 = __toESM(require("react"), 1);
3513
3614
 
3514
3615
  // src/components/DatePicker/RangePicker/index.tsx
3515
- var import_react15 = __toESM(require("react"), 1);
3616
+ var import_react16 = __toESM(require("react"), 1);
3516
3617
 
3517
3618
  // src/components/Tab/Tab.tsx
3518
- var import_react14 = __toESM(require("react"), 1);
3619
+ var import_react15 = __toESM(require("react"), 1);
3519
3620
 
3520
3621
  // src/components/Tab/TabItem.tsx
3521
- var import_react13 = __toESM(require("react"), 1);
3622
+ var import_react14 = __toESM(require("react"), 1);
3522
3623
  var import_jsx_runtime316 = require("react/jsx-runtime");
3523
- var TabItem = import_react13.default.forwardRef((props, ref) => {
3624
+ var TabItem = import_react14.default.forwardRef((props, ref) => {
3524
3625
  const { isActive: isActive2, title, onClick } = props;
3525
3626
  return /* @__PURE__ */ (0, import_jsx_runtime316.jsx)(
3526
- "div",
3627
+ "button",
3527
3628
  {
3528
3629
  ref,
3630
+ type: "button",
3631
+ role: "tab",
3632
+ "aria-selected": isActive2,
3633
+ tabIndex: isActive2 ? 0 : -1,
3529
3634
  className: clsx_default("tab-item", isActive2 ? "active" : null),
3530
3635
  onClick,
3531
3636
  children: title
@@ -3540,44 +3645,64 @@ var import_jsx_runtime317 = require("react/jsx-runtime");
3540
3645
  var Tab = (props) => {
3541
3646
  const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
3542
3647
  const shape = variant ?? type ?? "default";
3543
- const [underlineStyle, setUnderlineStyle] = import_react14.default.useState({
3648
+ const [underlineStyle, setUnderlineStyle] = import_react15.default.useState({
3544
3649
  left: 0,
3545
3650
  width: 0
3546
3651
  });
3547
- const itemRefs = import_react14.default.useRef([]);
3652
+ const itemRefs = import_react15.default.useRef([]);
3653
+ const handleKeyDown = (e) => {
3654
+ const last = tabs.length - 1;
3655
+ let next = null;
3656
+ if (e.key === "ArrowRight") next = activeIndex >= last ? 0 : activeIndex + 1;
3657
+ else if (e.key === "ArrowLeft") next = activeIndex <= 0 ? last : activeIndex - 1;
3658
+ else if (e.key === "Home") next = 0;
3659
+ else if (e.key === "End") next = last;
3660
+ if (next === null) return;
3661
+ e.preventDefault();
3662
+ onChange(tabs[next], next);
3663
+ itemRefs.current[next]?.focus();
3664
+ };
3548
3665
  const handleChangeActiveTab = (tabItem, tabIdx) => {
3549
3666
  onChange(tabItem, tabIdx);
3550
3667
  };
3551
- import_react14.default.useEffect(() => {
3668
+ import_react15.default.useEffect(() => {
3552
3669
  const el = itemRefs.current[activeIndex];
3553
3670
  if (el) {
3554
3671
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
3555
3672
  }
3556
3673
  }, [activeIndex, tabs.length]);
3557
- return /* @__PURE__ */ (0, import_jsx_runtime317.jsxs)("div", { className: clsx_default("lib-xplat-tab", `type-${shape}`, size), children: [
3558
- tabs.map((tab, idx) => /* @__PURE__ */ (0, import_jsx_runtime317.jsx)(
3559
- TabItem_default,
3560
- {
3561
- onClick: () => handleChangeActiveTab(tab, idx),
3562
- isActive: activeIndex === idx,
3563
- ref: (el) => {
3564
- itemRefs.current[idx] = el;
3565
- },
3566
- title: tab.title
3567
- },
3568
- `${tab.value}_${idx}`
3569
- )),
3570
- shape === "toggle" && /* @__PURE__ */ (0, import_jsx_runtime317.jsx)(
3571
- "div",
3572
- {
3573
- className: "tab-toggle-underline",
3574
- style: {
3575
- left: underlineStyle.left,
3576
- width: underlineStyle.width
3577
- }
3578
- }
3579
- )
3580
- ] });
3674
+ return /* @__PURE__ */ (0, import_jsx_runtime317.jsxs)(
3675
+ "div",
3676
+ {
3677
+ className: clsx_default("lib-xplat-tab", `type-${shape}`, size),
3678
+ role: "tablist",
3679
+ onKeyDown: handleKeyDown,
3680
+ children: [
3681
+ tabs.map((tab, idx) => /* @__PURE__ */ (0, import_jsx_runtime317.jsx)(
3682
+ TabItem_default,
3683
+ {
3684
+ onClick: () => handleChangeActiveTab(tab, idx),
3685
+ isActive: activeIndex === idx,
3686
+ ref: (el) => {
3687
+ itemRefs.current[idx] = el;
3688
+ },
3689
+ title: tab.title
3690
+ },
3691
+ `${tab.value}_${idx}`
3692
+ )),
3693
+ shape === "toggle" && /* @__PURE__ */ (0, import_jsx_runtime317.jsx)(
3694
+ "div",
3695
+ {
3696
+ className: "tab-toggle-underline",
3697
+ style: {
3698
+ left: underlineStyle.left,
3699
+ width: underlineStyle.width
3700
+ }
3701
+ }
3702
+ )
3703
+ ]
3704
+ }
3705
+ );
3581
3706
  };
3582
3707
  Tab.displayName = "Tab";
3583
3708
  var Tab_default = Tab;
@@ -3593,7 +3718,7 @@ var RangePicker = (props) => {
3593
3718
  maxDate,
3594
3719
  locale = "ko"
3595
3720
  } = props;
3596
- const [activeTab, setActiveTab] = import_react15.default.useState("start");
3721
+ const [activeTab, setActiveTab] = import_react16.default.useState("start");
3597
3722
  const handleStartChange = (date) => {
3598
3723
  if (!date) return;
3599
3724
  const newStart = date > endDate ? endDate : date;
@@ -3678,7 +3803,7 @@ var RangePicker_default = RangePicker;
3678
3803
  var import_jsx_runtime319 = require("react/jsx-runtime");
3679
3804
  var PopupPicker = (props) => {
3680
3805
  const { component, type, locale } = props;
3681
- const [isOpen, setIsOpen] = import_react16.default.useState(false);
3806
+ const [isOpen, setIsOpen] = import_react17.default.useState(false);
3682
3807
  const handleClick = () => setIsOpen(true);
3683
3808
  const handleClose = () => setIsOpen(false);
3684
3809
  const handleSingleChange = (date) => {
@@ -3687,7 +3812,7 @@ var PopupPicker = (props) => {
3687
3812
  handleClose();
3688
3813
  };
3689
3814
  return /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: "lib-xplat-popup-datepicker", children: [
3690
- import_react16.default.cloneElement(component, { onClick: handleClick }),
3815
+ import_react17.default.cloneElement(component, { onClick: handleClick }),
3691
3816
  /* @__PURE__ */ (0, import_jsx_runtime319.jsx)(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
3692
3817
  /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: "popup-datepicker-content", children: [
3693
3818
  type === "single" && /* @__PURE__ */ (0, import_jsx_runtime319.jsx)(
@@ -3746,15 +3871,18 @@ Divider.displayName = "Divider";
3746
3871
  var Divider_default = Divider;
3747
3872
 
3748
3873
  // src/components/Drawer/Drawer.tsx
3749
- var import_react17 = __toESM(require("react"), 1);
3874
+ var import_react18 = __toESM(require("react"), 1);
3750
3875
  var import_react_dom2 = require("react-dom");
3751
3876
  var import_jsx_runtime321 = require("react/jsx-runtime");
3752
3877
  var ANIMATION_DURATION_MS2 = 250;
3753
3878
  var Drawer = (props) => {
3754
3879
  const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
3755
- const [mounted, setMounted] = import_react17.default.useState(false);
3756
- const [visible, setVisible] = import_react17.default.useState(false);
3757
- import_react17.default.useEffect(() => {
3880
+ const [mounted, setMounted] = import_react18.default.useState(false);
3881
+ const [visible, setVisible] = import_react18.default.useState(false);
3882
+ const panelRef = import_react18.default.useRef(null);
3883
+ useEscapeKey(isOpen, onClose);
3884
+ useFocusTrap(panelRef, isOpen && mounted, { trap: true });
3885
+ import_react18.default.useEffect(() => {
3758
3886
  if (isOpen) {
3759
3887
  setMounted(true);
3760
3888
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -3776,6 +3904,7 @@ var Drawer = (props) => {
3776
3904
  children: /* @__PURE__ */ (0, import_jsx_runtime321.jsxs)(
3777
3905
  "div",
3778
3906
  {
3907
+ ref: panelRef,
3779
3908
  className: clsx_default("lib-xplat-drawer", placement, size, stateClass),
3780
3909
  role: "dialog",
3781
3910
  "aria-modal": "true",
@@ -3798,7 +3927,7 @@ Drawer.displayName = "Drawer";
3798
3927
  var Drawer_default = Drawer;
3799
3928
 
3800
3929
  // src/components/Dropdown/Dropdown.tsx
3801
- var import_react20 = __toESM(require("react"), 1);
3930
+ var import_react21 = __toESM(require("react"), 1);
3802
3931
 
3803
3932
  // src/tokens/hooks/Portal.tsx
3804
3933
  var import_react_dom3 = __toESM(require("react-dom"), 1);
@@ -3810,13 +3939,13 @@ Portal.displayName = "Portal";
3810
3939
  var Portal_default = Portal;
3811
3940
 
3812
3941
  // src/tokens/hooks/useAutoPosition.ts
3813
- var import_react18 = __toESM(require("react"), 1);
3942
+ var import_react19 = __toESM(require("react"), 1);
3814
3943
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3815
- const [position, setPosition] = import_react18.default.useState({
3944
+ const [position, setPosition] = import_react19.default.useState({
3816
3945
  position: {},
3817
3946
  direction: "bottom"
3818
3947
  });
3819
- const calculatePosition = import_react18.default.useCallback(() => {
3948
+ const calculatePosition = import_react19.default.useCallback(() => {
3820
3949
  if (!triggerRef.current || !popRef.current) return;
3821
3950
  const triggerRect = triggerRef.current.getBoundingClientRect();
3822
3951
  const popW = popRef.current.offsetWidth;
@@ -3843,13 +3972,13 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3843
3972
  direction
3844
3973
  });
3845
3974
  }, [triggerRef, popRef]);
3846
- import_react18.default.useLayoutEffect(() => {
3975
+ import_react19.default.useLayoutEffect(() => {
3847
3976
  if (!enabled) return;
3848
3977
  calculatePosition();
3849
3978
  const raf = requestAnimationFrame(calculatePosition);
3850
3979
  return () => cancelAnimationFrame(raf);
3851
3980
  }, [calculatePosition, enabled]);
3852
- import_react18.default.useEffect(() => {
3981
+ import_react19.default.useEffect(() => {
3853
3982
  if (!enabled || !popRef.current) return;
3854
3983
  const observer = new ResizeObserver(() => {
3855
3984
  calculatePosition();
@@ -3857,7 +3986,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3857
3986
  observer.observe(popRef.current);
3858
3987
  return () => observer.disconnect();
3859
3988
  }, [calculatePosition, enabled, popRef]);
3860
- import_react18.default.useEffect(() => {
3989
+ import_react19.default.useEffect(() => {
3861
3990
  if (!enabled) return;
3862
3991
  window.addEventListener("resize", calculatePosition);
3863
3992
  window.addEventListener("scroll", calculatePosition, true);
@@ -3871,9 +4000,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3871
4000
  var useAutoPosition_default = useAutoPosition;
3872
4001
 
3873
4002
  // src/tokens/hooks/useClickOutside.ts
3874
- var import_react19 = __toESM(require("react"), 1);
4003
+ var import_react20 = __toESM(require("react"), 1);
3875
4004
  var useClickOutside = (refs, handler, enabled = true) => {
3876
- import_react19.default.useEffect(() => {
4005
+ import_react20.default.useEffect(() => {
3877
4006
  if (!enabled) return;
3878
4007
  const refArray = Array.isArray(refs) ? refs : [refs];
3879
4008
  const listener = (event) => {
@@ -3899,14 +4028,18 @@ var useClickOutside_default = useClickOutside;
3899
4028
  var import_jsx_runtime322 = require("react/jsx-runtime");
3900
4029
  var Dropdown = (props) => {
3901
4030
  const { items, children } = props;
3902
- const [isOpen, setIsOpen] = import_react20.default.useState(false);
3903
- const [mounted, setMounted] = import_react20.default.useState(false);
3904
- const [visible, setVisible] = import_react20.default.useState(false);
3905
- const triggerRef = import_react20.default.useRef(null);
3906
- const menuRef = import_react20.default.useRef(null);
4031
+ const [isOpen, setIsOpen] = import_react21.default.useState(false);
4032
+ const [mounted, setMounted] = import_react21.default.useState(false);
4033
+ const [visible, setVisible] = import_react21.default.useState(false);
4034
+ const triggerRef = import_react21.default.useRef(null);
4035
+ const menuRef = import_react21.default.useRef(null);
3907
4036
  const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
3908
4037
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
3909
- import_react20.default.useEffect(() => {
4038
+ useEscapeKey(isOpen, () => {
4039
+ setIsOpen(false);
4040
+ triggerRef.current?.focus({ preventScroll: true });
4041
+ });
4042
+ import_react21.default.useEffect(() => {
3910
4043
  if (isOpen) {
3911
4044
  setMounted(true);
3912
4045
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -3960,7 +4093,7 @@ Dropdown.displayName = "Dropdown";
3960
4093
  var Dropdown_default = Dropdown;
3961
4094
 
3962
4095
  // src/components/Editor/Editor.tsx
3963
- var import_react21 = __toESM(require("react"), 1);
4096
+ var import_react22 = __toESM(require("react"), 1);
3964
4097
  var import_jsx_runtime323 = require("react/jsx-runtime");
3965
4098
  var DEFAULT_TOOLBAR = [
3966
4099
  "bold",
@@ -4010,6 +4143,15 @@ var ALLOWED_ATTRS = {
4010
4143
  a: ["href", "target", "rel"],
4011
4144
  img: ["src", "alt"]
4012
4145
  };
4146
+ var DROP_WITH_CONTENT = /* @__PURE__ */ new Set([
4147
+ "script",
4148
+ "style",
4149
+ "noscript",
4150
+ "iframe",
4151
+ "object",
4152
+ "embed",
4153
+ "template"
4154
+ ]);
4013
4155
  var sanitizeHtml = (input) => {
4014
4156
  const doc = new DOMParser().parseFromString(`<div>${input}</div>`, "text/html");
4015
4157
  const root = doc.body.firstElementChild;
@@ -4018,6 +4160,10 @@ var sanitizeHtml = (input) => {
4018
4160
  const children = Array.from(node.children);
4019
4161
  for (const child of children) {
4020
4162
  const tag = child.tagName.toLowerCase();
4163
+ if (DROP_WITH_CONTENT.has(tag)) {
4164
+ node.removeChild(child);
4165
+ continue;
4166
+ }
4021
4167
  if (!ALLOWED_TAGS.has(tag)) {
4022
4168
  while (child.firstChild) node.insertBefore(child.firstChild, child);
4023
4169
  node.removeChild(child);
@@ -4068,26 +4214,30 @@ var Editor = (props) => {
4068
4214
  onImageUpload,
4069
4215
  minHeight = 200
4070
4216
  } = props;
4071
- const editorRef = import_react21.default.useRef(null);
4072
- const lastRangeRef = import_react21.default.useRef(null);
4073
- const composingRef = import_react21.default.useRef(false);
4074
- const [isFocused, setIsFocused] = import_react21.default.useState(false);
4075
- const [isEmpty, setIsEmpty] = import_react21.default.useState(!value);
4076
- const [activeFormats, setActiveFormats] = import_react21.default.useState(/* @__PURE__ */ new Set());
4077
- const [slashOpen, setSlashOpen] = import_react21.default.useState(false);
4078
- const [slashFilter, setSlashFilter] = import_react21.default.useState("");
4079
- const [slashIdx, setSlashIdx] = import_react21.default.useState(0);
4080
- const [slashPos, setSlashPos] = import_react21.default.useState({ top: 0, left: 0 });
4081
- const slashStartRangeRef = import_react21.default.useRef(null);
4082
- const [linkOpen, setLinkOpen] = import_react21.default.useState(false);
4083
- const [linkValue, setLinkValue] = import_react21.default.useState("");
4084
- const [linkPos, setLinkPos] = import_react21.default.useState({ top: 0, left: 0 });
4085
- import_react21.default.useEffect(() => {
4086
- if (!editorRef.current) return;
4087
- if (editorRef.current.innerHTML !== value) {
4088
- editorRef.current.innerHTML = sanitizeHtml(value || "");
4089
- updateEmpty();
4090
- }
4217
+ const editorRef = import_react22.default.useRef(null);
4218
+ const lastRangeRef = import_react22.default.useRef(null);
4219
+ const composingRef = import_react22.default.useRef(false);
4220
+ const [isFocused, setIsFocused] = import_react22.default.useState(false);
4221
+ const [isEmpty, setIsEmpty] = import_react22.default.useState(!value);
4222
+ const [activeFormats, setActiveFormats] = import_react22.default.useState(/* @__PURE__ */ new Set());
4223
+ const [slashOpen, setSlashOpen] = import_react22.default.useState(false);
4224
+ const [slashFilter, setSlashFilter] = import_react22.default.useState("");
4225
+ const [slashIdx, setSlashIdx] = import_react22.default.useState(0);
4226
+ const [slashPos, setSlashPos] = import_react22.default.useState({ top: 0, left: 0 });
4227
+ const slashStartRangeRef = import_react22.default.useRef(null);
4228
+ const [linkOpen, setLinkOpen] = import_react22.default.useState(false);
4229
+ const [linkValue, setLinkValue] = import_react22.default.useState("");
4230
+ const [linkPos, setLinkPos] = import_react22.default.useState({ top: 0, left: 0 });
4231
+ const lastEmittedRef = import_react22.default.useRef(null);
4232
+ import_react22.default.useEffect(() => {
4233
+ const el = editorRef.current;
4234
+ if (!el) return;
4235
+ if (value === lastEmittedRef.current) return;
4236
+ if (el.innerHTML === value) return;
4237
+ el.innerHTML = sanitizeHtml(value || "");
4238
+ if (!el.firstChild) el.innerHTML = "<p><br></p>";
4239
+ lastEmittedRef.current = null;
4240
+ updateEmpty();
4091
4241
  }, [value]);
4092
4242
  const updateEmpty = () => {
4093
4243
  const el = editorRef.current;
@@ -4103,10 +4253,19 @@ var Editor = (props) => {
4103
4253
  }
4104
4254
  };
4105
4255
  const restoreSelection = () => {
4106
- if (!lastRangeRef.current) return;
4256
+ const range = lastRangeRef.current;
4257
+ if (!range) return;
4258
+ if (!editorRef.current?.contains(range.startContainer)) {
4259
+ lastRangeRef.current = null;
4260
+ return;
4261
+ }
4107
4262
  const sel = window.getSelection();
4108
- sel?.removeAllRanges();
4109
- sel?.addRange(lastRangeRef.current);
4263
+ try {
4264
+ sel?.removeAllRanges();
4265
+ sel?.addRange(range);
4266
+ } catch {
4267
+ lastRangeRef.current = null;
4268
+ }
4110
4269
  };
4111
4270
  const updateActiveFormats = () => {
4112
4271
  if (!editorRef.current) return;
@@ -4135,6 +4294,96 @@ var Editor = (props) => {
4135
4294
  const setBlock = (tag) => {
4136
4295
  exec("formatBlock", tag);
4137
4296
  };
4297
+ const closestPre = () => {
4298
+ const sel = window.getSelection();
4299
+ const node = sel?.anchorNode;
4300
+ if (!node || !editorRef.current?.contains(node)) return null;
4301
+ const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
4302
+ return el?.closest("pre") ?? null;
4303
+ };
4304
+ const insertCodeBlock = () => {
4305
+ const el = editorRef.current;
4306
+ const sel = window.getSelection();
4307
+ if (!el || !sel || sel.rangeCount === 0) return;
4308
+ const existing = closestPre();
4309
+ if (existing) {
4310
+ const p = document.createElement("p");
4311
+ p.textContent = existing.textContent || "";
4312
+ if (!p.textContent) p.innerHTML = "<br>";
4313
+ existing.replaceWith(p);
4314
+ placeCaretAtEnd(p);
4315
+ handleInput();
4316
+ return;
4317
+ }
4318
+ const range = sel.getRangeAt(0);
4319
+ const frag = range.cloneContents();
4320
+ const holder = document.createElement("div");
4321
+ holder.appendChild(frag);
4322
+ const BLOCK = /^(p|div|h[1-6]|li|blockquote|pre|tr)$/i;
4323
+ const linesOf = (node) => {
4324
+ const out = [];
4325
+ let cur = "";
4326
+ for (const child of Array.from(node.childNodes)) {
4327
+ if (child.nodeType === Node.TEXT_NODE) {
4328
+ cur += child.textContent || "";
4329
+ } else if (child.nodeName === "BR") {
4330
+ out.push(cur);
4331
+ cur = "";
4332
+ } else if (BLOCK.test(child.nodeName)) {
4333
+ if (cur) {
4334
+ out.push(cur);
4335
+ cur = "";
4336
+ }
4337
+ const sub = linesOf(child);
4338
+ out.push(...sub.length > 0 ? sub : [""]);
4339
+ } else {
4340
+ cur += linesOf(child).join("\n");
4341
+ }
4342
+ }
4343
+ if (cur) out.push(cur);
4344
+ return out;
4345
+ };
4346
+ const text = linesOf(holder).join("\n").replace(/\n+$/, "");
4347
+ const pre = document.createElement("pre");
4348
+ const code = document.createElement("code");
4349
+ code.textContent = text || "";
4350
+ pre.appendChild(code);
4351
+ range.deleteContents();
4352
+ range.insertNode(pre);
4353
+ ensureParagraphAfter(pre);
4354
+ placeCaretAtEnd(code);
4355
+ handleInput();
4356
+ };
4357
+ const insertTextAtCaret = (text) => {
4358
+ const sel = window.getSelection();
4359
+ if (!sel || sel.rangeCount === 0) return;
4360
+ const range = sel.getRangeAt(0);
4361
+ range.deleteContents();
4362
+ const node = document.createTextNode(text);
4363
+ range.insertNode(node);
4364
+ range.setStartAfter(node);
4365
+ range.collapse(true);
4366
+ sel.removeAllRanges();
4367
+ sel.addRange(range);
4368
+ handleInput();
4369
+ };
4370
+ const ensureParagraphAfter = (node) => {
4371
+ const next = node.nextElementSibling;
4372
+ if (next && next.tagName === "P") return;
4373
+ const p = document.createElement("p");
4374
+ p.innerHTML = "<br>";
4375
+ node.after(p);
4376
+ };
4377
+ const placeCaretAtEnd = (node) => {
4378
+ const sel = window.getSelection();
4379
+ if (!sel) return;
4380
+ const r2 = document.createRange();
4381
+ r2.selectNodeContents(node);
4382
+ r2.collapse(false);
4383
+ sel.removeAllRanges();
4384
+ sel.addRange(r2);
4385
+ editorRef.current?.focus();
4386
+ };
4138
4387
  const insertDivider = () => {
4139
4388
  exec("insertHorizontalRule");
4140
4389
  const el = editorRef.current;
@@ -4181,7 +4430,9 @@ var Editor = (props) => {
4181
4430
  const range = sel.getRangeAt(0);
4182
4431
  slashStartRangeRef.current = range.cloneRange();
4183
4432
  const rect = range.getBoundingClientRect();
4184
- const editorRect = editorRef.current.getBoundingClientRect();
4433
+ const editorEl = editorRef.current;
4434
+ if (!editorEl) return;
4435
+ const editorRect = editorEl.getBoundingClientRect();
4185
4436
  setSlashPos({
4186
4437
  top: rect.bottom - editorRect.top + 4,
4187
4438
  left: rect.left - editorRect.left
@@ -4196,7 +4447,7 @@ var Editor = (props) => {
4196
4447
  setSlashIdx(0);
4197
4448
  slashStartRangeRef.current = null;
4198
4449
  };
4199
- const filteredSlashItems = import_react21.default.useMemo(() => {
4450
+ const filteredSlashItems = import_react22.default.useMemo(() => {
4200
4451
  if (!slashFilter) return SLASH_ITEMS;
4201
4452
  const f = slashFilter.toLowerCase();
4202
4453
  return SLASH_ITEMS.filter((it) => it.label.toLowerCase().includes(f) || it.key.includes(f));
@@ -4239,7 +4490,7 @@ var Editor = (props) => {
4239
4490
  setBlock("blockquote");
4240
4491
  break;
4241
4492
  case "code-block":
4242
- setBlock("pre");
4493
+ insertCodeBlock();
4243
4494
  break;
4244
4495
  case "divider":
4245
4496
  insertDivider();
@@ -4257,7 +4508,9 @@ var Editor = (props) => {
4257
4508
  if (!sel || sel.rangeCount === 0) return;
4258
4509
  const range = sel.getRangeAt(0);
4259
4510
  const rect = range.getBoundingClientRect();
4260
- const editorRect = editorRef.current.getBoundingClientRect();
4511
+ const editorEl2 = editorRef.current;
4512
+ if (!editorEl2) return;
4513
+ const editorRect = editorEl2.getBoundingClientRect();
4261
4514
  setLinkPos({
4262
4515
  top: rect.bottom - editorRect.top + 4,
4263
4516
  left: rect.left - editorRect.left
@@ -4290,13 +4543,13 @@ var Editor = (props) => {
4290
4543
  if (node.nodeType !== Node.TEXT_NODE) return false;
4291
4544
  const text = (node.textContent || "").slice(0, range.startOffset);
4292
4545
  const patterns = [
4293
- [/^###\s$/, () => setBlock("h3")],
4294
- [/^##\s$/, () => setBlock("h2")],
4295
- [/^#\s$/, () => setBlock("h1")],
4296
- [/^-\s$/, () => exec("insertUnorderedList")],
4297
- [/^\*\s$/, () => exec("insertUnorderedList")],
4298
- [/^1\.\s$/, () => exec("insertOrderedList")],
4299
- [/^>\s$/, () => setBlock("blockquote")]
4546
+ [/^###$/, () => setBlock("h3")],
4547
+ [/^##$/, () => setBlock("h2")],
4548
+ [/^#$/, () => setBlock("h1")],
4549
+ [/^-$/, () => exec("insertUnorderedList")],
4550
+ [/^\*$/, () => exec("insertUnorderedList")],
4551
+ [/^1\.$/, () => exec("insertOrderedList")],
4552
+ [/^>$/, () => setBlock("blockquote")]
4300
4553
  ];
4301
4554
  for (const [re, fn] of patterns) {
4302
4555
  if (re.test(text)) {
@@ -4316,7 +4569,9 @@ var Editor = (props) => {
4316
4569
  if (composingRef.current) return;
4317
4570
  const el = editorRef.current;
4318
4571
  if (!el) return;
4319
- onChange?.(el.innerHTML);
4572
+ const html = el.innerHTML;
4573
+ lastEmittedRef.current = html;
4574
+ onChange?.(html);
4320
4575
  updateEmpty();
4321
4576
  updateActiveFormats();
4322
4577
  if (slashOpen) {
@@ -4344,6 +4599,31 @@ var Editor = (props) => {
4344
4599
  };
4345
4600
  const handleKeyDown = (e) => {
4346
4601
  if (readOnly) return;
4602
+ if (composingRef.current || e.nativeEvent.isComposing || e.keyCode === 229) return;
4603
+ const pre = closestPre();
4604
+ if (pre && !slashOpen) {
4605
+ if (e.key === "Enter" && !e.shiftKey) {
4606
+ const text = pre.textContent || "";
4607
+ if (text.endsWith("\n\n")) {
4608
+ e.preventDefault();
4609
+ const code = pre.querySelector("code") ?? pre;
4610
+ code.textContent = text.replace(/\n\n$/, "");
4611
+ ensureParagraphAfter(pre);
4612
+ const next = pre.nextElementSibling;
4613
+ if (next) placeCaretAtEnd(next);
4614
+ handleInput();
4615
+ return;
4616
+ }
4617
+ e.preventDefault();
4618
+ insertTextAtCaret("\n");
4619
+ return;
4620
+ }
4621
+ if (e.key === "Tab") {
4622
+ e.preventDefault();
4623
+ insertTextAtCaret(" ");
4624
+ return;
4625
+ }
4626
+ }
4347
4627
  if (slashOpen) {
4348
4628
  if (e.key === "ArrowDown") {
4349
4629
  e.preventDefault();
@@ -4390,6 +4670,7 @@ var Editor = (props) => {
4390
4670
  return;
4391
4671
  }
4392
4672
  }
4673
+ if (pre) return;
4393
4674
  if (enableSlashCommand && e.key === "/") {
4394
4675
  setTimeout(openSlashMenu, 0);
4395
4676
  }
@@ -4402,8 +4683,12 @@ var Editor = (props) => {
4402
4683
  const handlePaste = (e) => {
4403
4684
  if (readOnly) return;
4404
4685
  e.preventDefault();
4405
- const html = e.clipboardData.getData("text/html");
4406
4686
  const text = e.clipboardData.getData("text/plain");
4687
+ if (closestPre()) {
4688
+ insertTextAtCaret(text);
4689
+ return;
4690
+ }
4691
+ const html = e.clipboardData.getData("text/html");
4407
4692
  const clean = html ? sanitizeHtml(html) : escapeHtml(text);
4408
4693
  document.execCommand("insertHTML", false, clean);
4409
4694
  handleInput();
@@ -4427,6 +4712,7 @@ var Editor = (props) => {
4427
4712
  updateActiveFormats();
4428
4713
  };
4429
4714
  const onToolbarAction = (item) => {
4715
+ if (closestPre() && item !== "code-block") return;
4430
4716
  switch (item) {
4431
4717
  case "bold":
4432
4718
  exec("bold");
@@ -4468,7 +4754,7 @@ var Editor = (props) => {
4468
4754
  setBlock("blockquote");
4469
4755
  break;
4470
4756
  case "code-block":
4471
- setBlock("pre");
4757
+ insertCodeBlock();
4472
4758
  break;
4473
4759
  case "link":
4474
4760
  openLinkEditor();
@@ -4498,6 +4784,10 @@ var Editor = (props) => {
4498
4784
  ref: editorRef,
4499
4785
  contentEditable: !readOnly,
4500
4786
  suppressContentEditableWarning: true,
4787
+ role: "textbox",
4788
+ "aria-multiline": "true",
4789
+ "aria-readonly": readOnly || void 0,
4790
+ "aria-label": placeholder,
4501
4791
  className: "lib-xplat-editor__editable",
4502
4792
  onInput: handleInput,
4503
4793
  onKeyDown: handleKeyDown,
@@ -4589,7 +4879,7 @@ var EditorToolbar = ({ items, active, onAction }) => {
4589
4879
  )) });
4590
4880
  };
4591
4881
  var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
4592
- import_react21.default.useEffect(() => {
4882
+ import_react22.default.useEffect(() => {
4593
4883
  const handleClickOutside = (e) => {
4594
4884
  const target = e.target;
4595
4885
  const menu = document.querySelector(".lib-xplat-editor__slash-menu");
@@ -4623,8 +4913,8 @@ var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
4623
4913
  );
4624
4914
  };
4625
4915
  var LinkPopover = ({ position, value, onChange, onConfirm, onClose }) => {
4626
- const inputRef = import_react21.default.useRef(null);
4627
- import_react21.default.useEffect(() => {
4916
+ const inputRef = import_react22.default.useRef(null);
4917
+ import_react22.default.useEffect(() => {
4628
4918
  inputRef.current?.focus();
4629
4919
  }, []);
4630
4920
  return /* @__PURE__ */ (0, import_jsx_runtime323.jsxs)(
@@ -4682,7 +4972,7 @@ EmptyState.displayName = "EmptyState";
4682
4972
  var EmptyState_default = EmptyState;
4683
4973
 
4684
4974
  // src/components/FileUpload/FileUpload.tsx
4685
- var import_react22 = __toESM(require("react"), 1);
4975
+ var import_react23 = __toESM(require("react"), 1);
4686
4976
  var import_jsx_runtime325 = require("react/jsx-runtime");
4687
4977
  var FileUpload = (props) => {
4688
4978
  const {
@@ -4694,8 +4984,8 @@ var FileUpload = (props) => {
4694
4984
  description,
4695
4985
  validations
4696
4986
  } = props;
4697
- const [isDragOver, setIsDragOver] = import_react22.default.useState(false);
4698
- const inputRef = import_react22.default.useRef(null);
4987
+ const [isDragOver, setIsDragOver] = import_react23.default.useState(false);
4988
+ const inputRef = import_react23.default.useRef(null);
4699
4989
  const handleFiles = (fileList) => {
4700
4990
  let files = Array.from(fileList);
4701
4991
  if (maxSize) {
@@ -4757,10 +5047,10 @@ FileUpload.displayName = "FileUpload";
4757
5047
  var FileUpload_default = FileUpload;
4758
5048
 
4759
5049
  // src/components/HtmlTypeWriter/HtmlTypeWriter.tsx
4760
- var import_react24 = __toESM(require("react"), 1);
5050
+ var import_react25 = __toESM(require("react"), 1);
4761
5051
 
4762
5052
  // src/components/HtmlTypeWriter/utils.ts
4763
- var import_react23 = __toESM(require("react"), 1);
5053
+ var import_react24 = __toESM(require("react"), 1);
4764
5054
  var voidTags = /* @__PURE__ */ new Set([
4765
5055
  "br",
4766
5056
  "img",
@@ -4828,15 +5118,15 @@ var convertNodeToReactWithRange = (node, typedLen, rangeMap) => {
4828
5118
  props[attr.name] = attr.value;
4829
5119
  });
4830
5120
  if (voidTags.has(tag)) {
4831
- return import_react23.default.createElement(tag, props);
5121
+ return import_react24.default.createElement(tag, props);
4832
5122
  }
4833
5123
  const children = Array.from(element.childNodes).map((child) => convertNodeToReactWithRange(child, typedLen, rangeMap)).filter((n) => n != null);
4834
- return import_react23.default.createElement(tag, props, ...children);
5124
+ return import_react24.default.createElement(tag, props, ...children);
4835
5125
  };
4836
5126
  var htmlToReactProgressive = (root, typedLen, rangeMap) => {
4837
5127
  const nodes = Array.from(root.childNodes).map((child, idx) => {
4838
5128
  const node = convertNodeToReactWithRange(child, typedLen, rangeMap);
4839
- return node == null ? null : import_react23.default.createElement(import_react23.default.Fragment, { key: idx }, node);
5129
+ return node == null ? null : import_react24.default.createElement(import_react24.default.Fragment, { key: idx }, node);
4840
5130
  }).filter(Boolean);
4841
5131
  return nodes.length === 0 ? null : nodes;
4842
5132
  };
@@ -4849,20 +5139,20 @@ var HtmlTypeWriter = ({
4849
5139
  onDone,
4850
5140
  onChange
4851
5141
  }) => {
4852
- const [typedLen, setTypedLen] = import_react24.default.useState(0);
4853
- const doneCalledRef = import_react24.default.useRef(false);
4854
- const { doc, rangeMap, totalLength } = import_react24.default.useMemo(() => {
5142
+ const [typedLen, setTypedLen] = import_react25.default.useState(0);
5143
+ const doneCalledRef = import_react25.default.useRef(false);
5144
+ const { doc, rangeMap, totalLength } = import_react25.default.useMemo(() => {
4855
5145
  if (typeof window === "undefined") return { doc: null, rangeMap: /* @__PURE__ */ new Map(), totalLength: 0 };
4856
5146
  const decoded = decodeHtmlEntities(html);
4857
5147
  const doc2 = new DOMParser().parseFromString(decoded, "text/html");
4858
5148
  const { rangeMap: rangeMap2, totalLength: totalLength2 } = buildRangeMap(doc2.body);
4859
5149
  return { doc: doc2, rangeMap: rangeMap2, totalLength: totalLength2 };
4860
5150
  }, [html]);
4861
- import_react24.default.useEffect(() => {
5151
+ import_react25.default.useEffect(() => {
4862
5152
  setTypedLen(0);
4863
5153
  doneCalledRef.current = false;
4864
5154
  }, [html]);
4865
- import_react24.default.useEffect(() => {
5155
+ import_react25.default.useEffect(() => {
4866
5156
  if (!totalLength) return;
4867
5157
  if (typedLen >= totalLength) return;
4868
5158
  const timer = window.setInterval(() => {
@@ -4870,18 +5160,18 @@ var HtmlTypeWriter = ({
4870
5160
  }, duration);
4871
5161
  return () => window.clearInterval(timer);
4872
5162
  }, [typedLen, totalLength, duration]);
4873
- import_react24.default.useEffect(() => {
5163
+ import_react25.default.useEffect(() => {
4874
5164
  if (typedLen > 0 && typedLen < totalLength) {
4875
5165
  onChange?.();
4876
5166
  }
4877
5167
  }, [typedLen, totalLength, onChange]);
4878
- import_react24.default.useEffect(() => {
5168
+ import_react25.default.useEffect(() => {
4879
5169
  if (typedLen === totalLength && totalLength > 0 && !doneCalledRef.current) {
4880
5170
  doneCalledRef.current = true;
4881
5171
  onDone?.();
4882
5172
  }
4883
5173
  }, [typedLen, totalLength, onDone]);
4884
- const parsed = import_react24.default.useMemo(
5174
+ const parsed = import_react25.default.useMemo(
4885
5175
  () => doc ? htmlToReactProgressive(doc.body, typedLen, rangeMap) : null,
4886
5176
  [doc, typedLen, rangeMap]
4887
5177
  );
@@ -4891,12 +5181,12 @@ HtmlTypeWriter.displayName = "HtmlTypeWriter";
4891
5181
  var HtmlTypeWriter_default = HtmlTypeWriter;
4892
5182
 
4893
5183
  // src/components/ImageSelector/ImageSelector.tsx
4894
- var import_react25 = __toESM(require("react"), 1);
5184
+ var import_react26 = __toESM(require("react"), 1);
4895
5185
  var import_jsx_runtime327 = require("react/jsx-runtime");
4896
5186
  var ImageSelector = (props) => {
4897
5187
  const { value, label, onChange, validations } = props;
4898
- const [previewUrl, setPreviewUrl] = import_react25.default.useState();
4899
- import_react25.default.useEffect(() => {
5188
+ const [previewUrl, setPreviewUrl] = import_react26.default.useState();
5189
+ import_react26.default.useEffect(() => {
4900
5190
  if (!value) {
4901
5191
  setPreviewUrl(void 0);
4902
5192
  return;
@@ -4905,7 +5195,7 @@ var ImageSelector = (props) => {
4905
5195
  setPreviewUrl(url);
4906
5196
  return () => URL.revokeObjectURL(url);
4907
5197
  }, [value]);
4908
- const inputRef = import_react25.default.useRef(null);
5198
+ const inputRef = import_react26.default.useRef(null);
4909
5199
  const handleFileChange = (e) => {
4910
5200
  const selectedFile = e.target.files?.[0];
4911
5201
  if (selectedFile) {
@@ -5088,17 +5378,21 @@ Pagination.displayName = "Pagination";
5088
5378
  var Pagination_default = Pagination;
5089
5379
 
5090
5380
  // src/components/PopOver/PopOver.tsx
5091
- var import_react26 = __toESM(require("react"), 1);
5381
+ var import_react27 = __toESM(require("react"), 1);
5092
5382
  var import_jsx_runtime332 = require("react/jsx-runtime");
5093
5383
  var PopOver = (props) => {
5094
5384
  const { children, isOpen, onClose, PopOverEl } = props;
5095
- const popRef = import_react26.default.useRef(null);
5096
- const triggerRef = import_react26.default.useRef(null);
5097
- const [localOpen, setLocalOpen] = import_react26.default.useState(false);
5098
- const [eventTrigger, setEventTrigger] = import_react26.default.useState(false);
5385
+ const popRef = import_react27.default.useRef(null);
5386
+ const triggerRef = import_react27.default.useRef(null);
5387
+ const [localOpen, setLocalOpen] = import_react27.default.useState(false);
5388
+ const [eventTrigger, setEventTrigger] = import_react27.default.useState(false);
5099
5389
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
5390
+ useEscapeKey(isOpen, () => {
5391
+ onClose();
5392
+ triggerRef.current?.focus({ preventScroll: true });
5393
+ });
5100
5394
  const position = useAutoPosition_default(triggerRef, popRef, localOpen);
5101
- import_react26.default.useEffect(() => {
5395
+ import_react27.default.useEffect(() => {
5102
5396
  if (isOpen) {
5103
5397
  setLocalOpen(isOpen);
5104
5398
  setTimeout(() => {
@@ -5183,12 +5477,12 @@ Progress.displayName = "Progress";
5183
5477
  var Progress_default = Progress;
5184
5478
 
5185
5479
  // src/components/Radio/RadioGroupContext.tsx
5186
- var import_react27 = __toESM(require("react"), 1);
5187
- var RadioGroupContext = import_react27.default.createContext(
5480
+ var import_react28 = __toESM(require("react"), 1);
5481
+ var RadioGroupContext = import_react28.default.createContext(
5188
5482
  null
5189
5483
  );
5190
5484
  var useRadioGroupContext = () => {
5191
- return import_react27.default.useContext(RadioGroupContext);
5485
+ return import_react28.default.useContext(RadioGroupContext);
5192
5486
  };
5193
5487
  var RadioGroupContext_default = RadioGroupContext;
5194
5488
 
@@ -5264,19 +5558,19 @@ RadioGroup.displayName = "RadioGroup";
5264
5558
  var RadioGroup_default = RadioGroup;
5265
5559
 
5266
5560
  // src/components/Select/Select.tsx
5267
- var import_react30 = __toESM(require("react"), 1);
5561
+ var import_react31 = __toESM(require("react"), 1);
5268
5562
 
5269
5563
  // src/components/Select/context.ts
5270
- var import_react28 = __toESM(require("react"), 1);
5271
- var SelectContext = import_react28.default.createContext(null);
5564
+ var import_react29 = __toESM(require("react"), 1);
5565
+ var SelectContext = import_react29.default.createContext(null);
5272
5566
  var context_default = SelectContext;
5273
5567
 
5274
5568
  // src/components/Select/SelectItem.tsx
5275
- var import_react29 = __toESM(require("react"), 1);
5569
+ var import_react30 = __toESM(require("react"), 1);
5276
5570
  var import_jsx_runtime336 = require("react/jsx-runtime");
5277
5571
  var SelectItem = (props) => {
5278
5572
  const { children, value, onClick, disabled = false } = props;
5279
- const ctx = import_react29.default.useContext(context_default);
5573
+ const ctx = import_react30.default.useContext(context_default);
5280
5574
  const handleClick = (e) => {
5281
5575
  e.preventDefault();
5282
5576
  e.stopPropagation();
@@ -5316,32 +5610,37 @@ var SelectRoot = (props) => {
5316
5610
  onChange,
5317
5611
  children,
5318
5612
  disabled = false,
5613
+ searchable = false,
5614
+ searchPlaceholder = "\uAC80\uC0C9",
5319
5615
  error = false,
5320
5616
  validations,
5617
+ label,
5618
+ required,
5321
5619
  size = "md"
5322
5620
  } = props;
5323
- const itemChildren = import_react30.default.Children.toArray(children).filter(
5324
- (child) => import_react30.default.isValidElement(child) && child.type === SelectItem_default
5621
+ const fieldId = import_react31.default.useId();
5622
+ const itemChildren = import_react31.default.Children.toArray(children).filter(
5623
+ (child) => import_react31.default.isValidElement(child) && child.type === SelectItem_default
5325
5624
  );
5326
5625
  const isControlled = valueProp !== void 0;
5327
- const [isOpen, setOpen] = import_react30.default.useState(false);
5328
- const [uncontrolledLabel, setUncontrolledLabel] = import_react30.default.useState(null);
5329
- const [uncontrolledValue, setUncontrolledValue] = import_react30.default.useState(void 0);
5330
- const controlledLabel = import_react30.default.useMemo(() => {
5626
+ const [isOpen, setOpen] = import_react31.default.useState(false);
5627
+ const [uncontrolledLabel, setUncontrolledLabel] = import_react31.default.useState(null);
5628
+ const [uncontrolledValue, setUncontrolledValue] = import_react31.default.useState(void 0);
5629
+ const controlledLabel = import_react31.default.useMemo(() => {
5331
5630
  if (!isControlled) return null;
5332
5631
  const match = itemChildren.find((child) => child.props.value === valueProp);
5333
5632
  return match ? match.props.children : null;
5334
5633
  }, [isControlled, valueProp, itemChildren]);
5335
5634
  const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
5336
5635
  const selectedValue = isControlled ? valueProp : uncontrolledValue;
5337
- const triggerRef = import_react30.default.useRef(null);
5338
- const contentRef = import_react30.default.useRef(null);
5339
- const [mounted, setMounted] = import_react30.default.useState(false);
5340
- const [visible, setVisible] = import_react30.default.useState(false);
5341
- import_react30.default.useEffect(() => {
5636
+ const triggerRef = import_react31.default.useRef(null);
5637
+ const contentRef = import_react31.default.useRef(null);
5638
+ const [mounted, setMounted] = import_react31.default.useState(false);
5639
+ const [visible, setVisible] = import_react31.default.useState(false);
5640
+ import_react31.default.useEffect(() => {
5342
5641
  if (disabled && isOpen) setOpen(false);
5343
5642
  }, [disabled, isOpen]);
5344
- import_react30.default.useEffect(() => {
5643
+ import_react31.default.useEffect(() => {
5345
5644
  if (isOpen) {
5346
5645
  setMounted(true);
5347
5646
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -5351,22 +5650,42 @@ var SelectRoot = (props) => {
5351
5650
  const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS3);
5352
5651
  return () => clearTimeout(t);
5353
5652
  }, [isOpen]);
5354
- const open = import_react30.default.useCallback(() => setOpen(true), []);
5355
- const close = import_react30.default.useCallback(() => setOpen(false), []);
5356
- const toggle = import_react30.default.useCallback(() => setOpen((prev) => !prev), []);
5653
+ const [query, setQuery] = import_react31.default.useState("");
5654
+ const textOf = (node) => {
5655
+ if (node === null || node === void 0 || typeof node === "boolean") return "";
5656
+ if (typeof node === "string" || typeof node === "number") return String(node);
5657
+ if (Array.isArray(node)) return node.map(textOf).join("");
5658
+ if (import_react31.default.isValidElement(node)) return textOf(node.props.children);
5659
+ return "";
5660
+ };
5661
+ const visibleItems = import_react31.default.useMemo(() => {
5662
+ if (!searchable || !query.trim()) return itemChildren;
5663
+ const q = query.trim().toLowerCase();
5664
+ return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
5665
+ }, [searchable, query, itemChildren]);
5666
+ const open = import_react31.default.useCallback(() => setOpen(true), []);
5667
+ const close = import_react31.default.useCallback(() => {
5668
+ setOpen(false);
5669
+ setQuery("");
5670
+ }, []);
5671
+ const toggle = import_react31.default.useCallback(() => setOpen((prev) => !prev), []);
5357
5672
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
5673
+ useEscapeKey(isOpen, () => {
5674
+ close();
5675
+ triggerRef.current?.focus({ preventScroll: true });
5676
+ });
5358
5677
  const position = useAutoPosition_default(triggerRef, contentRef, mounted);
5359
- const setSelected = import_react30.default.useCallback(
5360
- (label, itemValue) => {
5678
+ const setSelected = import_react31.default.useCallback(
5679
+ (label2, itemValue) => {
5361
5680
  if (!isControlled) {
5362
- setUncontrolledLabel(label);
5681
+ setUncontrolledLabel(label2);
5363
5682
  setUncontrolledValue(itemValue);
5364
5683
  }
5365
- onChange?.(itemValue, label);
5684
+ onChange?.(itemValue, label2);
5366
5685
  },
5367
5686
  [isControlled, onChange]
5368
5687
  );
5369
- const ctxValue = import_react30.default.useMemo(
5688
+ const ctxValue = import_react31.default.useMemo(
5370
5689
  () => ({
5371
5690
  isOpen,
5372
5691
  mounted,
@@ -5402,6 +5721,7 @@ var SelectRoot = (props) => {
5402
5721
  /* @__PURE__ */ (0, import_jsx_runtime337.jsxs)(
5403
5722
  "div",
5404
5723
  {
5724
+ id: fieldId,
5405
5725
  ref: triggerRef,
5406
5726
  className: clsx_default(
5407
5727
  "select-trigger",
@@ -5444,20 +5764,33 @@ var SelectRoot = (props) => {
5444
5764
  ]
5445
5765
  }
5446
5766
  ),
5447
- mounted && /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(
5767
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime337.jsxs)(
5448
5768
  "div",
5449
5769
  {
5450
5770
  className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
5451
5771
  ref: contentRef,
5452
5772
  style: { ...position.position, width: triggerRef.current?.offsetWidth },
5453
5773
  role: "listbox",
5454
- children: /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(context_default.Provider, { value: ctxValue, children: itemChildren })
5774
+ children: [
5775
+ searchable && /* @__PURE__ */ (0, import_jsx_runtime337.jsx)("div", { className: "select-search", children: /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(
5776
+ "input",
5777
+ {
5778
+ type: "text",
5779
+ value: query,
5780
+ placeholder: searchPlaceholder,
5781
+ onChange: (e) => setQuery(e.target.value),
5782
+ autoFocus: true,
5783
+ "aria-label": searchPlaceholder
5784
+ }
5785
+ ) }),
5786
+ /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(context_default.Provider, { value: ctxValue, children: visibleItems.length > 0 ? visibleItems : /* @__PURE__ */ (0, import_jsx_runtime337.jsx)("div", { className: "select-empty", children: "\uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" }) })
5787
+ ]
5455
5788
  }
5456
5789
  ) })
5457
5790
  ]
5458
5791
  }
5459
5792
  ) });
5460
- return /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(Field, { validations, children: control });
5793
+ return /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
5461
5794
  };
5462
5795
  SelectRoot.displayName = "Select";
5463
5796
  var Select = Object.assign(SelectRoot, {
@@ -5537,8 +5870,44 @@ var Spinner = (props) => {
5537
5870
  Spinner.displayName = "Spinner";
5538
5871
  var Spinner_default = Spinner;
5539
5872
 
5540
- // src/components/Steps/Steps.tsx
5873
+ // src/components/Stat/Stat.tsx
5541
5874
  var import_jsx_runtime340 = require("react/jsx-runtime");
5875
+ var ARROW = {
5876
+ up: "\u25B2",
5877
+ down: "\u25BC",
5878
+ flat: "\u2014"
5879
+ };
5880
+ var Stat = (props) => {
5881
+ const {
5882
+ label,
5883
+ value,
5884
+ unit,
5885
+ description,
5886
+ trend,
5887
+ icon,
5888
+ size = "md",
5889
+ type = "primary"
5890
+ } = props;
5891
+ const statusType = normalizeStatus(type);
5892
+ return /* @__PURE__ */ (0, import_jsx_runtime340.jsxs)("div", { className: clsx_default("lib-xplat-stat", size, statusType), children: [
5893
+ /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("div", { className: "stat-label", children: label }),
5894
+ /* @__PURE__ */ (0, import_jsx_runtime340.jsxs)("div", { className: "stat-value-row", children: [
5895
+ icon && /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { className: "stat-icon", children: icon }),
5896
+ /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { className: "stat-value", children: value }),
5897
+ unit && /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { className: "stat-unit", children: unit }),
5898
+ trend && /* @__PURE__ */ (0, import_jsx_runtime340.jsxs)("span", { className: clsx_default("stat-trend", trend.direction), children: [
5899
+ /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { "aria-hidden": "true", children: ARROW[trend.direction] }),
5900
+ trend.value
5901
+ ] })
5902
+ ] }),
5903
+ description && /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("div", { className: "stat-description", children: description })
5904
+ ] });
5905
+ };
5906
+ Stat.displayName = "Stat";
5907
+ var Stat_default = Stat;
5908
+
5909
+ // src/components/Steps/Steps.tsx
5910
+ var import_jsx_runtime341 = require("react/jsx-runtime");
5542
5911
  var Steps = (props) => {
5543
5912
  const {
5544
5913
  items,
@@ -5546,13 +5915,13 @@ var Steps = (props) => {
5546
5915
  type = "primary"
5547
5916
  } = props;
5548
5917
  const statusType = normalizeStatus(type);
5549
- return /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
5918
+ return /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
5550
5919
  const status = index < current ? "completed" : index === current ? "active" : "pending";
5551
- return /* @__PURE__ */ (0, import_jsx_runtime340.jsxs)("div", { className: clsx_default("step-item", status), children: [
5552
- /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ (0, import_jsx_runtime340.jsx)(CheckIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { children: index + 1 }) }),
5553
- /* @__PURE__ */ (0, import_jsx_runtime340.jsxs)("div", { className: "step-content", children: [
5554
- /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { className: "step-title", children: item.title }),
5555
- item.description && /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { className: "step-description", children: item.description })
5920
+ return /* @__PURE__ */ (0, import_jsx_runtime341.jsxs)("div", { className: clsx_default("step-item", status), children: [
5921
+ /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(CheckIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("span", { children: index + 1 }) }),
5922
+ /* @__PURE__ */ (0, import_jsx_runtime341.jsxs)("div", { className: "step-content", children: [
5923
+ /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("span", { className: "step-title", children: item.title }),
5924
+ item.description && /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("span", { className: "step-description", children: item.description })
5556
5925
  ] })
5557
5926
  ] }, index);
5558
5927
  }) });
@@ -5561,8 +5930,8 @@ Steps.displayName = "Steps";
5561
5930
  var Steps_default = Steps;
5562
5931
 
5563
5932
  // src/components/Swiper/Swiper.tsx
5564
- var import_react31 = __toESM(require("react"), 1);
5565
- var import_jsx_runtime341 = require("react/jsx-runtime");
5933
+ var import_react32 = __toESM(require("react"), 1);
5934
+ var import_jsx_runtime342 = require("react/jsx-runtime");
5566
5935
  var Swiper = (props) => {
5567
5936
  const {
5568
5937
  auto = false,
@@ -5586,26 +5955,26 @@ var Swiper = (props) => {
5586
5955
  const maxIndex = Math.max(0, totalSlides - viewItemCount);
5587
5956
  const useLoop = loop && canSlide;
5588
5957
  const cloneCount = useLoop ? totalSlides : 0;
5589
- const extendedItems = import_react31.default.useMemo(() => {
5958
+ const extendedItems = import_react32.default.useMemo(() => {
5590
5959
  if (!useLoop) return items;
5591
5960
  return [...items, ...items, ...items];
5592
5961
  }, [items, useLoop]);
5593
5962
  const initialIdx = Math.max(0, Math.min(indexProp ?? 0, maxIndex));
5594
- const [innerIndex, setInnerIndex] = import_react31.default.useState(
5963
+ const [innerIndex, setInnerIndex] = import_react32.default.useState(
5595
5964
  useLoop ? cloneCount + initialIdx : initialIdx
5596
5965
  );
5597
- const [isDragging, setIsDragging] = import_react31.default.useState(false);
5598
- const [dragOffset, setDragOffset] = import_react31.default.useState(0);
5599
- const [animated, setAnimated] = import_react31.default.useState(false);
5600
- const [containerWidth, setContainerWidth] = import_react31.default.useState(0);
5601
- const containerRef = import_react31.default.useRef(null);
5602
- const startXRef = import_react31.default.useRef(0);
5603
- const startTimeRef = import_react31.default.useRef(0);
5604
- const autoplayTimerRef = import_react31.default.useRef(null);
5605
- const resumeTimeoutRef = import_react31.default.useRef(null);
5606
- const [paused, setPaused] = import_react31.default.useState(false);
5607
- const initializedRef = import_react31.default.useRef(false);
5608
- import_react31.default.useEffect(() => {
5966
+ const [isDragging, setIsDragging] = import_react32.default.useState(false);
5967
+ const [dragOffset, setDragOffset] = import_react32.default.useState(0);
5968
+ const [animated, setAnimated] = import_react32.default.useState(false);
5969
+ const [containerWidth, setContainerWidth] = import_react32.default.useState(0);
5970
+ const containerRef = import_react32.default.useRef(null);
5971
+ const startXRef = import_react32.default.useRef(0);
5972
+ const startTimeRef = import_react32.default.useRef(0);
5973
+ const autoplayTimerRef = import_react32.default.useRef(null);
5974
+ const resumeTimeoutRef = import_react32.default.useRef(null);
5975
+ const [paused, setPaused] = import_react32.default.useState(false);
5976
+ const initializedRef = import_react32.default.useRef(false);
5977
+ import_react32.default.useEffect(() => {
5609
5978
  const el = containerRef.current;
5610
5979
  if (!el) return;
5611
5980
  const ro = new ResizeObserver((entries) => {
@@ -5628,7 +5997,7 @@ var Swiper = (props) => {
5628
5997
  return ((inner - cloneCount) % totalSlides + totalSlides) % totalSlides;
5629
5998
  };
5630
5999
  const realIndex = getRealIndex(innerIndex);
5631
- const moveToInner = import_react31.default.useCallback(
6000
+ const moveToInner = import_react32.default.useCallback(
5632
6001
  (idx, withAnim = true) => {
5633
6002
  if (!useLoop) {
5634
6003
  setAnimated(withAnim);
@@ -5656,7 +6025,7 @@ var Swiper = (props) => {
5656
6025
  },
5657
6026
  [useLoop, cloneCount, totalSlides]
5658
6027
  );
5659
- const handleTransitionEnd = import_react31.default.useCallback(() => {
6028
+ const handleTransitionEnd = import_react32.default.useCallback(() => {
5660
6029
  if (!useLoop) return;
5661
6030
  const real = getRealIndex(innerIndex);
5662
6031
  const canonical = cloneCount + real;
@@ -5666,7 +6035,7 @@ var Swiper = (props) => {
5666
6035
  }
5667
6036
  onChange?.(Math.min(real, maxIndex));
5668
6037
  }, [useLoop, innerIndex, cloneCount, totalSlides, maxIndex, onChange]);
5669
- const slideTo = import_react31.default.useCallback(
6038
+ const slideTo = import_react32.default.useCallback(
5670
6039
  (logicalIndex) => {
5671
6040
  if (!canSlide) return;
5672
6041
  const clamped = useLoop ? logicalIndex : Math.max(0, Math.min(logicalIndex, maxIndex));
@@ -5676,7 +6045,7 @@ var Swiper = (props) => {
5676
6045
  },
5677
6046
  [canSlide, useLoop, cloneCount, maxIndex, onChange, moveToInner]
5678
6047
  );
5679
- const slideNext = import_react31.default.useCallback(() => {
6048
+ const slideNext = import_react32.default.useCallback(() => {
5680
6049
  if (!canSlide) return;
5681
6050
  const nextInner = innerIndex + slideBy;
5682
6051
  if (useLoop) {
@@ -5685,7 +6054,7 @@ var Swiper = (props) => {
5685
6054
  moveToInner(Math.min(nextInner, maxIndex), true);
5686
6055
  }
5687
6056
  }, [canSlide, useLoop, innerIndex, slideBy, maxIndex, moveToInner]);
5688
- const slidePrev = import_react31.default.useCallback(() => {
6057
+ const slidePrev = import_react32.default.useCallback(() => {
5689
6058
  if (!canSlide) return;
5690
6059
  const prevInner = innerIndex - slideBy;
5691
6060
  if (useLoop) {
@@ -5694,7 +6063,7 @@ var Swiper = (props) => {
5694
6063
  moveToInner(Math.max(prevInner, 0), true);
5695
6064
  }
5696
6065
  }, [canSlide, useLoop, innerIndex, slideBy, moveToInner]);
5697
- import_react31.default.useEffect(() => {
6066
+ import_react32.default.useEffect(() => {
5698
6067
  if (indexProp === void 0) return;
5699
6068
  const clamped = Math.max(0, Math.min(indexProp, maxIndex));
5700
6069
  const target = useLoop ? cloneCount + clamped : clamped;
@@ -5702,12 +6071,12 @@ var Swiper = (props) => {
5702
6071
  moveToInner(target, true);
5703
6072
  }
5704
6073
  }, [indexProp]);
5705
- import_react31.default.useImperativeHandle(swiperRef, () => ({
6074
+ import_react32.default.useImperativeHandle(swiperRef, () => ({
5706
6075
  slidePrev,
5707
6076
  slideNext,
5708
6077
  slideTo
5709
6078
  }));
5710
- import_react31.default.useEffect(() => {
6079
+ import_react32.default.useEffect(() => {
5711
6080
  if (!auto || !canSlide || paused) return;
5712
6081
  autoplayTimerRef.current = setInterval(slideNext, autoplayDelay);
5713
6082
  return () => {
@@ -5733,7 +6102,7 @@ var Swiper = (props) => {
5733
6102
  resumeTimeoutRef.current = null;
5734
6103
  }, pauseOnInteraction);
5735
6104
  };
5736
- import_react31.default.useEffect(() => {
6105
+ import_react32.default.useEffect(() => {
5737
6106
  return () => {
5738
6107
  if (resumeTimeoutRef.current) clearTimeout(resumeTimeoutRef.current);
5739
6108
  };
@@ -5751,7 +6120,7 @@ var Swiper = (props) => {
5751
6120
  startXRef.current = getClientX(e);
5752
6121
  startTimeRef.current = Date.now();
5753
6122
  };
5754
- import_react31.default.useEffect(() => {
6123
+ import_react32.default.useEffect(() => {
5755
6124
  if (!isDragging) return;
5756
6125
  const handleMove = (e) => {
5757
6126
  setDragOffset(getClientX(e) - startXRef.current);
@@ -5790,8 +6159,8 @@ var Swiper = (props) => {
5790
6159
  }, [isDragging, dragOffset, innerIndex, useLoop, maxIndex, slideStep, moveToInner]);
5791
6160
  const slideWidthPercent = 100 / viewItemCount;
5792
6161
  const gapAdjust = spaceBetween * (viewItemCount - 1) / viewItemCount;
5793
- const slideElements = import_react31.default.useMemo(
5794
- () => extendedItems.map((item, idx) => /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(
6162
+ const slideElements = import_react32.default.useMemo(
6163
+ () => extendedItems.map((item, idx) => /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
5795
6164
  "div",
5796
6165
  {
5797
6166
  className: "lib-xplat-swiper__slide",
@@ -5810,15 +6179,15 @@ var Swiper = (props) => {
5810
6179
  Math.floor(realIndex / slideBy),
5811
6180
  totalSteps - 1
5812
6181
  );
5813
- return /* @__PURE__ */ (0, import_jsx_runtime341.jsxs)("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
5814
- /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(
6182
+ return /* @__PURE__ */ (0, import_jsx_runtime342.jsxs)("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
6183
+ /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
5815
6184
  "div",
5816
6185
  {
5817
6186
  className: "lib-xplat-swiper__viewport",
5818
6187
  onMouseDown: handleDragStart,
5819
6188
  onTouchStart: handleDragStart,
5820
6189
  onDragStart: (e) => e.preventDefault(),
5821
- children: /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(
6190
+ children: /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
5822
6191
  "div",
5823
6192
  {
5824
6193
  className: clsx_default(
@@ -5836,7 +6205,7 @@ var Swiper = (props) => {
5836
6205
  )
5837
6206
  }
5838
6207
  ),
5839
- showProgress && canSlide && /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(
6208
+ showProgress && canSlide && /* @__PURE__ */ (0, import_jsx_runtime342.jsx)("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ (0, import_jsx_runtime342.jsx)("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
5840
6209
  "span",
5841
6210
  {
5842
6211
  className: "lib-xplat-swiper__progress-fill",
@@ -5846,7 +6215,7 @@ var Swiper = (props) => {
5846
6215
  }
5847
6216
  }
5848
6217
  ) }) }),
5849
- canSlide && /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(
6218
+ canSlide && /* @__PURE__ */ (0, import_jsx_runtime342.jsx)("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
5850
6219
  "button",
5851
6220
  {
5852
6221
  className: clsx_default(
@@ -5864,8 +6233,8 @@ Swiper.displayName = "Swiper";
5864
6233
  var Swiper_default = Swiper;
5865
6234
 
5866
6235
  // src/components/Switch/Switch.tsx
5867
- var import_react32 = __toESM(require("react"), 1);
5868
- var import_jsx_runtime342 = require("react/jsx-runtime");
6236
+ var import_react33 = __toESM(require("react"), 1);
6237
+ var import_jsx_runtime343 = require("react/jsx-runtime");
5869
6238
  var KNOB_TRANSITION_MS = 250;
5870
6239
  var Switch = (props) => {
5871
6240
  const {
@@ -5874,12 +6243,15 @@ var Switch = (props) => {
5874
6243
  type = "primary",
5875
6244
  disabled,
5876
6245
  onChange,
5877
- validations
6246
+ validations,
6247
+ label,
6248
+ required
5878
6249
  } = props;
6250
+ const fieldId = import_react33.default.useId();
5879
6251
  const statusType = normalizeStatus(type);
5880
- const [isAnimating, setIsAnimating] = import_react32.default.useState(false);
5881
- const timeoutRef = import_react32.default.useRef(null);
5882
- import_react32.default.useEffect(() => {
6252
+ const [isAnimating, setIsAnimating] = import_react33.default.useState(false);
6253
+ const timeoutRef = import_react33.default.useRef(null);
6254
+ import_react33.default.useEffect(() => {
5883
6255
  return () => {
5884
6256
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5885
6257
  };
@@ -5894,9 +6266,10 @@ var Switch = (props) => {
5894
6266
  timeoutRef.current = null;
5895
6267
  }, KNOB_TRANSITION_MS);
5896
6268
  };
5897
- const control = /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
6269
+ const control = /* @__PURE__ */ (0, import_jsx_runtime343.jsx)(
5898
6270
  "div",
5899
6271
  {
6272
+ id: fieldId,
5900
6273
  className: clsx_default(
5901
6274
  "lib-xplat-switch",
5902
6275
  size,
@@ -5908,26 +6281,26 @@ var Switch = (props) => {
5908
6281
  onClick: handleClick,
5909
6282
  "aria-invalid": hasError(validations) || void 0,
5910
6283
  "aria-disabled": disabled || isAnimating,
5911
- children: /* @__PURE__ */ (0, import_jsx_runtime342.jsx)("div", { className: clsx_default("knob", value ? "checked" : void 0) })
6284
+ children: /* @__PURE__ */ (0, import_jsx_runtime343.jsx)("div", { className: clsx_default("knob", value ? "checked" : void 0) })
5912
6285
  }
5913
6286
  );
5914
- return /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(Field, { validations, children: control });
6287
+ return /* @__PURE__ */ (0, import_jsx_runtime343.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
5915
6288
  };
5916
6289
  Switch.displayName = "Switch";
5917
6290
  var Switch_default = Switch;
5918
6291
 
5919
6292
  // src/components/Table/TableContext.tsx
5920
- var import_react33 = __toESM(require("react"), 1);
5921
- var TableContext = import_react33.default.createContext(null);
6293
+ var import_react34 = __toESM(require("react"), 1);
6294
+ var TableContext = import_react34.default.createContext(null);
5922
6295
  var useTableContext = () => {
5923
- const ctx = import_react33.default.useContext(TableContext);
6296
+ const ctx = import_react34.default.useContext(TableContext);
5924
6297
  if (!ctx) throw new Error("Table components must be used inside <Table>");
5925
6298
  return ctx;
5926
6299
  };
5927
6300
  var TableContext_default = TableContext;
5928
6301
 
5929
6302
  // src/components/Table/Table.tsx
5930
- var import_jsx_runtime343 = require("react/jsx-runtime");
6303
+ var import_jsx_runtime344 = require("react/jsx-runtime");
5931
6304
  var Table = (props) => {
5932
6305
  const {
5933
6306
  children,
@@ -5937,7 +6310,7 @@ var Table = (props) => {
5937
6310
  headerSticky = false,
5938
6311
  stickyShadow = true
5939
6312
  } = props;
5940
- return /* @__PURE__ */ (0, import_jsx_runtime343.jsx)("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ (0, import_jsx_runtime343.jsx)(
6313
+ return /* @__PURE__ */ (0, import_jsx_runtime344.jsx)("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ (0, import_jsx_runtime344.jsx)(
5941
6314
  TableContext_default.Provider,
5942
6315
  {
5943
6316
  value: {
@@ -5946,7 +6319,7 @@ var Table = (props) => {
5946
6319
  headerSticky,
5947
6320
  stickyShadow
5948
6321
  },
5949
- children: /* @__PURE__ */ (0, import_jsx_runtime343.jsx)("table", { className: "lib-xplat-table", children })
6322
+ children: /* @__PURE__ */ (0, import_jsx_runtime344.jsx)("table", { className: "lib-xplat-table", children })
5950
6323
  }
5951
6324
  ) });
5952
6325
  };
@@ -5954,41 +6327,41 @@ Table.displayName = "Table";
5954
6327
  var Table_default = Table;
5955
6328
 
5956
6329
  // src/components/Table/TableBody.tsx
5957
- var import_jsx_runtime344 = require("react/jsx-runtime");
6330
+ var import_jsx_runtime345 = require("react/jsx-runtime");
5958
6331
  var TableBody = (props) => {
5959
6332
  const { children } = props;
5960
- return /* @__PURE__ */ (0, import_jsx_runtime344.jsx)("tbody", { children });
6333
+ return /* @__PURE__ */ (0, import_jsx_runtime345.jsx)("tbody", { children });
5961
6334
  };
5962
6335
  TableBody.displayName = "TableBody";
5963
6336
  var TableBody_default = TableBody;
5964
6337
 
5965
6338
  // src/components/Table/TableCell.tsx
5966
- var import_react36 = __toESM(require("react"), 1);
6339
+ var import_react37 = __toESM(require("react"), 1);
5967
6340
 
5968
6341
  // src/components/Table/TableHeadContext.tsx
5969
- var import_react34 = __toESM(require("react"), 1);
5970
- var TableHeadContext = import_react34.default.createContext(
6342
+ var import_react35 = __toESM(require("react"), 1);
6343
+ var TableHeadContext = import_react35.default.createContext(
5971
6344
  null
5972
6345
  );
5973
6346
  var useTableHeadContext = () => {
5974
- const ctx = import_react34.default.useContext(TableHeadContext);
6347
+ const ctx = import_react35.default.useContext(TableHeadContext);
5975
6348
  return ctx;
5976
6349
  };
5977
6350
  var TableHeadContext_default = TableHeadContext;
5978
6351
 
5979
6352
  // src/components/Table/TableRowContext.tsx
5980
- var import_react35 = __toESM(require("react"), 1);
5981
- var TableRowContext = import_react35.default.createContext(null);
6353
+ var import_react36 = __toESM(require("react"), 1);
6354
+ var TableRowContext = import_react36.default.createContext(null);
5982
6355
  var useTableRowContext = () => {
5983
- const ctx = import_react35.default.useContext(TableRowContext);
6356
+ const ctx = import_react36.default.useContext(TableRowContext);
5984
6357
  if (!ctx) throw new Error("Table components must be used inside <Table>");
5985
6358
  return ctx;
5986
6359
  };
5987
6360
  var TableRowContext_default = TableRowContext;
5988
6361
 
5989
6362
  // src/components/Table/TableCell.tsx
5990
- var import_jsx_runtime345 = require("react/jsx-runtime");
5991
- var TableCell = import_react36.default.memo((props) => {
6363
+ var import_jsx_runtime346 = require("react/jsx-runtime");
6364
+ var TableCell = import_react37.default.memo((props) => {
5992
6365
  const {
5993
6366
  children,
5994
6367
  align = "center",
@@ -6002,9 +6375,9 @@ var TableCell = import_react36.default.memo((props) => {
6002
6375
  const { registerStickyCell, stickyCells } = useTableRowContext();
6003
6376
  const { stickyShadow } = useTableContext();
6004
6377
  const headContext = useTableHeadContext();
6005
- const [left, setLeft] = import_react36.default.useState(0);
6006
- const cellRef = import_react36.default.useRef(null);
6007
- const calculateLeft = import_react36.default.useCallback(() => {
6378
+ const [left, setLeft] = import_react37.default.useState(0);
6379
+ const cellRef = import_react37.default.useRef(null);
6380
+ const calculateLeft = import_react37.default.useCallback(() => {
6008
6381
  if (!cellRef.current) return 0;
6009
6382
  let totalLeft = 0;
6010
6383
  for (const ref of stickyCells) {
@@ -6013,7 +6386,7 @@ var TableCell = import_react36.default.memo((props) => {
6013
6386
  }
6014
6387
  return totalLeft;
6015
6388
  }, [stickyCells]);
6016
- import_react36.default.useEffect(() => {
6389
+ import_react37.default.useEffect(() => {
6017
6390
  if (!isSticky || !cellRef.current) return;
6018
6391
  registerStickyCell(cellRef);
6019
6392
  setLeft(calculateLeft());
@@ -6032,7 +6405,7 @@ var TableCell = import_react36.default.memo((props) => {
6032
6405
  const CellTag = isHeaderCell ? "th" : "td";
6033
6406
  const isLastSticky = isSticky && stickyCells[stickyCells.length - 1] === cellRef;
6034
6407
  const enableHover = headContext && headContext.cellHover;
6035
- return /* @__PURE__ */ (0, import_jsx_runtime345.jsx)(
6408
+ return /* @__PURE__ */ (0, import_jsx_runtime346.jsx)(
6036
6409
  CellTag,
6037
6410
  {
6038
6411
  ref: cellRef,
@@ -6059,21 +6432,21 @@ TableCell.displayName = "TableCell";
6059
6432
  var TableCell_default = TableCell;
6060
6433
 
6061
6434
  // src/components/Table/TableHead.tsx
6062
- var import_jsx_runtime346 = require("react/jsx-runtime");
6435
+ var import_jsx_runtime347 = require("react/jsx-runtime");
6063
6436
  var TableHead = ({
6064
6437
  children,
6065
6438
  cellHover = false
6066
6439
  }) => {
6067
6440
  const { headerSticky } = useTableContext();
6068
- return /* @__PURE__ */ (0, import_jsx_runtime346.jsx)(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ (0, import_jsx_runtime346.jsx)("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
6441
+ return /* @__PURE__ */ (0, import_jsx_runtime347.jsx)(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ (0, import_jsx_runtime347.jsx)("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
6069
6442
  };
6070
6443
  TableHead.displayName = "TableHead";
6071
6444
  var TableHead_default = TableHead;
6072
6445
 
6073
6446
  // src/components/Table/TableRow.tsx
6074
- var import_react37 = __toESM(require("react"), 1);
6075
- var import_jsx_runtime347 = require("react/jsx-runtime");
6076
- var TableRow = import_react37.default.memo((props) => {
6447
+ var import_react38 = __toESM(require("react"), 1);
6448
+ var import_jsx_runtime348 = require("react/jsx-runtime");
6449
+ var TableRow = import_react38.default.memo((props) => {
6077
6450
  const {
6078
6451
  children,
6079
6452
  type = "secondary",
@@ -6082,14 +6455,14 @@ var TableRow = import_react37.default.memo((props) => {
6082
6455
  onClick
6083
6456
  } = props;
6084
6457
  const { rowBorderUse } = useTableContext();
6085
- const [stickyCells, setStickyCells] = import_react37.default.useState([]);
6458
+ const [stickyCells, setStickyCells] = import_react38.default.useState([]);
6086
6459
  const registerStickyCell = (ref) => {
6087
6460
  setStickyCells((prev) => {
6088
6461
  if (prev.includes(ref)) return prev;
6089
6462
  return [...prev, ref];
6090
6463
  });
6091
6464
  };
6092
- return /* @__PURE__ */ (0, import_jsx_runtime347.jsx)(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ (0, import_jsx_runtime347.jsx)(
6465
+ return /* @__PURE__ */ (0, import_jsx_runtime348.jsx)(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ (0, import_jsx_runtime348.jsx)(
6093
6466
  "tr",
6094
6467
  {
6095
6468
  className: clsx_default(
@@ -6113,7 +6486,7 @@ TableRow.displayName = "TableRow";
6113
6486
  var TableRow_default = TableRow;
6114
6487
 
6115
6488
  // src/components/Tag/Tag.tsx
6116
- var import_jsx_runtime348 = require("react/jsx-runtime");
6489
+ var import_jsx_runtime349 = require("react/jsx-runtime");
6117
6490
  var Tag = (props) => {
6118
6491
  const {
6119
6492
  children,
@@ -6125,7 +6498,7 @@ var Tag = (props) => {
6125
6498
  colorIndex
6126
6499
  } = props;
6127
6500
  const shape = variant ?? type ?? "neutral";
6128
- return /* @__PURE__ */ (0, import_jsx_runtime348.jsxs)(
6501
+ return /* @__PURE__ */ (0, import_jsx_runtime349.jsxs)(
6129
6502
  "span",
6130
6503
  {
6131
6504
  className: clsx_default(
@@ -6136,8 +6509,8 @@ var Tag = (props) => {
6136
6509
  disabled && "disabled"
6137
6510
  ),
6138
6511
  children: [
6139
- /* @__PURE__ */ (0, import_jsx_runtime348.jsx)("span", { className: "tag-label", children }),
6140
- onClose && /* @__PURE__ */ (0, import_jsx_runtime348.jsx)("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ (0, import_jsx_runtime348.jsx)(XIcon_default, {}) })
6512
+ /* @__PURE__ */ (0, import_jsx_runtime349.jsx)("span", { className: "tag-label", children }),
6513
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime349.jsx)("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ (0, import_jsx_runtime349.jsx)(XIcon_default, {}) })
6141
6514
  ]
6142
6515
  }
6143
6516
  );
@@ -6146,24 +6519,29 @@ Tag.displayName = "Tag";
6146
6519
  var Tag_default = Tag;
6147
6520
 
6148
6521
  // src/components/TextArea/TextArea.tsx
6149
- var import_react38 = __toESM(require("react"), 1);
6150
- var import_jsx_runtime349 = require("react/jsx-runtime");
6151
- var TextArea = import_react38.default.forwardRef(
6522
+ var import_react39 = __toESM(require("react"), 1);
6523
+ var import_jsx_runtime350 = require("react/jsx-runtime");
6524
+ var TextArea = import_react39.default.forwardRef(
6152
6525
  (props, ref) => {
6153
6526
  const {
6154
6527
  className,
6155
6528
  size = "md",
6156
6529
  validations,
6530
+ label,
6531
+ required,
6157
6532
  resize = "vertical",
6158
6533
  rows = 3,
6159
6534
  disabled,
6160
6535
  ...textareaProps
6161
6536
  } = props;
6162
- const control = /* @__PURE__ */ (0, import_jsx_runtime349.jsx)("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ (0, import_jsx_runtime349.jsx)(
6537
+ const autoId = import_react39.default.useId();
6538
+ const fieldId = props.id ?? autoId;
6539
+ const control = /* @__PURE__ */ (0, import_jsx_runtime350.jsx)("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ (0, import_jsx_runtime350.jsx)(
6163
6540
  "textarea",
6164
6541
  {
6165
6542
  ...textareaProps,
6166
6543
  ref,
6544
+ id: fieldId,
6167
6545
  rows,
6168
6546
  disabled,
6169
6547
  "aria-invalid": hasError(validations) || void 0,
@@ -6171,32 +6549,166 @@ var TextArea = import_react38.default.forwardRef(
6171
6549
  style: { resize }
6172
6550
  }
6173
6551
  ) });
6174
- return /* @__PURE__ */ (0, import_jsx_runtime349.jsx)(Field, { validations, children: control });
6552
+ return /* @__PURE__ */ (0, import_jsx_runtime350.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
6175
6553
  }
6176
6554
  );
6177
6555
  TextArea.displayName = "TextArea";
6178
6556
  var TextArea_default = TextArea;
6179
6557
 
6558
+ // src/components/TimePicker/TimePicker.tsx
6559
+ var import_react40 = __toESM(require("react"), 1);
6560
+ var import_jsx_runtime351 = require("react/jsx-runtime");
6561
+ var ANIMATION_DURATION_MS4 = 200;
6562
+ var toMinutes = (hhmm) => {
6563
+ if (!hhmm) return null;
6564
+ const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
6565
+ if (!m) return null;
6566
+ const h = Number(m[1]);
6567
+ const min = Number(m[2]);
6568
+ if (h > 23 || min > 59) return null;
6569
+ return h * 60 + min;
6570
+ };
6571
+ var toHHmm = (minutes) => `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
6572
+ var display = (hhmm, use12Hours) => {
6573
+ if (!use12Hours) return hhmm;
6574
+ const total = toMinutes(hhmm);
6575
+ if (total === null) return hhmm;
6576
+ const h24 = Math.floor(total / 60);
6577
+ const mm = String(total % 60).padStart(2, "0");
6578
+ const period = h24 < 12 ? "\uC624\uC804" : "\uC624\uD6C4";
6579
+ const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
6580
+ return `${period} ${h12}:${mm}`;
6581
+ };
6582
+ var TimePicker = (props) => {
6583
+ const {
6584
+ value,
6585
+ onChange,
6586
+ step = 30,
6587
+ min,
6588
+ max,
6589
+ use12Hours = false,
6590
+ placeholder = "\uC2DC\uAC01 \uC120\uD0DD",
6591
+ disabled = false,
6592
+ size = "md",
6593
+ label,
6594
+ required,
6595
+ validations
6596
+ } = props;
6597
+ const fieldId = import_react40.default.useId();
6598
+ const triggerRef = import_react40.default.useRef(null);
6599
+ const contentRef = import_react40.default.useRef(null);
6600
+ const [isOpen, setOpen] = import_react40.default.useState(false);
6601
+ const [mounted, setMounted] = import_react40.default.useState(false);
6602
+ const [visible, setVisible] = import_react40.default.useState(false);
6603
+ const options = import_react40.default.useMemo(() => {
6604
+ const safeStep = step > 0 && step <= 720 ? step : 30;
6605
+ const lo = toMinutes(min) ?? 0;
6606
+ const hi = toMinutes(max) ?? 24 * 60 - 1;
6607
+ const out = [];
6608
+ for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
6609
+ return out;
6610
+ }, [step, min, max]);
6611
+ const close = import_react40.default.useCallback(() => setOpen(false), []);
6612
+ useClickOutside_default([triggerRef, contentRef], close, isOpen);
6613
+ useEscapeKey(isOpen, () => {
6614
+ close();
6615
+ triggerRef.current?.focus({ preventScroll: true });
6616
+ });
6617
+ const position = useAutoPosition_default(triggerRef, contentRef, mounted);
6618
+ import_react40.default.useEffect(() => {
6619
+ if (disabled && isOpen) setOpen(false);
6620
+ }, [disabled, isOpen]);
6621
+ import_react40.default.useEffect(() => {
6622
+ if (isOpen) {
6623
+ setMounted(true);
6624
+ const t2 = setTimeout(() => setVisible(true), 1);
6625
+ return () => clearTimeout(t2);
6626
+ }
6627
+ setVisible(false);
6628
+ const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS4);
6629
+ return () => clearTimeout(t);
6630
+ }, [isOpen]);
6631
+ const pick = (hhmm) => {
6632
+ onChange?.(hhmm);
6633
+ close();
6634
+ triggerRef.current?.focus({ preventScroll: true });
6635
+ };
6636
+ const control = /* @__PURE__ */ (0, import_jsx_runtime351.jsxs)("div", { className: clsx_default("lib-xplat-time-picker", size, disabled && "disabled"), children: [
6637
+ /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(
6638
+ "div",
6639
+ {
6640
+ id: fieldId,
6641
+ ref: triggerRef,
6642
+ className: clsx_default("time-picker-trigger", hasError(validations) && "error"),
6643
+ role: "combobox",
6644
+ "aria-expanded": isOpen,
6645
+ "aria-haspopup": "listbox",
6646
+ "aria-invalid": hasError(validations) || void 0,
6647
+ tabIndex: disabled ? void 0 : 0,
6648
+ onClick: () => !disabled && setOpen((p) => !p),
6649
+ onKeyDown: (e) => {
6650
+ if (disabled) return;
6651
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
6652
+ e.preventDefault();
6653
+ setOpen(true);
6654
+ }
6655
+ },
6656
+ children: /* @__PURE__ */ (0, import_jsx_runtime351.jsx)("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
6657
+ }
6658
+ ),
6659
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(
6660
+ "div",
6661
+ {
6662
+ ref: contentRef,
6663
+ className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit"),
6664
+ style: { ...position.position, width: triggerRef.current?.offsetWidth },
6665
+ role: "listbox",
6666
+ children: options.map((t) => /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(
6667
+ "div",
6668
+ {
6669
+ className: clsx_default("time-picker-item", t === value && "is-selected"),
6670
+ role: "option",
6671
+ "aria-selected": t === value,
6672
+ tabIndex: 0,
6673
+ onClick: () => pick(t),
6674
+ onKeyDown: (e) => {
6675
+ if (e.key === "Enter" || e.key === " ") {
6676
+ e.preventDefault();
6677
+ pick(t);
6678
+ }
6679
+ },
6680
+ children: display(t, use12Hours)
6681
+ },
6682
+ t
6683
+ ))
6684
+ }
6685
+ ) })
6686
+ ] });
6687
+ return /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
6688
+ };
6689
+ TimePicker.displayName = "TimePicker";
6690
+ var TimePicker_default = TimePicker;
6691
+
6180
6692
  // src/components/Toast/Toast.tsx
6181
- var import_react39 = __toESM(require("react"), 1);
6693
+ var import_react41 = __toESM(require("react"), 1);
6182
6694
  var import_react_dom4 = require("react-dom");
6183
- var import_jsx_runtime350 = require("react/jsx-runtime");
6184
- var ToastContext = import_react39.default.createContext(null);
6695
+ var import_jsx_runtime352 = require("react/jsx-runtime");
6696
+ var ToastContext = import_react41.default.createContext(null);
6185
6697
  var useToast = () => {
6186
- const ctx = import_react39.default.useContext(ToastContext);
6698
+ const ctx = import_react41.default.useContext(ToastContext);
6187
6699
  if (!ctx) throw new Error("useToast must be used within ToastProvider");
6188
6700
  return ctx;
6189
6701
  };
6190
6702
  var EXIT_DURATION = 300;
6191
6703
  var ToastItemComponent = ({ item, isExiting, onClose }) => {
6192
- const ref = import_react39.default.useRef(null);
6193
- const [height, setHeight] = import_react39.default.useState(void 0);
6194
- import_react39.default.useEffect(() => {
6704
+ const ref = import_react41.default.useRef(null);
6705
+ const [height, setHeight] = import_react41.default.useState(void 0);
6706
+ import_react41.default.useEffect(() => {
6195
6707
  if (ref.current && !isExiting) {
6196
6708
  setHeight(ref.current.offsetHeight);
6197
6709
  }
6198
6710
  }, [isExiting]);
6199
- return /* @__PURE__ */ (0, import_jsx_runtime350.jsx)(
6711
+ return /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
6200
6712
  "div",
6201
6713
  {
6202
6714
  className: clsx_default("lib-xplat-toast-wrapper", { exit: isExiting }),
@@ -6204,15 +6716,15 @@ var ToastItemComponent = ({ item, isExiting, onClose }) => {
6204
6716
  maxHeight: isExiting ? 0 : height ?? "none",
6205
6717
  marginBottom: isExiting ? 0 : void 0
6206
6718
  },
6207
- children: /* @__PURE__ */ (0, import_jsx_runtime350.jsxs)(
6719
+ children: /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)(
6208
6720
  "div",
6209
6721
  {
6210
6722
  ref,
6211
6723
  className: clsx_default("lib-xplat-toast", item.type, { exit: isExiting }),
6212
6724
  role: "alert",
6213
6725
  children: [
6214
- /* @__PURE__ */ (0, import_jsx_runtime350.jsx)("span", { className: "message", children: item.message }),
6215
- /* @__PURE__ */ (0, import_jsx_runtime350.jsx)("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
6726
+ /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("span", { className: "message", children: item.message }),
6727
+ /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
6216
6728
  ]
6217
6729
  }
6218
6730
  )
@@ -6223,13 +6735,13 @@ var ToastProvider = ({
6223
6735
  children,
6224
6736
  position = "top-right"
6225
6737
  }) => {
6226
- const [toasts, setToasts] = import_react39.default.useState([]);
6227
- const [removing, setRemoving] = import_react39.default.useState(/* @__PURE__ */ new Set());
6228
- const [mounted, setMounted] = import_react39.default.useState(false);
6229
- import_react39.default.useEffect(() => {
6738
+ const [toasts, setToasts] = import_react41.default.useState([]);
6739
+ const [removing, setRemoving] = import_react41.default.useState(/* @__PURE__ */ new Set());
6740
+ const [mounted, setMounted] = import_react41.default.useState(false);
6741
+ import_react41.default.useEffect(() => {
6230
6742
  setMounted(true);
6231
6743
  }, []);
6232
- const remove = import_react39.default.useCallback((id) => {
6744
+ const remove = import_react41.default.useCallback((id) => {
6233
6745
  setRemoving((prev) => new Set(prev).add(id));
6234
6746
  setTimeout(() => {
6235
6747
  setToasts((prev) => prev.filter((t) => t.id !== id));
@@ -6240,7 +6752,7 @@ var ToastProvider = ({
6240
6752
  });
6241
6753
  }, EXIT_DURATION);
6242
6754
  }, []);
6243
- const toast = import_react39.default.useCallback(
6755
+ const toast = import_react41.default.useCallback(
6244
6756
  (type, message, duration = 3e3) => {
6245
6757
  const id = `${Date.now()}-${Math.random()}`;
6246
6758
  setToasts((prev) => [...prev, { id, type, message }]);
@@ -6250,10 +6762,10 @@ var ToastProvider = ({
6250
6762
  },
6251
6763
  [remove]
6252
6764
  );
6253
- return /* @__PURE__ */ (0, import_jsx_runtime350.jsxs)(ToastContext.Provider, { value: { toast }, children: [
6765
+ return /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)(ToastContext.Provider, { value: { toast }, children: [
6254
6766
  children,
6255
6767
  mounted && (0, import_react_dom4.createPortal)(
6256
- /* @__PURE__ */ (0, import_jsx_runtime350.jsx)("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime350.jsx)(
6768
+ /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
6257
6769
  ToastItemComponent,
6258
6770
  {
6259
6771
  item: t,
@@ -6269,8 +6781,8 @@ var ToastProvider = ({
6269
6781
  ToastProvider.displayName = "ToastProvider";
6270
6782
 
6271
6783
  // src/components/Tooltip/Tooltip.tsx
6272
- var import_react40 = __toESM(require("react"), 1);
6273
- var import_jsx_runtime351 = require("react/jsx-runtime");
6784
+ var import_react42 = __toESM(require("react"), 1);
6785
+ var import_jsx_runtime353 = require("react/jsx-runtime");
6274
6786
  var OFFSET = 12;
6275
6787
  var GAP = 8;
6276
6788
  var SHOW_DELAY = 300;
@@ -6285,14 +6797,14 @@ var Tooltip = (props) => {
6285
6797
  disabled = false
6286
6798
  } = props;
6287
6799
  const shape = variant ?? type ?? "dark";
6288
- const triggerRef = import_react40.default.useRef(null);
6289
- const tooltipRef = import_react40.default.useRef(null);
6290
- const [visible, setVisible] = import_react40.default.useState(false);
6291
- const [pos, setPos] = import_react40.default.useState({ left: 0, top: 0 });
6292
- const delayTimer = import_react40.default.useRef(0);
6293
- const rafRef = import_react40.default.useRef(0);
6294
- const cursor = import_react40.default.useRef(null);
6295
- const clamp = import_react40.default.useCallback((left, top, w, h) => {
6800
+ const triggerRef = import_react42.default.useRef(null);
6801
+ const tooltipRef = import_react42.default.useRef(null);
6802
+ const [visible, setVisible] = import_react42.default.useState(false);
6803
+ const [pos, setPos] = import_react42.default.useState({ left: 0, top: 0 });
6804
+ const delayTimer = import_react42.default.useRef(0);
6805
+ const rafRef = import_react42.default.useRef(0);
6806
+ const cursor = import_react42.default.useRef(null);
6807
+ const clamp = import_react42.default.useCallback((left, top, w, h) => {
6296
6808
  const vw = window.innerWidth;
6297
6809
  const vh = window.innerHeight;
6298
6810
  return {
@@ -6300,7 +6812,7 @@ var Tooltip = (props) => {
6300
6812
  top: Math.min(Math.max(GAP, top), Math.max(GAP, vh - h - GAP))
6301
6813
  };
6302
6814
  }, []);
6303
- const placeAtCursor = import_react40.default.useCallback((x, y) => {
6815
+ const placeAtCursor = import_react42.default.useCallback((x, y) => {
6304
6816
  const el = tooltipRef.current;
6305
6817
  if (!el) return;
6306
6818
  const w = el.offsetWidth;
@@ -6311,7 +6823,7 @@ var Tooltip = (props) => {
6311
6823
  if (top < GAP) top = y + OFFSET;
6312
6824
  setPos(clamp(left, top, w, h));
6313
6825
  }, [clamp]);
6314
- const placeAtTrigger = import_react40.default.useCallback(() => {
6826
+ const placeAtTrigger = import_react42.default.useCallback(() => {
6315
6827
  const el = tooltipRef.current;
6316
6828
  const trigger = triggerRef.current;
6317
6829
  if (!el || !trigger) return;
@@ -6323,19 +6835,19 @@ var Tooltip = (props) => {
6323
6835
  const left = rect.left + rect.width / 2 - w / 2;
6324
6836
  setPos(clamp(left, top, w, h));
6325
6837
  }, [clamp]);
6326
- const reposition = import_react40.default.useCallback(() => {
6838
+ const reposition = import_react42.default.useCallback(() => {
6327
6839
  if (follow && cursor.current) {
6328
6840
  placeAtCursor(cursor.current.x, cursor.current.y);
6329
6841
  } else {
6330
6842
  placeAtTrigger();
6331
6843
  }
6332
6844
  }, [follow, placeAtCursor, placeAtTrigger]);
6333
- const handleMouseEnter = import_react40.default.useCallback((e) => {
6845
+ const handleMouseEnter = import_react42.default.useCallback((e) => {
6334
6846
  if (disabled) return;
6335
6847
  cursor.current = { x: e.clientX, y: e.clientY };
6336
6848
  delayTimer.current = window.setTimeout(() => setVisible(true), SHOW_DELAY);
6337
6849
  }, [disabled]);
6338
- const handleMouseMove = import_react40.default.useCallback((e) => {
6850
+ const handleMouseMove = import_react42.default.useCallback((e) => {
6339
6851
  cursor.current = { x: e.clientX, y: e.clientY };
6340
6852
  if (!visible || !follow) return;
6341
6853
  cancelAnimationFrame(rafRef.current);
@@ -6343,25 +6855,25 @@ var Tooltip = (props) => {
6343
6855
  if (cursor.current) placeAtCursor(cursor.current.x, cursor.current.y);
6344
6856
  });
6345
6857
  }, [visible, follow, placeAtCursor]);
6346
- const close = import_react40.default.useCallback(() => {
6858
+ const close = import_react42.default.useCallback(() => {
6347
6859
  window.clearTimeout(delayTimer.current);
6348
6860
  cancelAnimationFrame(rafRef.current);
6349
6861
  setVisible(false);
6350
6862
  }, []);
6351
- const handleMouseLeave = import_react40.default.useCallback(() => {
6863
+ const handleMouseLeave = import_react42.default.useCallback(() => {
6352
6864
  cursor.current = null;
6353
6865
  close();
6354
6866
  }, [close]);
6355
- const handleFocus = import_react40.default.useCallback(() => {
6867
+ const handleFocus = import_react42.default.useCallback(() => {
6356
6868
  if (disabled) return;
6357
6869
  cursor.current = null;
6358
6870
  setVisible(true);
6359
6871
  }, [disabled]);
6360
- import_react40.default.useLayoutEffect(() => {
6872
+ import_react42.default.useLayoutEffect(() => {
6361
6873
  if (!visible) return;
6362
6874
  reposition();
6363
6875
  }, [visible, reposition]);
6364
- import_react40.default.useEffect(() => {
6876
+ import_react42.default.useEffect(() => {
6365
6877
  if (!visible || follow) return;
6366
6878
  const onChange = () => placeAtTrigger();
6367
6879
  window.addEventListener("scroll", onChange, true);
@@ -6371,12 +6883,12 @@ var Tooltip = (props) => {
6371
6883
  window.removeEventListener("resize", onChange);
6372
6884
  };
6373
6885
  }, [visible, follow, placeAtTrigger]);
6374
- import_react40.default.useEffect(() => () => {
6886
+ import_react42.default.useEffect(() => () => {
6375
6887
  window.clearTimeout(delayTimer.current);
6376
6888
  cancelAnimationFrame(rafRef.current);
6377
6889
  }, []);
6378
- if (!title && !description) return /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(import_jsx_runtime351.Fragment, { children });
6379
- return /* @__PURE__ */ (0, import_jsx_runtime351.jsxs)(
6890
+ if (!title && !description) return /* @__PURE__ */ (0, import_jsx_runtime353.jsx)(import_jsx_runtime353.Fragment, { children });
6891
+ return /* @__PURE__ */ (0, import_jsx_runtime353.jsxs)(
6380
6892
  "div",
6381
6893
  {
6382
6894
  ref: triggerRef,
@@ -6389,7 +6901,7 @@ var Tooltip = (props) => {
6389
6901
  onBlur: close,
6390
6902
  children: [
6391
6903
  children,
6392
- visible && /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime351.jsxs)(
6904
+ visible && /* @__PURE__ */ (0, import_jsx_runtime353.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime353.jsxs)(
6393
6905
  "div",
6394
6906
  {
6395
6907
  ref: tooltipRef,
@@ -6397,8 +6909,8 @@ var Tooltip = (props) => {
6397
6909
  className: clsx_default("lib-xplat-tooltip", shape),
6398
6910
  style: { position: "fixed", left: pos.left, top: pos.top },
6399
6911
  children: [
6400
- title && /* @__PURE__ */ (0, import_jsx_runtime351.jsx)("div", { className: "tooltip-title", children: title }),
6401
- description && /* @__PURE__ */ (0, import_jsx_runtime351.jsx)("div", { className: "tooltip-desc", children: description })
6912
+ title && /* @__PURE__ */ (0, import_jsx_runtime353.jsx)("div", { className: "tooltip-title", children: title }),
6913
+ description && /* @__PURE__ */ (0, import_jsx_runtime353.jsx)("div", { className: "tooltip-desc", children: description })
6402
6914
  ]
6403
6915
  }
6404
6916
  ) })
@@ -6410,11 +6922,11 @@ Tooltip.displayName = "Tooltip";
6410
6922
  var Tooltip_default = Tooltip;
6411
6923
 
6412
6924
  // src/components/Video/Video.tsx
6413
- var import_react41 = __toESM(require("react"), 1);
6414
- var import_jsx_runtime352 = require("react/jsx-runtime");
6415
- var PipIcon = () => /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
6416
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
6417
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
6925
+ var import_react43 = __toESM(require("react"), 1);
6926
+ var import_jsx_runtime354 = require("react/jsx-runtime");
6927
+ var PipIcon = () => /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
6928
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
6929
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
6418
6930
  ] });
6419
6931
  var formatTime = (sec) => {
6420
6932
  if (!Number.isFinite(sec) || sec < 0) return "0:00";
@@ -6422,7 +6934,7 @@ var formatTime = (sec) => {
6422
6934
  const s = Math.floor(sec % 60);
6423
6935
  return `${m}:${s.toString().padStart(2, "0")}`;
6424
6936
  };
6425
- var Video = import_react41.default.forwardRef((props, ref) => {
6937
+ var Video = import_react43.default.forwardRef((props, ref) => {
6426
6938
  const {
6427
6939
  src,
6428
6940
  poster,
@@ -6446,21 +6958,21 @@ var Video = import_react41.default.forwardRef((props, ref) => {
6446
6958
  children,
6447
6959
  ...rest
6448
6960
  } = props;
6449
- const containerRef = import_react41.default.useRef(null);
6450
- const videoRef = import_react41.default.useRef(null);
6451
- const [isPlaying, setIsPlaying] = import_react41.default.useState(Boolean(autoPlay));
6452
- const [isLoaded, setIsLoaded] = import_react41.default.useState(false);
6453
- const [currentTime, setCurrentTime] = import_react41.default.useState(0);
6454
- const [duration, setDuration] = import_react41.default.useState(0);
6455
- const [buffered, setBuffered] = import_react41.default.useState(0);
6456
- const [volume, setVolume] = import_react41.default.useState(1);
6457
- const [isMuted, setIsMuted] = import_react41.default.useState(Boolean(muted));
6458
- const [isFullscreen, setIsFullscreen] = import_react41.default.useState(false);
6459
- const [playbackRate, setPlaybackRate] = import_react41.default.useState(1);
6460
- const [rateMenuOpen, setRateMenuOpen] = import_react41.default.useState(false);
6461
- const [captionsOn, setCaptionsOn] = import_react41.default.useState(false);
6462
- const [isPip, setIsPip] = import_react41.default.useState(false);
6463
- const setRefs = import_react41.default.useCallback(
6961
+ const containerRef = import_react43.default.useRef(null);
6962
+ const videoRef = import_react43.default.useRef(null);
6963
+ const [isPlaying, setIsPlaying] = import_react43.default.useState(Boolean(autoPlay));
6964
+ const [isLoaded, setIsLoaded] = import_react43.default.useState(false);
6965
+ const [currentTime, setCurrentTime] = import_react43.default.useState(0);
6966
+ const [duration, setDuration] = import_react43.default.useState(0);
6967
+ const [buffered, setBuffered] = import_react43.default.useState(0);
6968
+ const [volume, setVolume] = import_react43.default.useState(1);
6969
+ const [isMuted, setIsMuted] = import_react43.default.useState(Boolean(muted));
6970
+ const [isFullscreen, setIsFullscreen] = import_react43.default.useState(false);
6971
+ const [playbackRate, setPlaybackRate] = import_react43.default.useState(1);
6972
+ const [rateMenuOpen, setRateMenuOpen] = import_react43.default.useState(false);
6973
+ const [captionsOn, setCaptionsOn] = import_react43.default.useState(false);
6974
+ const [isPip, setIsPip] = import_react43.default.useState(false);
6975
+ const setRefs = import_react43.default.useCallback(
6464
6976
  (el) => {
6465
6977
  videoRef.current = el;
6466
6978
  if (typeof ref === "function") ref(el);
@@ -6468,14 +6980,14 @@ var Video = import_react41.default.forwardRef((props, ref) => {
6468
6980
  },
6469
6981
  [ref]
6470
6982
  );
6471
- import_react41.default.useEffect(() => {
6983
+ import_react43.default.useEffect(() => {
6472
6984
  const onFsChange = () => {
6473
6985
  setIsFullscreen(document.fullscreenElement === containerRef.current);
6474
6986
  };
6475
6987
  document.addEventListener("fullscreenchange", onFsChange);
6476
6988
  return () => document.removeEventListener("fullscreenchange", onFsChange);
6477
6989
  }, []);
6478
- import_react41.default.useEffect(() => {
6990
+ import_react43.default.useEffect(() => {
6479
6991
  const v = videoRef.current;
6480
6992
  if (!v) return;
6481
6993
  const onEnter = () => setIsPip(true);
@@ -6589,13 +7101,13 @@ var Video = import_react41.default.forwardRef((props, ref) => {
6589
7101
  const volumePct = (isMuted ? 0 : volume) * 100;
6590
7102
  const VolumeGlyph = isMuted || volume === 0 ? VolumeXIcon_default : volume < 0.5 ? VolumeIcon_default : Volume2Icon_default;
6591
7103
  const pipSupported = typeof document !== "undefined" && "pictureInPictureEnabled" in document && document.pictureInPictureEnabled;
6592
- return /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)(
7104
+ return /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)(
6593
7105
  "div",
6594
7106
  {
6595
7107
  ref: containerRef,
6596
7108
  className: clsx_default("lib-xplat-video", showControls && "has-controls"),
6597
7109
  children: [
6598
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
7110
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
6599
7111
  "video",
6600
7112
  {
6601
7113
  ref: setRefs,
@@ -6616,7 +7128,7 @@ var Video = import_react41.default.forwardRef((props, ref) => {
6616
7128
  children
6617
7129
  }
6618
7130
  ),
6619
- showCenterPlay && /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
7131
+ showCenterPlay && /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
6620
7132
  "button",
6621
7133
  {
6622
7134
  type: "button",
@@ -6628,11 +7140,11 @@ var Video = import_react41.default.forwardRef((props, ref) => {
6628
7140
  onClick: togglePlay,
6629
7141
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
6630
7142
  tabIndex: -1,
6631
- children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("span", { className: "center-play-icon", children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(PlayCircleIcon_default, {}) })
7143
+ children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("span", { className: "center-play-icon", children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(PlayCircleIcon_default, {}) })
6632
7144
  }
6633
7145
  ),
6634
- showControls && /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
6635
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
7146
+ showControls && /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
7147
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
6636
7148
  "input",
6637
7149
  {
6638
7150
  type: "range",
@@ -6649,29 +7161,29 @@ var Video = import_react41.default.forwardRef((props, ref) => {
6649
7161
  }
6650
7162
  }
6651
7163
  ),
6652
- /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("div", { className: "controls-row", children: [
6653
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
7164
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("div", { className: "controls-row", children: [
7165
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
6654
7166
  "button",
6655
7167
  {
6656
7168
  type: "button",
6657
7169
  className: "control-btn",
6658
7170
  onClick: togglePlay,
6659
7171
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
6660
- children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(PauseIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(PlayIcon_default, {})
7172
+ children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(PauseIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(PlayIcon_default, {})
6661
7173
  }
6662
7174
  ),
6663
- /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("div", { className: "volume-group", children: [
6664
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
7175
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("div", { className: "volume-group", children: [
7176
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
6665
7177
  "button",
6666
7178
  {
6667
7179
  type: "button",
6668
7180
  className: "control-btn",
6669
7181
  onClick: toggleMute,
6670
7182
  "aria-label": isMuted ? "\uC74C\uC18C\uAC70 \uD574\uC81C" : "\uC74C\uC18C\uAC70",
6671
- children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(VolumeGlyph, {})
7183
+ children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(VolumeGlyph, {})
6672
7184
  }
6673
7185
  ),
6674
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
7186
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
6675
7187
  "input",
6676
7188
  {
6677
7189
  type: "range",
@@ -6686,14 +7198,14 @@ var Video = import_react41.default.forwardRef((props, ref) => {
6686
7198
  }
6687
7199
  )
6688
7200
  ] }),
6689
- /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("span", { className: "time", children: [
7201
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("span", { className: "time", children: [
6690
7202
  formatTime(currentTime),
6691
7203
  " / ",
6692
7204
  formatTime(duration)
6693
7205
  ] }),
6694
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("div", { className: "controls-spacer" }),
6695
- playbackRates && playbackRates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
6696
- /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)(
7206
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("div", { className: "controls-spacer" }),
7207
+ playbackRates && playbackRates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
7208
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)(
6697
7209
  "button",
6698
7210
  {
6699
7211
  type: "button",
@@ -6707,7 +7219,7 @@ var Video = import_react41.default.forwardRef((props, ref) => {
6707
7219
  ]
6708
7220
  }
6709
7221
  ),
6710
- rateMenuOpen && /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)(
7222
+ rateMenuOpen && /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)(
6711
7223
  "button",
6712
7224
  {
6713
7225
  type: "button",
@@ -6721,7 +7233,7 @@ var Video = import_react41.default.forwardRef((props, ref) => {
6721
7233
  }
6722
7234
  ) }, r2)) })
6723
7235
  ] }),
6724
- showCaptions && /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
7236
+ showCaptions && /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
6725
7237
  "button",
6726
7238
  {
6727
7239
  type: "button",
@@ -6729,37 +7241,37 @@ var Video = import_react41.default.forwardRef((props, ref) => {
6729
7241
  onClick: toggleCaptions,
6730
7242
  "aria-label": captionsOn ? "\uC790\uB9C9 \uB044\uAE30" : "\uC790\uB9C9 \uCF1C\uAE30",
6731
7243
  "aria-pressed": captionsOn,
6732
- children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(TypeIcon_default, {})
7244
+ children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(TypeIcon_default, {})
6733
7245
  }
6734
7246
  ),
6735
- showPip && pipSupported && /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
7247
+ showPip && pipSupported && /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
6736
7248
  "button",
6737
7249
  {
6738
7250
  type: "button",
6739
7251
  className: clsx_default("control-btn", isPip && "is-active"),
6740
7252
  onClick: togglePip,
6741
7253
  "aria-label": isPip ? "PIP \uC885\uB8CC" : "PIP",
6742
- children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(PipIcon, {})
7254
+ children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(PipIcon, {})
6743
7255
  }
6744
7256
  ),
6745
- showDownload && /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
7257
+ showDownload && /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
6746
7258
  "a",
6747
7259
  {
6748
7260
  className: "control-btn",
6749
7261
  href: src,
6750
7262
  download: downloadFileName ?? true,
6751
7263
  "aria-label": "\uB2E4\uC6B4\uB85C\uB4DC",
6752
- children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(DownloadIcon_default, {})
7264
+ children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(DownloadIcon_default, {})
6753
7265
  }
6754
7266
  ),
6755
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
7267
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
6756
7268
  "button",
6757
7269
  {
6758
7270
  type: "button",
6759
7271
  className: "control-btn",
6760
7272
  onClick: toggleFullscreen,
6761
7273
  "aria-label": isFullscreen ? "\uC804\uCCB4\uD654\uBA74 \uC885\uB8CC" : "\uC804\uCCB4\uD654\uBA74",
6762
- children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(MinimizeIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(MaximizeIcon_default, {})
7274
+ children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(MinimizeIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(MaximizeIcon_default, {})
6763
7275
  }
6764
7276
  )
6765
7277
  ] })
@@ -6817,6 +7329,7 @@ var Video_default = Video;
6817
7329
  SingleDatePicker,
6818
7330
  Skeleton,
6819
7331
  Spinner,
7332
+ Stat,
6820
7333
  Steps,
6821
7334
  Swiper,
6822
7335
  Switch,
@@ -6828,6 +7341,7 @@ var Video_default = Video;
6828
7341
  TableRow,
6829
7342
  Tag,
6830
7343
  TextArea,
7344
+ TimePicker,
6831
7345
  ToastProvider,
6832
7346
  Tooltip,
6833
7347
  Video,