@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
@@ -1532,11 +1532,16 @@ var FieldMessage = (props) => {
1532
1532
  FieldMessage.displayName = "FieldMessage";
1533
1533
  var FieldMessage_default = FieldMessage;
1534
1534
  var Field = (props) => {
1535
- const { validations, children } = props;
1536
- if (!validations || validations.length === 0) return /* @__PURE__ */ jsx297(Fragment, { children });
1535
+ const { label, required = false, htmlFor, validations, children } = props;
1536
+ const hasMessages = !!validations && validations.length > 0;
1537
+ if (!label && !hasMessages) return /* @__PURE__ */ jsx297(Fragment, { children });
1537
1538
  return /* @__PURE__ */ jsxs191("div", { className: "lib-xplat-field", children: [
1539
+ label && /* @__PURE__ */ jsxs191("label", { className: "lib-xplat-field-label", htmlFor, children: [
1540
+ label,
1541
+ required && /* @__PURE__ */ jsx297("span", { className: "required", "aria-hidden": "true", children: "*" })
1542
+ ] }),
1538
1543
  children,
1539
- /* @__PURE__ */ jsx297(FieldMessage, { validations })
1544
+ hasMessages && /* @__PURE__ */ jsx297(FieldMessage, { validations })
1540
1545
  ] });
1541
1546
  };
1542
1547
  Field.displayName = "Field";
@@ -1547,7 +1552,9 @@ import { jsx as jsx298 } from "react/jsx-runtime";
1547
1552
  var MAX_HEIGHT = 400;
1548
1553
  var AutoResizeTextArea = React2.forwardRef(
1549
1554
  (props, ref) => {
1550
- const { value, className, onChange, disabled, bare = false, validations, ...textareaProps } = props;
1555
+ const { value, className, onChange, disabled, bare = false, validations, label, required, ...textareaProps } = props;
1556
+ const autoId = React2.useId();
1557
+ const fieldId = props.id ?? autoId;
1551
1558
  const localRef = React2.useRef(null);
1552
1559
  const setRefs = (el) => {
1553
1560
  localRef.current = el;
@@ -1581,6 +1588,7 @@ var AutoResizeTextArea = React2.forwardRef(
1581
1588
  "aria-invalid": hasError(validations) || void 0,
1582
1589
  ...textareaProps,
1583
1590
  ref: setRefs,
1591
+ id: fieldId,
1584
1592
  className,
1585
1593
  disabled,
1586
1594
  value,
@@ -1594,12 +1602,13 @@ var AutoResizeTextArea = React2.forwardRef(
1594
1602
  "aria-invalid": hasError(validations) || void 0,
1595
1603
  ...textareaProps,
1596
1604
  ref: setRefs,
1605
+ id: fieldId,
1597
1606
  disabled,
1598
1607
  value,
1599
1608
  onChange: handleChange
1600
1609
  }
1601
1610
  ) }) });
1602
- return /* @__PURE__ */ jsx298(Field, { validations, children: control });
1611
+ return /* @__PURE__ */ jsx298(Field, { validations, label, required, htmlFor: fieldId, children: control });
1603
1612
  }
1604
1613
  );
1605
1614
  AutoResizeTextArea.displayName = "AutoResizeTextArea";
@@ -2817,8 +2826,11 @@ var ChatInput = React7.forwardRef(
2817
2826
  buttonType = "primary",
2818
2827
  onSubmit,
2819
2828
  onChange,
2820
- validations
2829
+ validations,
2830
+ label,
2831
+ required
2821
2832
  } = props;
2833
+ const fieldId = React7.useId();
2822
2834
  const isControlled = valueProp !== void 0;
2823
2835
  const [internalValue, setInternalValue] = React7.useState("");
2824
2836
  const value = isControlled ? valueProp : internalValue;
@@ -2843,6 +2855,7 @@ var ChatInput = React7.forwardRef(
2843
2855
  /* @__PURE__ */ jsx308(
2844
2856
  AutoResizeTextArea_default,
2845
2857
  {
2858
+ id: fieldId,
2846
2859
  ref,
2847
2860
  bare: true,
2848
2861
  className: "chat-input-textarea",
@@ -2867,7 +2880,7 @@ var ChatInput = React7.forwardRef(
2867
2880
  }
2868
2881
  )
2869
2882
  ] });
2870
- return /* @__PURE__ */ jsx308(Field, { validations, children: control });
2883
+ return /* @__PURE__ */ jsx308(Field, { validations, label, required, htmlFor: fieldId, children: control });
2871
2884
  }
2872
2885
  );
2873
2886
  ChatInput.displayName = "ChatInput";
@@ -2938,7 +2951,7 @@ Chip.displayName = "Chip";
2938
2951
  var Chip_default = Chip;
2939
2952
 
2940
2953
  // src/components/DatePicker/InputDatePicker/index.tsx
2941
- import React12 from "react";
2954
+ import React13 from "react";
2942
2955
 
2943
2956
  // src/components/Input/Input.tsx
2944
2957
  import React8 from "react";
@@ -3036,8 +3049,12 @@ var Input = React8.forwardRef((props, ref) => {
3036
3049
  suffix,
3037
3050
  disabled,
3038
3051
  validations,
3052
+ label,
3053
+ required,
3039
3054
  ...inputProps
3040
3055
  } = props;
3056
+ const autoId = React8.useId();
3057
+ const fieldId = inputProps.id ?? autoId;
3041
3058
  const localValue = formatValue(type, value);
3042
3059
  const handleChange = (e) => {
3043
3060
  let val = e.target.value;
@@ -3053,7 +3070,7 @@ var Input = React8.forwardRef((props, ref) => {
3053
3070
  onChange(event);
3054
3071
  }
3055
3072
  };
3056
- return /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
3073
+ return /* @__PURE__ */ jsx311(Field, { label, required, htmlFor: fieldId, children: /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
3057
3074
  /* @__PURE__ */ jsxs199(
3058
3075
  "div",
3059
3076
  {
@@ -3064,6 +3081,7 @@ var Input = React8.forwardRef((props, ref) => {
3064
3081
  {
3065
3082
  ...inputProps,
3066
3083
  ref,
3084
+ id: fieldId,
3067
3085
  disabled,
3068
3086
  type: type === "number" ? "text" : type,
3069
3087
  value: localValue,
@@ -3076,7 +3094,7 @@ var Input = React8.forwardRef((props, ref) => {
3076
3094
  }
3077
3095
  ),
3078
3096
  /* @__PURE__ */ jsx311(FieldMessage_default, { validations })
3079
- ] });
3097
+ ] }) });
3080
3098
  });
3081
3099
  Input.displayName = "Input";
3082
3100
  var Input_default = Input;
@@ -3106,16 +3124,96 @@ PasswordInput.displayName = "PasswordInput";
3106
3124
  var PasswordInput_default = PasswordInput;
3107
3125
 
3108
3126
  // src/components/Modal/Modal.tsx
3109
- import React10 from "react";
3127
+ import React11 from "react";
3110
3128
  import { createPortal } from "react-dom";
3129
+
3130
+ // src/tokens/hooks/useOverlayKeyboard.ts
3131
+ import React10 from "react";
3132
+ var FOCUSABLE = [
3133
+ "a[href]",
3134
+ "button:not([disabled])",
3135
+ "input:not([disabled]):not([type='hidden'])",
3136
+ "select:not([disabled])",
3137
+ "textarea:not([disabled])",
3138
+ "[tabindex]:not([tabindex='-1'])"
3139
+ ].join(",");
3140
+ var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
3141
+ // 화면에 없는 것은 제외 (display:none 등)
3142
+ (n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
3143
+ );
3144
+ var useEscapeKey = (enabled, onEscape) => {
3145
+ React10.useEffect(() => {
3146
+ if (!enabled) return;
3147
+ const onKey = (e) => {
3148
+ if (e.key !== "Escape") return;
3149
+ if (e.defaultPrevented) return;
3150
+ e.preventDefault();
3151
+ onEscape();
3152
+ };
3153
+ document.addEventListener("keydown", onKey);
3154
+ return () => document.removeEventListener("keydown", onKey);
3155
+ }, [enabled, onEscape]);
3156
+ };
3157
+ var useFocusTrap = (containerRef, enabled, options = {}) => {
3158
+ const { trap = false, initialFocus } = options;
3159
+ const restoreRef = React10.useRef(null);
3160
+ React10.useEffect(() => {
3161
+ if (!enabled) return;
3162
+ restoreRef.current = document.activeElement;
3163
+ const raf = requestAnimationFrame(() => {
3164
+ const el = containerRef.current;
3165
+ if (!el) return;
3166
+ const target = initialFocus?.current ?? focusableIn(el)[0] ?? el;
3167
+ if (!target.hasAttribute("tabindex") && !focusableIn(el).includes(target)) {
3168
+ target.setAttribute("tabindex", "-1");
3169
+ }
3170
+ target.focus({ preventScroll: true });
3171
+ });
3172
+ return () => {
3173
+ cancelAnimationFrame(raf);
3174
+ const prev = restoreRef.current;
3175
+ if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
3176
+ };
3177
+ }, [enabled, containerRef, initialFocus]);
3178
+ React10.useEffect(() => {
3179
+ if (!enabled || !trap) return;
3180
+ const onKey = (e) => {
3181
+ if (e.key !== "Tab") return;
3182
+ const el = containerRef.current;
3183
+ if (!el) return;
3184
+ const items = focusableIn(el);
3185
+ if (items.length === 0) {
3186
+ e.preventDefault();
3187
+ return;
3188
+ }
3189
+ const first = items[0];
3190
+ const last = items[items.length - 1];
3191
+ const active = document.activeElement;
3192
+ if (e.shiftKey && (active === first || !el.contains(active))) {
3193
+ e.preventDefault();
3194
+ last.focus();
3195
+ } else if (!e.shiftKey && (active === last || !el.contains(active))) {
3196
+ e.preventDefault();
3197
+ first.focus();
3198
+ }
3199
+ };
3200
+ document.addEventListener("keydown", onKey);
3201
+ return () => document.removeEventListener("keydown", onKey);
3202
+ }, [enabled, trap, containerRef]);
3203
+ };
3204
+
3205
+ // src/components/Modal/Modal.tsx
3111
3206
  import { jsx as jsx313 } from "react/jsx-runtime";
3112
3207
  var ANIMATION_DURATION_MS = 200;
3113
3208
  var Modal = (props) => {
3114
3209
  const { isOpen, onClose, children } = props;
3115
- const [mounted, setMounted] = React10.useState(false);
3116
- const [visible, setVisible] = React10.useState(false);
3117
- const [settled, setSettled] = React10.useState(false);
3118
- React10.useEffect(() => {
3210
+ const [mounted, setMounted] = React11.useState(false);
3211
+ const [visible, setVisible] = React11.useState(false);
3212
+ const [settled, setSettled] = React11.useState(false);
3213
+ const boxRef = React11.useRef(null);
3214
+ useEscapeKey(isOpen, onClose);
3215
+ useFocusTrap(boxRef, isOpen && mounted, { trap: true });
3216
+ React11.useEffect(() => {
3119
3217
  if (isOpen) {
3120
3218
  setMounted(true);
3121
3219
  const show = setTimeout(() => setVisible(true), 1);
@@ -3142,6 +3240,7 @@ var Modal = (props) => {
3142
3240
  children: /* @__PURE__ */ jsx313(
3143
3241
  "div",
3144
3242
  {
3243
+ ref: boxRef,
3145
3244
  className: clsx_default("lib-xplat-modal", "modal-box", stateClass, settled && "settled"),
3146
3245
  role: "dialog",
3147
3246
  "aria-modal": "true",
@@ -3158,9 +3257,9 @@ Modal.displayName = "Modal";
3158
3257
  var Modal_default = Modal;
3159
3258
 
3160
3259
  // src/components/DatePicker/SingleDatePicker/index.tsx
3161
- import React11 from "react";
3260
+ import React12 from "react";
3162
3261
  import { Fragment as Fragment4, jsx as jsx314, jsxs as jsxs200 } from "react/jsx-runtime";
3163
- var DayCell2 = React11.memo(
3262
+ var DayCell2 = React12.memo(
3164
3263
  ({
3165
3264
  day,
3166
3265
  disabled,
@@ -3212,26 +3311,26 @@ var SingleDatePicker = (props) => {
3212
3311
  initialYear,
3213
3312
  initialMonth
3214
3313
  );
3215
- const [pickerMode, setPickerMode] = React11.useState("days");
3216
- const [yearRangeStart, setYearRangeStart] = React11.useState(
3314
+ const [pickerMode, setPickerMode] = React12.useState("days");
3315
+ const [yearRangeStart, setYearRangeStart] = React12.useState(
3217
3316
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
3218
3317
  );
3219
- const minTime = React11.useMemo(
3318
+ const minTime = React12.useMemo(
3220
3319
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
3221
3320
  [minDate]
3222
3321
  );
3223
- const maxTime = React11.useMemo(
3322
+ const maxTime = React12.useMemo(
3224
3323
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
3225
3324
  [maxDate]
3226
3325
  );
3227
- const highlightSet = React11.useMemo(() => {
3326
+ const highlightSet = React12.useMemo(() => {
3228
3327
  const set = /* @__PURE__ */ new Set();
3229
3328
  for (const h of highlightDates) {
3230
3329
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
3231
3330
  }
3232
3331
  return set;
3233
3332
  }, [highlightDates]);
3234
- const handleSelect = React11.useCallback(
3333
+ const handleSelect = React12.useCallback(
3235
3334
  (date) => {
3236
3335
  onChange?.(date);
3237
3336
  },
@@ -3360,8 +3459,8 @@ var formatDate = (date) => {
3360
3459
  };
3361
3460
  var InputDatePicker = (props) => {
3362
3461
  const { value, onChange, minDate, maxDate, disabled, locale = "ko", placeholder } = props;
3363
- const [isOpen, setIsOpen] = React12.useState(false);
3364
- const [tempDate, setTempDate] = React12.useState(value ?? /* @__PURE__ */ new Date());
3462
+ const [isOpen, setIsOpen] = React13.useState(false);
3463
+ const [tempDate, setTempDate] = React13.useState(value ?? /* @__PURE__ */ new Date());
3365
3464
  const handleOpen = () => {
3366
3465
  if (disabled) return;
3367
3466
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -3410,23 +3509,27 @@ InputDatePicker.displayName = "InputDatePicker";
3410
3509
  var InputDatePicker_default = InputDatePicker;
3411
3510
 
3412
3511
  // src/components/DatePicker/PopupPicker/index.tsx
3413
- import React16 from "react";
3512
+ import React17 from "react";
3414
3513
 
3415
3514
  // src/components/DatePicker/RangePicker/index.tsx
3416
- import React15 from "react";
3515
+ import React16 from "react";
3417
3516
 
3418
3517
  // src/components/Tab/Tab.tsx
3419
- import React14 from "react";
3518
+ import React15 from "react";
3420
3519
 
3421
3520
  // src/components/Tab/TabItem.tsx
3422
- import React13 from "react";
3521
+ import React14 from "react";
3423
3522
  import { jsx as jsx316 } from "react/jsx-runtime";
3424
- var TabItem = React13.forwardRef((props, ref) => {
3523
+ var TabItem = React14.forwardRef((props, ref) => {
3425
3524
  const { isActive: isActive2, title, onClick } = props;
3426
3525
  return /* @__PURE__ */ jsx316(
3427
- "div",
3526
+ "button",
3428
3527
  {
3429
3528
  ref,
3529
+ type: "button",
3530
+ role: "tab",
3531
+ "aria-selected": isActive2,
3532
+ tabIndex: isActive2 ? 0 : -1,
3430
3533
  className: clsx_default("tab-item", isActive2 ? "active" : null),
3431
3534
  onClick,
3432
3535
  children: title
@@ -3441,44 +3544,64 @@ import { jsx as jsx317, jsxs as jsxs202 } from "react/jsx-runtime";
3441
3544
  var Tab = (props) => {
3442
3545
  const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
3443
3546
  const shape = variant ?? type ?? "default";
3444
- const [underlineStyle, setUnderlineStyle] = React14.useState({
3547
+ const [underlineStyle, setUnderlineStyle] = React15.useState({
3445
3548
  left: 0,
3446
3549
  width: 0
3447
3550
  });
3448
- const itemRefs = React14.useRef([]);
3551
+ const itemRefs = React15.useRef([]);
3552
+ const handleKeyDown = (e) => {
3553
+ const last = tabs.length - 1;
3554
+ let next = null;
3555
+ if (e.key === "ArrowRight") next = activeIndex >= last ? 0 : activeIndex + 1;
3556
+ else if (e.key === "ArrowLeft") next = activeIndex <= 0 ? last : activeIndex - 1;
3557
+ else if (e.key === "Home") next = 0;
3558
+ else if (e.key === "End") next = last;
3559
+ if (next === null) return;
3560
+ e.preventDefault();
3561
+ onChange(tabs[next], next);
3562
+ itemRefs.current[next]?.focus();
3563
+ };
3449
3564
  const handleChangeActiveTab = (tabItem, tabIdx) => {
3450
3565
  onChange(tabItem, tabIdx);
3451
3566
  };
3452
- React14.useEffect(() => {
3567
+ React15.useEffect(() => {
3453
3568
  const el = itemRefs.current[activeIndex];
3454
3569
  if (el) {
3455
3570
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
3456
3571
  }
3457
3572
  }, [activeIndex, tabs.length]);
3458
- return /* @__PURE__ */ jsxs202("div", { className: clsx_default("lib-xplat-tab", `type-${shape}`, size), children: [
3459
- tabs.map((tab, idx) => /* @__PURE__ */ jsx317(
3460
- TabItem_default,
3461
- {
3462
- onClick: () => handleChangeActiveTab(tab, idx),
3463
- isActive: activeIndex === idx,
3464
- ref: (el) => {
3465
- itemRefs.current[idx] = el;
3466
- },
3467
- title: tab.title
3468
- },
3469
- `${tab.value}_${idx}`
3470
- )),
3471
- shape === "toggle" && /* @__PURE__ */ jsx317(
3472
- "div",
3473
- {
3474
- className: "tab-toggle-underline",
3475
- style: {
3476
- left: underlineStyle.left,
3477
- width: underlineStyle.width
3478
- }
3479
- }
3480
- )
3481
- ] });
3573
+ return /* @__PURE__ */ jsxs202(
3574
+ "div",
3575
+ {
3576
+ className: clsx_default("lib-xplat-tab", `type-${shape}`, size),
3577
+ role: "tablist",
3578
+ onKeyDown: handleKeyDown,
3579
+ children: [
3580
+ tabs.map((tab, idx) => /* @__PURE__ */ jsx317(
3581
+ TabItem_default,
3582
+ {
3583
+ onClick: () => handleChangeActiveTab(tab, idx),
3584
+ isActive: activeIndex === idx,
3585
+ ref: (el) => {
3586
+ itemRefs.current[idx] = el;
3587
+ },
3588
+ title: tab.title
3589
+ },
3590
+ `${tab.value}_${idx}`
3591
+ )),
3592
+ shape === "toggle" && /* @__PURE__ */ jsx317(
3593
+ "div",
3594
+ {
3595
+ className: "tab-toggle-underline",
3596
+ style: {
3597
+ left: underlineStyle.left,
3598
+ width: underlineStyle.width
3599
+ }
3600
+ }
3601
+ )
3602
+ ]
3603
+ }
3604
+ );
3482
3605
  };
3483
3606
  Tab.displayName = "Tab";
3484
3607
  var Tab_default = Tab;
@@ -3494,7 +3617,7 @@ var RangePicker = (props) => {
3494
3617
  maxDate,
3495
3618
  locale = "ko"
3496
3619
  } = props;
3497
- const [activeTab, setActiveTab] = React15.useState("start");
3620
+ const [activeTab, setActiveTab] = React16.useState("start");
3498
3621
  const handleStartChange = (date) => {
3499
3622
  if (!date) return;
3500
3623
  const newStart = date > endDate ? endDate : date;
@@ -3579,7 +3702,7 @@ var RangePicker_default = RangePicker;
3579
3702
  import { jsx as jsx319, jsxs as jsxs204 } from "react/jsx-runtime";
3580
3703
  var PopupPicker = (props) => {
3581
3704
  const { component, type, locale } = props;
3582
- const [isOpen, setIsOpen] = React16.useState(false);
3705
+ const [isOpen, setIsOpen] = React17.useState(false);
3583
3706
  const handleClick = () => setIsOpen(true);
3584
3707
  const handleClose = () => setIsOpen(false);
3585
3708
  const handleSingleChange = (date) => {
@@ -3588,7 +3711,7 @@ var PopupPicker = (props) => {
3588
3711
  handleClose();
3589
3712
  };
3590
3713
  return /* @__PURE__ */ jsxs204("div", { className: "lib-xplat-popup-datepicker", children: [
3591
- React16.cloneElement(component, { onClick: handleClick }),
3714
+ React17.cloneElement(component, { onClick: handleClick }),
3592
3715
  /* @__PURE__ */ jsx319(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ jsxs204("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
3593
3716
  /* @__PURE__ */ jsxs204("div", { className: "popup-datepicker-content", children: [
3594
3717
  type === "single" && /* @__PURE__ */ jsx319(
@@ -3647,15 +3770,18 @@ Divider.displayName = "Divider";
3647
3770
  var Divider_default = Divider;
3648
3771
 
3649
3772
  // src/components/Drawer/Drawer.tsx
3650
- import React17 from "react";
3773
+ import React18 from "react";
3651
3774
  import { createPortal as createPortal2 } from "react-dom";
3652
3775
  import { jsx as jsx321, jsxs as jsxs205 } from "react/jsx-runtime";
3653
3776
  var ANIMATION_DURATION_MS2 = 250;
3654
3777
  var Drawer = (props) => {
3655
3778
  const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
3656
- const [mounted, setMounted] = React17.useState(false);
3657
- const [visible, setVisible] = React17.useState(false);
3658
- React17.useEffect(() => {
3779
+ const [mounted, setMounted] = React18.useState(false);
3780
+ const [visible, setVisible] = React18.useState(false);
3781
+ const panelRef = React18.useRef(null);
3782
+ useEscapeKey(isOpen, onClose);
3783
+ useFocusTrap(panelRef, isOpen && mounted, { trap: true });
3784
+ React18.useEffect(() => {
3659
3785
  if (isOpen) {
3660
3786
  setMounted(true);
3661
3787
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -3677,6 +3803,7 @@ var Drawer = (props) => {
3677
3803
  children: /* @__PURE__ */ jsxs205(
3678
3804
  "div",
3679
3805
  {
3806
+ ref: panelRef,
3680
3807
  className: clsx_default("lib-xplat-drawer", placement, size, stateClass),
3681
3808
  role: "dialog",
3682
3809
  "aria-modal": "true",
@@ -3699,7 +3826,7 @@ Drawer.displayName = "Drawer";
3699
3826
  var Drawer_default = Drawer;
3700
3827
 
3701
3828
  // src/components/Dropdown/Dropdown.tsx
3702
- import React20 from "react";
3829
+ import React21 from "react";
3703
3830
 
3704
3831
  // src/tokens/hooks/Portal.tsx
3705
3832
  import ReactDOM from "react-dom";
@@ -3711,13 +3838,13 @@ Portal.displayName = "Portal";
3711
3838
  var Portal_default = Portal;
3712
3839
 
3713
3840
  // src/tokens/hooks/useAutoPosition.ts
3714
- import React18 from "react";
3841
+ import React19 from "react";
3715
3842
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3716
- const [position, setPosition] = React18.useState({
3843
+ const [position, setPosition] = React19.useState({
3717
3844
  position: {},
3718
3845
  direction: "bottom"
3719
3846
  });
3720
- const calculatePosition = React18.useCallback(() => {
3847
+ const calculatePosition = React19.useCallback(() => {
3721
3848
  if (!triggerRef.current || !popRef.current) return;
3722
3849
  const triggerRect = triggerRef.current.getBoundingClientRect();
3723
3850
  const popW = popRef.current.offsetWidth;
@@ -3744,13 +3871,13 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3744
3871
  direction
3745
3872
  });
3746
3873
  }, [triggerRef, popRef]);
3747
- React18.useLayoutEffect(() => {
3874
+ React19.useLayoutEffect(() => {
3748
3875
  if (!enabled) return;
3749
3876
  calculatePosition();
3750
3877
  const raf = requestAnimationFrame(calculatePosition);
3751
3878
  return () => cancelAnimationFrame(raf);
3752
3879
  }, [calculatePosition, enabled]);
3753
- React18.useEffect(() => {
3880
+ React19.useEffect(() => {
3754
3881
  if (!enabled || !popRef.current) return;
3755
3882
  const observer = new ResizeObserver(() => {
3756
3883
  calculatePosition();
@@ -3758,7 +3885,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3758
3885
  observer.observe(popRef.current);
3759
3886
  return () => observer.disconnect();
3760
3887
  }, [calculatePosition, enabled, popRef]);
3761
- React18.useEffect(() => {
3888
+ React19.useEffect(() => {
3762
3889
  if (!enabled) return;
3763
3890
  window.addEventListener("resize", calculatePosition);
3764
3891
  window.addEventListener("scroll", calculatePosition, true);
@@ -3772,9 +3899,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3772
3899
  var useAutoPosition_default = useAutoPosition;
3773
3900
 
3774
3901
  // src/tokens/hooks/useClickOutside.ts
3775
- import React19 from "react";
3902
+ import React20 from "react";
3776
3903
  var useClickOutside = (refs, handler, enabled = true) => {
3777
- React19.useEffect(() => {
3904
+ React20.useEffect(() => {
3778
3905
  if (!enabled) return;
3779
3906
  const refArray = Array.isArray(refs) ? refs : [refs];
3780
3907
  const listener = (event) => {
@@ -3800,14 +3927,18 @@ var useClickOutside_default = useClickOutside;
3800
3927
  import { jsx as jsx322, jsxs as jsxs206 } from "react/jsx-runtime";
3801
3928
  var Dropdown = (props) => {
3802
3929
  const { items, children } = props;
3803
- const [isOpen, setIsOpen] = React20.useState(false);
3804
- const [mounted, setMounted] = React20.useState(false);
3805
- const [visible, setVisible] = React20.useState(false);
3806
- const triggerRef = React20.useRef(null);
3807
- const menuRef = React20.useRef(null);
3930
+ const [isOpen, setIsOpen] = React21.useState(false);
3931
+ const [mounted, setMounted] = React21.useState(false);
3932
+ const [visible, setVisible] = React21.useState(false);
3933
+ const triggerRef = React21.useRef(null);
3934
+ const menuRef = React21.useRef(null);
3808
3935
  const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
3809
3936
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
3810
- React20.useEffect(() => {
3937
+ useEscapeKey(isOpen, () => {
3938
+ setIsOpen(false);
3939
+ triggerRef.current?.focus({ preventScroll: true });
3940
+ });
3941
+ React21.useEffect(() => {
3811
3942
  if (isOpen) {
3812
3943
  setMounted(true);
3813
3944
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -3861,7 +3992,7 @@ Dropdown.displayName = "Dropdown";
3861
3992
  var Dropdown_default = Dropdown;
3862
3993
 
3863
3994
  // src/components/Editor/Editor.tsx
3864
- import React21 from "react";
3995
+ import React22 from "react";
3865
3996
  import { jsx as jsx323, jsxs as jsxs207 } from "react/jsx-runtime";
3866
3997
  var DEFAULT_TOOLBAR = [
3867
3998
  "bold",
@@ -3911,6 +4042,15 @@ var ALLOWED_ATTRS = {
3911
4042
  a: ["href", "target", "rel"],
3912
4043
  img: ["src", "alt"]
3913
4044
  };
4045
+ var DROP_WITH_CONTENT = /* @__PURE__ */ new Set([
4046
+ "script",
4047
+ "style",
4048
+ "noscript",
4049
+ "iframe",
4050
+ "object",
4051
+ "embed",
4052
+ "template"
4053
+ ]);
3914
4054
  var sanitizeHtml = (input) => {
3915
4055
  const doc = new DOMParser().parseFromString(`<div>${input}</div>`, "text/html");
3916
4056
  const root = doc.body.firstElementChild;
@@ -3919,6 +4059,10 @@ var sanitizeHtml = (input) => {
3919
4059
  const children = Array.from(node.children);
3920
4060
  for (const child of children) {
3921
4061
  const tag = child.tagName.toLowerCase();
4062
+ if (DROP_WITH_CONTENT.has(tag)) {
4063
+ node.removeChild(child);
4064
+ continue;
4065
+ }
3922
4066
  if (!ALLOWED_TAGS.has(tag)) {
3923
4067
  while (child.firstChild) node.insertBefore(child.firstChild, child);
3924
4068
  node.removeChild(child);
@@ -3969,26 +4113,30 @@ var Editor = (props) => {
3969
4113
  onImageUpload,
3970
4114
  minHeight = 200
3971
4115
  } = props;
3972
- const editorRef = React21.useRef(null);
3973
- const lastRangeRef = React21.useRef(null);
3974
- const composingRef = React21.useRef(false);
3975
- const [isFocused, setIsFocused] = React21.useState(false);
3976
- const [isEmpty, setIsEmpty] = React21.useState(!value);
3977
- const [activeFormats, setActiveFormats] = React21.useState(/* @__PURE__ */ new Set());
3978
- const [slashOpen, setSlashOpen] = React21.useState(false);
3979
- const [slashFilter, setSlashFilter] = React21.useState("");
3980
- const [slashIdx, setSlashIdx] = React21.useState(0);
3981
- const [slashPos, setSlashPos] = React21.useState({ top: 0, left: 0 });
3982
- const slashStartRangeRef = React21.useRef(null);
3983
- const [linkOpen, setLinkOpen] = React21.useState(false);
3984
- const [linkValue, setLinkValue] = React21.useState("");
3985
- const [linkPos, setLinkPos] = React21.useState({ top: 0, left: 0 });
3986
- React21.useEffect(() => {
3987
- if (!editorRef.current) return;
3988
- if (editorRef.current.innerHTML !== value) {
3989
- editorRef.current.innerHTML = sanitizeHtml(value || "");
3990
- updateEmpty();
3991
- }
4116
+ const editorRef = React22.useRef(null);
4117
+ const lastRangeRef = React22.useRef(null);
4118
+ const composingRef = React22.useRef(false);
4119
+ const [isFocused, setIsFocused] = React22.useState(false);
4120
+ const [isEmpty, setIsEmpty] = React22.useState(!value);
4121
+ const [activeFormats, setActiveFormats] = React22.useState(/* @__PURE__ */ new Set());
4122
+ const [slashOpen, setSlashOpen] = React22.useState(false);
4123
+ const [slashFilter, setSlashFilter] = React22.useState("");
4124
+ const [slashIdx, setSlashIdx] = React22.useState(0);
4125
+ const [slashPos, setSlashPos] = React22.useState({ top: 0, left: 0 });
4126
+ const slashStartRangeRef = React22.useRef(null);
4127
+ const [linkOpen, setLinkOpen] = React22.useState(false);
4128
+ const [linkValue, setLinkValue] = React22.useState("");
4129
+ const [linkPos, setLinkPos] = React22.useState({ top: 0, left: 0 });
4130
+ const lastEmittedRef = React22.useRef(null);
4131
+ React22.useEffect(() => {
4132
+ const el = editorRef.current;
4133
+ if (!el) return;
4134
+ if (value === lastEmittedRef.current) return;
4135
+ if (el.innerHTML === value) return;
4136
+ el.innerHTML = sanitizeHtml(value || "");
4137
+ if (!el.firstChild) el.innerHTML = "<p><br></p>";
4138
+ lastEmittedRef.current = null;
4139
+ updateEmpty();
3992
4140
  }, [value]);
3993
4141
  const updateEmpty = () => {
3994
4142
  const el = editorRef.current;
@@ -4004,10 +4152,19 @@ var Editor = (props) => {
4004
4152
  }
4005
4153
  };
4006
4154
  const restoreSelection = () => {
4007
- if (!lastRangeRef.current) return;
4155
+ const range = lastRangeRef.current;
4156
+ if (!range) return;
4157
+ if (!editorRef.current?.contains(range.startContainer)) {
4158
+ lastRangeRef.current = null;
4159
+ return;
4160
+ }
4008
4161
  const sel = window.getSelection();
4009
- sel?.removeAllRanges();
4010
- sel?.addRange(lastRangeRef.current);
4162
+ try {
4163
+ sel?.removeAllRanges();
4164
+ sel?.addRange(range);
4165
+ } catch {
4166
+ lastRangeRef.current = null;
4167
+ }
4011
4168
  };
4012
4169
  const updateActiveFormats = () => {
4013
4170
  if (!editorRef.current) return;
@@ -4036,6 +4193,96 @@ var Editor = (props) => {
4036
4193
  const setBlock = (tag) => {
4037
4194
  exec("formatBlock", tag);
4038
4195
  };
4196
+ const closestPre = () => {
4197
+ const sel = window.getSelection();
4198
+ const node = sel?.anchorNode;
4199
+ if (!node || !editorRef.current?.contains(node)) return null;
4200
+ const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
4201
+ return el?.closest("pre") ?? null;
4202
+ };
4203
+ const insertCodeBlock = () => {
4204
+ const el = editorRef.current;
4205
+ const sel = window.getSelection();
4206
+ if (!el || !sel || sel.rangeCount === 0) return;
4207
+ const existing = closestPre();
4208
+ if (existing) {
4209
+ const p = document.createElement("p");
4210
+ p.textContent = existing.textContent || "";
4211
+ if (!p.textContent) p.innerHTML = "<br>";
4212
+ existing.replaceWith(p);
4213
+ placeCaretAtEnd(p);
4214
+ handleInput();
4215
+ return;
4216
+ }
4217
+ const range = sel.getRangeAt(0);
4218
+ const frag = range.cloneContents();
4219
+ const holder = document.createElement("div");
4220
+ holder.appendChild(frag);
4221
+ const BLOCK = /^(p|div|h[1-6]|li|blockquote|pre|tr)$/i;
4222
+ const linesOf = (node) => {
4223
+ const out = [];
4224
+ let cur = "";
4225
+ for (const child of Array.from(node.childNodes)) {
4226
+ if (child.nodeType === Node.TEXT_NODE) {
4227
+ cur += child.textContent || "";
4228
+ } else if (child.nodeName === "BR") {
4229
+ out.push(cur);
4230
+ cur = "";
4231
+ } else if (BLOCK.test(child.nodeName)) {
4232
+ if (cur) {
4233
+ out.push(cur);
4234
+ cur = "";
4235
+ }
4236
+ const sub = linesOf(child);
4237
+ out.push(...sub.length > 0 ? sub : [""]);
4238
+ } else {
4239
+ cur += linesOf(child).join("\n");
4240
+ }
4241
+ }
4242
+ if (cur) out.push(cur);
4243
+ return out;
4244
+ };
4245
+ const text = linesOf(holder).join("\n").replace(/\n+$/, "");
4246
+ const pre = document.createElement("pre");
4247
+ const code = document.createElement("code");
4248
+ code.textContent = text || "";
4249
+ pre.appendChild(code);
4250
+ range.deleteContents();
4251
+ range.insertNode(pre);
4252
+ ensureParagraphAfter(pre);
4253
+ placeCaretAtEnd(code);
4254
+ handleInput();
4255
+ };
4256
+ const insertTextAtCaret = (text) => {
4257
+ const sel = window.getSelection();
4258
+ if (!sel || sel.rangeCount === 0) return;
4259
+ const range = sel.getRangeAt(0);
4260
+ range.deleteContents();
4261
+ const node = document.createTextNode(text);
4262
+ range.insertNode(node);
4263
+ range.setStartAfter(node);
4264
+ range.collapse(true);
4265
+ sel.removeAllRanges();
4266
+ sel.addRange(range);
4267
+ handleInput();
4268
+ };
4269
+ const ensureParagraphAfter = (node) => {
4270
+ const next = node.nextElementSibling;
4271
+ if (next && next.tagName === "P") return;
4272
+ const p = document.createElement("p");
4273
+ p.innerHTML = "<br>";
4274
+ node.after(p);
4275
+ };
4276
+ const placeCaretAtEnd = (node) => {
4277
+ const sel = window.getSelection();
4278
+ if (!sel) return;
4279
+ const r2 = document.createRange();
4280
+ r2.selectNodeContents(node);
4281
+ r2.collapse(false);
4282
+ sel.removeAllRanges();
4283
+ sel.addRange(r2);
4284
+ editorRef.current?.focus();
4285
+ };
4039
4286
  const insertDivider = () => {
4040
4287
  exec("insertHorizontalRule");
4041
4288
  const el = editorRef.current;
@@ -4082,7 +4329,9 @@ var Editor = (props) => {
4082
4329
  const range = sel.getRangeAt(0);
4083
4330
  slashStartRangeRef.current = range.cloneRange();
4084
4331
  const rect = range.getBoundingClientRect();
4085
- const editorRect = editorRef.current.getBoundingClientRect();
4332
+ const editorEl = editorRef.current;
4333
+ if (!editorEl) return;
4334
+ const editorRect = editorEl.getBoundingClientRect();
4086
4335
  setSlashPos({
4087
4336
  top: rect.bottom - editorRect.top + 4,
4088
4337
  left: rect.left - editorRect.left
@@ -4097,7 +4346,7 @@ var Editor = (props) => {
4097
4346
  setSlashIdx(0);
4098
4347
  slashStartRangeRef.current = null;
4099
4348
  };
4100
- const filteredSlashItems = React21.useMemo(() => {
4349
+ const filteredSlashItems = React22.useMemo(() => {
4101
4350
  if (!slashFilter) return SLASH_ITEMS;
4102
4351
  const f = slashFilter.toLowerCase();
4103
4352
  return SLASH_ITEMS.filter((it) => it.label.toLowerCase().includes(f) || it.key.includes(f));
@@ -4140,7 +4389,7 @@ var Editor = (props) => {
4140
4389
  setBlock("blockquote");
4141
4390
  break;
4142
4391
  case "code-block":
4143
- setBlock("pre");
4392
+ insertCodeBlock();
4144
4393
  break;
4145
4394
  case "divider":
4146
4395
  insertDivider();
@@ -4158,7 +4407,9 @@ var Editor = (props) => {
4158
4407
  if (!sel || sel.rangeCount === 0) return;
4159
4408
  const range = sel.getRangeAt(0);
4160
4409
  const rect = range.getBoundingClientRect();
4161
- const editorRect = editorRef.current.getBoundingClientRect();
4410
+ const editorEl2 = editorRef.current;
4411
+ if (!editorEl2) return;
4412
+ const editorRect = editorEl2.getBoundingClientRect();
4162
4413
  setLinkPos({
4163
4414
  top: rect.bottom - editorRect.top + 4,
4164
4415
  left: rect.left - editorRect.left
@@ -4191,13 +4442,13 @@ var Editor = (props) => {
4191
4442
  if (node.nodeType !== Node.TEXT_NODE) return false;
4192
4443
  const text = (node.textContent || "").slice(0, range.startOffset);
4193
4444
  const patterns = [
4194
- [/^###\s$/, () => setBlock("h3")],
4195
- [/^##\s$/, () => setBlock("h2")],
4196
- [/^#\s$/, () => setBlock("h1")],
4197
- [/^-\s$/, () => exec("insertUnorderedList")],
4198
- [/^\*\s$/, () => exec("insertUnorderedList")],
4199
- [/^1\.\s$/, () => exec("insertOrderedList")],
4200
- [/^>\s$/, () => setBlock("blockquote")]
4445
+ [/^###$/, () => setBlock("h3")],
4446
+ [/^##$/, () => setBlock("h2")],
4447
+ [/^#$/, () => setBlock("h1")],
4448
+ [/^-$/, () => exec("insertUnorderedList")],
4449
+ [/^\*$/, () => exec("insertUnorderedList")],
4450
+ [/^1\.$/, () => exec("insertOrderedList")],
4451
+ [/^>$/, () => setBlock("blockquote")]
4201
4452
  ];
4202
4453
  for (const [re, fn] of patterns) {
4203
4454
  if (re.test(text)) {
@@ -4217,7 +4468,9 @@ var Editor = (props) => {
4217
4468
  if (composingRef.current) return;
4218
4469
  const el = editorRef.current;
4219
4470
  if (!el) return;
4220
- onChange?.(el.innerHTML);
4471
+ const html = el.innerHTML;
4472
+ lastEmittedRef.current = html;
4473
+ onChange?.(html);
4221
4474
  updateEmpty();
4222
4475
  updateActiveFormats();
4223
4476
  if (slashOpen) {
@@ -4245,6 +4498,31 @@ var Editor = (props) => {
4245
4498
  };
4246
4499
  const handleKeyDown = (e) => {
4247
4500
  if (readOnly) return;
4501
+ if (composingRef.current || e.nativeEvent.isComposing || e.keyCode === 229) return;
4502
+ const pre = closestPre();
4503
+ if (pre && !slashOpen) {
4504
+ if (e.key === "Enter" && !e.shiftKey) {
4505
+ const text = pre.textContent || "";
4506
+ if (text.endsWith("\n\n")) {
4507
+ e.preventDefault();
4508
+ const code = pre.querySelector("code") ?? pre;
4509
+ code.textContent = text.replace(/\n\n$/, "");
4510
+ ensureParagraphAfter(pre);
4511
+ const next = pre.nextElementSibling;
4512
+ if (next) placeCaretAtEnd(next);
4513
+ handleInput();
4514
+ return;
4515
+ }
4516
+ e.preventDefault();
4517
+ insertTextAtCaret("\n");
4518
+ return;
4519
+ }
4520
+ if (e.key === "Tab") {
4521
+ e.preventDefault();
4522
+ insertTextAtCaret(" ");
4523
+ return;
4524
+ }
4525
+ }
4248
4526
  if (slashOpen) {
4249
4527
  if (e.key === "ArrowDown") {
4250
4528
  e.preventDefault();
@@ -4291,6 +4569,7 @@ var Editor = (props) => {
4291
4569
  return;
4292
4570
  }
4293
4571
  }
4572
+ if (pre) return;
4294
4573
  if (enableSlashCommand && e.key === "/") {
4295
4574
  setTimeout(openSlashMenu, 0);
4296
4575
  }
@@ -4303,8 +4582,12 @@ var Editor = (props) => {
4303
4582
  const handlePaste = (e) => {
4304
4583
  if (readOnly) return;
4305
4584
  e.preventDefault();
4306
- const html = e.clipboardData.getData("text/html");
4307
4585
  const text = e.clipboardData.getData("text/plain");
4586
+ if (closestPre()) {
4587
+ insertTextAtCaret(text);
4588
+ return;
4589
+ }
4590
+ const html = e.clipboardData.getData("text/html");
4308
4591
  const clean = html ? sanitizeHtml(html) : escapeHtml(text);
4309
4592
  document.execCommand("insertHTML", false, clean);
4310
4593
  handleInput();
@@ -4328,6 +4611,7 @@ var Editor = (props) => {
4328
4611
  updateActiveFormats();
4329
4612
  };
4330
4613
  const onToolbarAction = (item) => {
4614
+ if (closestPre() && item !== "code-block") return;
4331
4615
  switch (item) {
4332
4616
  case "bold":
4333
4617
  exec("bold");
@@ -4369,7 +4653,7 @@ var Editor = (props) => {
4369
4653
  setBlock("blockquote");
4370
4654
  break;
4371
4655
  case "code-block":
4372
- setBlock("pre");
4656
+ insertCodeBlock();
4373
4657
  break;
4374
4658
  case "link":
4375
4659
  openLinkEditor();
@@ -4399,6 +4683,10 @@ var Editor = (props) => {
4399
4683
  ref: editorRef,
4400
4684
  contentEditable: !readOnly,
4401
4685
  suppressContentEditableWarning: true,
4686
+ role: "textbox",
4687
+ "aria-multiline": "true",
4688
+ "aria-readonly": readOnly || void 0,
4689
+ "aria-label": placeholder,
4402
4690
  className: "lib-xplat-editor__editable",
4403
4691
  onInput: handleInput,
4404
4692
  onKeyDown: handleKeyDown,
@@ -4490,7 +4778,7 @@ var EditorToolbar = ({ items, active, onAction }) => {
4490
4778
  )) });
4491
4779
  };
4492
4780
  var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
4493
- React21.useEffect(() => {
4781
+ React22.useEffect(() => {
4494
4782
  const handleClickOutside = (e) => {
4495
4783
  const target = e.target;
4496
4784
  const menu = document.querySelector(".lib-xplat-editor__slash-menu");
@@ -4524,8 +4812,8 @@ var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
4524
4812
  );
4525
4813
  };
4526
4814
  var LinkPopover = ({ position, value, onChange, onConfirm, onClose }) => {
4527
- const inputRef = React21.useRef(null);
4528
- React21.useEffect(() => {
4815
+ const inputRef = React22.useRef(null);
4816
+ React22.useEffect(() => {
4529
4817
  inputRef.current?.focus();
4530
4818
  }, []);
4531
4819
  return /* @__PURE__ */ jsxs207(
@@ -4583,7 +4871,7 @@ EmptyState.displayName = "EmptyState";
4583
4871
  var EmptyState_default = EmptyState;
4584
4872
 
4585
4873
  // src/components/FileUpload/FileUpload.tsx
4586
- import React22 from "react";
4874
+ import React23 from "react";
4587
4875
  import { jsx as jsx325, jsxs as jsxs209 } from "react/jsx-runtime";
4588
4876
  var FileUpload = (props) => {
4589
4877
  const {
@@ -4595,8 +4883,8 @@ var FileUpload = (props) => {
4595
4883
  description,
4596
4884
  validations
4597
4885
  } = props;
4598
- const [isDragOver, setIsDragOver] = React22.useState(false);
4599
- const inputRef = React22.useRef(null);
4886
+ const [isDragOver, setIsDragOver] = React23.useState(false);
4887
+ const inputRef = React23.useRef(null);
4600
4888
  const handleFiles = (fileList) => {
4601
4889
  let files = Array.from(fileList);
4602
4890
  if (maxSize) {
@@ -4658,10 +4946,10 @@ FileUpload.displayName = "FileUpload";
4658
4946
  var FileUpload_default = FileUpload;
4659
4947
 
4660
4948
  // src/components/HtmlTypeWriter/HtmlTypeWriter.tsx
4661
- import React24 from "react";
4949
+ import React25 from "react";
4662
4950
 
4663
4951
  // src/components/HtmlTypeWriter/utils.ts
4664
- import React23 from "react";
4952
+ import React24 from "react";
4665
4953
  var voidTags = /* @__PURE__ */ new Set([
4666
4954
  "br",
4667
4955
  "img",
@@ -4729,15 +5017,15 @@ var convertNodeToReactWithRange = (node, typedLen, rangeMap) => {
4729
5017
  props[attr.name] = attr.value;
4730
5018
  });
4731
5019
  if (voidTags.has(tag)) {
4732
- return React23.createElement(tag, props);
5020
+ return React24.createElement(tag, props);
4733
5021
  }
4734
5022
  const children = Array.from(element.childNodes).map((child) => convertNodeToReactWithRange(child, typedLen, rangeMap)).filter((n) => n != null);
4735
- return React23.createElement(tag, props, ...children);
5023
+ return React24.createElement(tag, props, ...children);
4736
5024
  };
4737
5025
  var htmlToReactProgressive = (root, typedLen, rangeMap) => {
4738
5026
  const nodes = Array.from(root.childNodes).map((child, idx) => {
4739
5027
  const node = convertNodeToReactWithRange(child, typedLen, rangeMap);
4740
- return node == null ? null : React23.createElement(React23.Fragment, { key: idx }, node);
5028
+ return node == null ? null : React24.createElement(React24.Fragment, { key: idx }, node);
4741
5029
  }).filter(Boolean);
4742
5030
  return nodes.length === 0 ? null : nodes;
4743
5031
  };
@@ -4750,20 +5038,20 @@ var HtmlTypeWriter = ({
4750
5038
  onDone,
4751
5039
  onChange
4752
5040
  }) => {
4753
- const [typedLen, setTypedLen] = React24.useState(0);
4754
- const doneCalledRef = React24.useRef(false);
4755
- const { doc, rangeMap, totalLength } = React24.useMemo(() => {
5041
+ const [typedLen, setTypedLen] = React25.useState(0);
5042
+ const doneCalledRef = React25.useRef(false);
5043
+ const { doc, rangeMap, totalLength } = React25.useMemo(() => {
4756
5044
  if (typeof window === "undefined") return { doc: null, rangeMap: /* @__PURE__ */ new Map(), totalLength: 0 };
4757
5045
  const decoded = decodeHtmlEntities(html);
4758
5046
  const doc2 = new DOMParser().parseFromString(decoded, "text/html");
4759
5047
  const { rangeMap: rangeMap2, totalLength: totalLength2 } = buildRangeMap(doc2.body);
4760
5048
  return { doc: doc2, rangeMap: rangeMap2, totalLength: totalLength2 };
4761
5049
  }, [html]);
4762
- React24.useEffect(() => {
5050
+ React25.useEffect(() => {
4763
5051
  setTypedLen(0);
4764
5052
  doneCalledRef.current = false;
4765
5053
  }, [html]);
4766
- React24.useEffect(() => {
5054
+ React25.useEffect(() => {
4767
5055
  if (!totalLength) return;
4768
5056
  if (typedLen >= totalLength) return;
4769
5057
  const timer = window.setInterval(() => {
@@ -4771,18 +5059,18 @@ var HtmlTypeWriter = ({
4771
5059
  }, duration);
4772
5060
  return () => window.clearInterval(timer);
4773
5061
  }, [typedLen, totalLength, duration]);
4774
- React24.useEffect(() => {
5062
+ React25.useEffect(() => {
4775
5063
  if (typedLen > 0 && typedLen < totalLength) {
4776
5064
  onChange?.();
4777
5065
  }
4778
5066
  }, [typedLen, totalLength, onChange]);
4779
- React24.useEffect(() => {
5067
+ React25.useEffect(() => {
4780
5068
  if (typedLen === totalLength && totalLength > 0 && !doneCalledRef.current) {
4781
5069
  doneCalledRef.current = true;
4782
5070
  onDone?.();
4783
5071
  }
4784
5072
  }, [typedLen, totalLength, onDone]);
4785
- const parsed = React24.useMemo(
5073
+ const parsed = React25.useMemo(
4786
5074
  () => doc ? htmlToReactProgressive(doc.body, typedLen, rangeMap) : null,
4787
5075
  [doc, typedLen, rangeMap]
4788
5076
  );
@@ -4792,12 +5080,12 @@ HtmlTypeWriter.displayName = "HtmlTypeWriter";
4792
5080
  var HtmlTypeWriter_default = HtmlTypeWriter;
4793
5081
 
4794
5082
  // src/components/ImageSelector/ImageSelector.tsx
4795
- import React25 from "react";
5083
+ import React26 from "react";
4796
5084
  import { jsx as jsx327, jsxs as jsxs210 } from "react/jsx-runtime";
4797
5085
  var ImageSelector = (props) => {
4798
5086
  const { value, label, onChange, validations } = props;
4799
- const [previewUrl, setPreviewUrl] = React25.useState();
4800
- React25.useEffect(() => {
5087
+ const [previewUrl, setPreviewUrl] = React26.useState();
5088
+ React26.useEffect(() => {
4801
5089
  if (!value) {
4802
5090
  setPreviewUrl(void 0);
4803
5091
  return;
@@ -4806,7 +5094,7 @@ var ImageSelector = (props) => {
4806
5094
  setPreviewUrl(url);
4807
5095
  return () => URL.revokeObjectURL(url);
4808
5096
  }, [value]);
4809
- const inputRef = React25.useRef(null);
5097
+ const inputRef = React26.useRef(null);
4810
5098
  const handleFileChange = (e) => {
4811
5099
  const selectedFile = e.target.files?.[0];
4812
5100
  if (selectedFile) {
@@ -4989,17 +5277,21 @@ Pagination.displayName = "Pagination";
4989
5277
  var Pagination_default = Pagination;
4990
5278
 
4991
5279
  // src/components/PopOver/PopOver.tsx
4992
- import React26 from "react";
5280
+ import React27 from "react";
4993
5281
  import { jsx as jsx332, jsxs as jsxs213 } from "react/jsx-runtime";
4994
5282
  var PopOver = (props) => {
4995
5283
  const { children, isOpen, onClose, PopOverEl } = props;
4996
- const popRef = React26.useRef(null);
4997
- const triggerRef = React26.useRef(null);
4998
- const [localOpen, setLocalOpen] = React26.useState(false);
4999
- const [eventTrigger, setEventTrigger] = React26.useState(false);
5284
+ const popRef = React27.useRef(null);
5285
+ const triggerRef = React27.useRef(null);
5286
+ const [localOpen, setLocalOpen] = React27.useState(false);
5287
+ const [eventTrigger, setEventTrigger] = React27.useState(false);
5000
5288
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
5289
+ useEscapeKey(isOpen, () => {
5290
+ onClose();
5291
+ triggerRef.current?.focus({ preventScroll: true });
5292
+ });
5001
5293
  const position = useAutoPosition_default(triggerRef, popRef, localOpen);
5002
- React26.useEffect(() => {
5294
+ React27.useEffect(() => {
5003
5295
  if (isOpen) {
5004
5296
  setLocalOpen(isOpen);
5005
5297
  setTimeout(() => {
@@ -5084,12 +5376,12 @@ Progress.displayName = "Progress";
5084
5376
  var Progress_default = Progress;
5085
5377
 
5086
5378
  // src/components/Radio/RadioGroupContext.tsx
5087
- import React27 from "react";
5088
- var RadioGroupContext = React27.createContext(
5379
+ import React28 from "react";
5380
+ var RadioGroupContext = React28.createContext(
5089
5381
  null
5090
5382
  );
5091
5383
  var useRadioGroupContext = () => {
5092
- return React27.useContext(RadioGroupContext);
5384
+ return React28.useContext(RadioGroupContext);
5093
5385
  };
5094
5386
  var RadioGroupContext_default = RadioGroupContext;
5095
5387
 
@@ -5165,19 +5457,19 @@ RadioGroup.displayName = "RadioGroup";
5165
5457
  var RadioGroup_default = RadioGroup;
5166
5458
 
5167
5459
  // src/components/Select/Select.tsx
5168
- import React30 from "react";
5460
+ import React31 from "react";
5169
5461
 
5170
5462
  // src/components/Select/context.ts
5171
- import React28 from "react";
5172
- var SelectContext = React28.createContext(null);
5463
+ import React29 from "react";
5464
+ var SelectContext = React29.createContext(null);
5173
5465
  var context_default = SelectContext;
5174
5466
 
5175
5467
  // src/components/Select/SelectItem.tsx
5176
- import React29 from "react";
5468
+ import React30 from "react";
5177
5469
  import { jsx as jsx336 } from "react/jsx-runtime";
5178
5470
  var SelectItem = (props) => {
5179
5471
  const { children, value, onClick, disabled = false } = props;
5180
- const ctx = React29.useContext(context_default);
5472
+ const ctx = React30.useContext(context_default);
5181
5473
  const handleClick = (e) => {
5182
5474
  e.preventDefault();
5183
5475
  e.stopPropagation();
@@ -5217,32 +5509,37 @@ var SelectRoot = (props) => {
5217
5509
  onChange,
5218
5510
  children,
5219
5511
  disabled = false,
5512
+ searchable = false,
5513
+ searchPlaceholder = "\uAC80\uC0C9",
5220
5514
  error = false,
5221
5515
  validations,
5516
+ label,
5517
+ required,
5222
5518
  size = "md"
5223
5519
  } = props;
5224
- const itemChildren = React30.Children.toArray(children).filter(
5225
- (child) => React30.isValidElement(child) && child.type === SelectItem_default
5520
+ const fieldId = React31.useId();
5521
+ const itemChildren = React31.Children.toArray(children).filter(
5522
+ (child) => React31.isValidElement(child) && child.type === SelectItem_default
5226
5523
  );
5227
5524
  const isControlled = valueProp !== void 0;
5228
- const [isOpen, setOpen] = React30.useState(false);
5229
- const [uncontrolledLabel, setUncontrolledLabel] = React30.useState(null);
5230
- const [uncontrolledValue, setUncontrolledValue] = React30.useState(void 0);
5231
- const controlledLabel = React30.useMemo(() => {
5525
+ const [isOpen, setOpen] = React31.useState(false);
5526
+ const [uncontrolledLabel, setUncontrolledLabel] = React31.useState(null);
5527
+ const [uncontrolledValue, setUncontrolledValue] = React31.useState(void 0);
5528
+ const controlledLabel = React31.useMemo(() => {
5232
5529
  if (!isControlled) return null;
5233
5530
  const match = itemChildren.find((child) => child.props.value === valueProp);
5234
5531
  return match ? match.props.children : null;
5235
5532
  }, [isControlled, valueProp, itemChildren]);
5236
5533
  const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
5237
5534
  const selectedValue = isControlled ? valueProp : uncontrolledValue;
5238
- const triggerRef = React30.useRef(null);
5239
- const contentRef = React30.useRef(null);
5240
- const [mounted, setMounted] = React30.useState(false);
5241
- const [visible, setVisible] = React30.useState(false);
5242
- React30.useEffect(() => {
5535
+ const triggerRef = React31.useRef(null);
5536
+ const contentRef = React31.useRef(null);
5537
+ const [mounted, setMounted] = React31.useState(false);
5538
+ const [visible, setVisible] = React31.useState(false);
5539
+ React31.useEffect(() => {
5243
5540
  if (disabled && isOpen) setOpen(false);
5244
5541
  }, [disabled, isOpen]);
5245
- React30.useEffect(() => {
5542
+ React31.useEffect(() => {
5246
5543
  if (isOpen) {
5247
5544
  setMounted(true);
5248
5545
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -5252,22 +5549,42 @@ var SelectRoot = (props) => {
5252
5549
  const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS3);
5253
5550
  return () => clearTimeout(t);
5254
5551
  }, [isOpen]);
5255
- const open = React30.useCallback(() => setOpen(true), []);
5256
- const close = React30.useCallback(() => setOpen(false), []);
5257
- const toggle = React30.useCallback(() => setOpen((prev) => !prev), []);
5552
+ const [query, setQuery] = React31.useState("");
5553
+ const textOf = (node) => {
5554
+ if (node === null || node === void 0 || typeof node === "boolean") return "";
5555
+ if (typeof node === "string" || typeof node === "number") return String(node);
5556
+ if (Array.isArray(node)) return node.map(textOf).join("");
5557
+ if (React31.isValidElement(node)) return textOf(node.props.children);
5558
+ return "";
5559
+ };
5560
+ const visibleItems = React31.useMemo(() => {
5561
+ if (!searchable || !query.trim()) return itemChildren;
5562
+ const q = query.trim().toLowerCase();
5563
+ return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
5564
+ }, [searchable, query, itemChildren]);
5565
+ const open = React31.useCallback(() => setOpen(true), []);
5566
+ const close = React31.useCallback(() => {
5567
+ setOpen(false);
5568
+ setQuery("");
5569
+ }, []);
5570
+ const toggle = React31.useCallback(() => setOpen((prev) => !prev), []);
5258
5571
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
5572
+ useEscapeKey(isOpen, () => {
5573
+ close();
5574
+ triggerRef.current?.focus({ preventScroll: true });
5575
+ });
5259
5576
  const position = useAutoPosition_default(triggerRef, contentRef, mounted);
5260
- const setSelected = React30.useCallback(
5261
- (label, itemValue) => {
5577
+ const setSelected = React31.useCallback(
5578
+ (label2, itemValue) => {
5262
5579
  if (!isControlled) {
5263
- setUncontrolledLabel(label);
5580
+ setUncontrolledLabel(label2);
5264
5581
  setUncontrolledValue(itemValue);
5265
5582
  }
5266
- onChange?.(itemValue, label);
5583
+ onChange?.(itemValue, label2);
5267
5584
  },
5268
5585
  [isControlled, onChange]
5269
5586
  );
5270
- const ctxValue = React30.useMemo(
5587
+ const ctxValue = React31.useMemo(
5271
5588
  () => ({
5272
5589
  isOpen,
5273
5590
  mounted,
@@ -5303,6 +5620,7 @@ var SelectRoot = (props) => {
5303
5620
  /* @__PURE__ */ jsxs216(
5304
5621
  "div",
5305
5622
  {
5623
+ id: fieldId,
5306
5624
  ref: triggerRef,
5307
5625
  className: clsx_default(
5308
5626
  "select-trigger",
@@ -5345,20 +5663,33 @@ var SelectRoot = (props) => {
5345
5663
  ]
5346
5664
  }
5347
5665
  ),
5348
- mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsx337(
5666
+ mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsxs216(
5349
5667
  "div",
5350
5668
  {
5351
5669
  className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
5352
5670
  ref: contentRef,
5353
5671
  style: { ...position.position, width: triggerRef.current?.offsetWidth },
5354
5672
  role: "listbox",
5355
- children: /* @__PURE__ */ jsx337(context_default.Provider, { value: ctxValue, children: itemChildren })
5673
+ children: [
5674
+ searchable && /* @__PURE__ */ jsx337("div", { className: "select-search", children: /* @__PURE__ */ jsx337(
5675
+ "input",
5676
+ {
5677
+ type: "text",
5678
+ value: query,
5679
+ placeholder: searchPlaceholder,
5680
+ onChange: (e) => setQuery(e.target.value),
5681
+ autoFocus: true,
5682
+ "aria-label": searchPlaceholder
5683
+ }
5684
+ ) }),
5685
+ /* @__PURE__ */ jsx337(context_default.Provider, { value: ctxValue, children: visibleItems.length > 0 ? visibleItems : /* @__PURE__ */ jsx337("div", { className: "select-empty", children: "\uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" }) })
5686
+ ]
5356
5687
  }
5357
5688
  ) })
5358
5689
  ]
5359
5690
  }
5360
5691
  ) });
5361
- return /* @__PURE__ */ jsx337(Field, { validations, children: control });
5692
+ return /* @__PURE__ */ jsx337(Field, { validations, label, required, htmlFor: fieldId, children: control });
5362
5693
  };
5363
5694
  SelectRoot.displayName = "Select";
5364
5695
  var Select = Object.assign(SelectRoot, {
@@ -5438,8 +5769,44 @@ var Spinner = (props) => {
5438
5769
  Spinner.displayName = "Spinner";
5439
5770
  var Spinner_default = Spinner;
5440
5771
 
5441
- // src/components/Steps/Steps.tsx
5772
+ // src/components/Stat/Stat.tsx
5442
5773
  import { jsx as jsx340, jsxs as jsxs218 } from "react/jsx-runtime";
5774
+ var ARROW = {
5775
+ up: "\u25B2",
5776
+ down: "\u25BC",
5777
+ flat: "\u2014"
5778
+ };
5779
+ var Stat = (props) => {
5780
+ const {
5781
+ label,
5782
+ value,
5783
+ unit,
5784
+ description,
5785
+ trend,
5786
+ icon,
5787
+ size = "md",
5788
+ type = "primary"
5789
+ } = props;
5790
+ const statusType = normalizeStatus(type);
5791
+ return /* @__PURE__ */ jsxs218("div", { className: clsx_default("lib-xplat-stat", size, statusType), children: [
5792
+ /* @__PURE__ */ jsx340("div", { className: "stat-label", children: label }),
5793
+ /* @__PURE__ */ jsxs218("div", { className: "stat-value-row", children: [
5794
+ icon && /* @__PURE__ */ jsx340("span", { className: "stat-icon", children: icon }),
5795
+ /* @__PURE__ */ jsx340("span", { className: "stat-value", children: value }),
5796
+ unit && /* @__PURE__ */ jsx340("span", { className: "stat-unit", children: unit }),
5797
+ trend && /* @__PURE__ */ jsxs218("span", { className: clsx_default("stat-trend", trend.direction), children: [
5798
+ /* @__PURE__ */ jsx340("span", { "aria-hidden": "true", children: ARROW[trend.direction] }),
5799
+ trend.value
5800
+ ] })
5801
+ ] }),
5802
+ description && /* @__PURE__ */ jsx340("div", { className: "stat-description", children: description })
5803
+ ] });
5804
+ };
5805
+ Stat.displayName = "Stat";
5806
+ var Stat_default = Stat;
5807
+
5808
+ // src/components/Steps/Steps.tsx
5809
+ import { jsx as jsx341, jsxs as jsxs219 } from "react/jsx-runtime";
5443
5810
  var Steps = (props) => {
5444
5811
  const {
5445
5812
  items,
@@ -5447,13 +5814,13 @@ var Steps = (props) => {
5447
5814
  type = "primary"
5448
5815
  } = props;
5449
5816
  const statusType = normalizeStatus(type);
5450
- return /* @__PURE__ */ jsx340("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
5817
+ return /* @__PURE__ */ jsx341("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
5451
5818
  const status = index < current ? "completed" : index === current ? "active" : "pending";
5452
- return /* @__PURE__ */ jsxs218("div", { className: clsx_default("step-item", status), children: [
5453
- /* @__PURE__ */ jsx340("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ jsx340(CheckIcon_default, {}) : /* @__PURE__ */ jsx340("span", { children: index + 1 }) }),
5454
- /* @__PURE__ */ jsxs218("div", { className: "step-content", children: [
5455
- /* @__PURE__ */ jsx340("span", { className: "step-title", children: item.title }),
5456
- item.description && /* @__PURE__ */ jsx340("span", { className: "step-description", children: item.description })
5819
+ return /* @__PURE__ */ jsxs219("div", { className: clsx_default("step-item", status), children: [
5820
+ /* @__PURE__ */ jsx341("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ jsx341(CheckIcon_default, {}) : /* @__PURE__ */ jsx341("span", { children: index + 1 }) }),
5821
+ /* @__PURE__ */ jsxs219("div", { className: "step-content", children: [
5822
+ /* @__PURE__ */ jsx341("span", { className: "step-title", children: item.title }),
5823
+ item.description && /* @__PURE__ */ jsx341("span", { className: "step-description", children: item.description })
5457
5824
  ] })
5458
5825
  ] }, index);
5459
5826
  }) });
@@ -5462,8 +5829,8 @@ Steps.displayName = "Steps";
5462
5829
  var Steps_default = Steps;
5463
5830
 
5464
5831
  // src/components/Swiper/Swiper.tsx
5465
- import React31 from "react";
5466
- import { jsx as jsx341, jsxs as jsxs219 } from "react/jsx-runtime";
5832
+ import React32 from "react";
5833
+ import { jsx as jsx342, jsxs as jsxs220 } from "react/jsx-runtime";
5467
5834
  var Swiper = (props) => {
5468
5835
  const {
5469
5836
  auto = false,
@@ -5487,26 +5854,26 @@ var Swiper = (props) => {
5487
5854
  const maxIndex = Math.max(0, totalSlides - viewItemCount);
5488
5855
  const useLoop = loop && canSlide;
5489
5856
  const cloneCount = useLoop ? totalSlides : 0;
5490
- const extendedItems = React31.useMemo(() => {
5857
+ const extendedItems = React32.useMemo(() => {
5491
5858
  if (!useLoop) return items;
5492
5859
  return [...items, ...items, ...items];
5493
5860
  }, [items, useLoop]);
5494
5861
  const initialIdx = Math.max(0, Math.min(indexProp ?? 0, maxIndex));
5495
- const [innerIndex, setInnerIndex] = React31.useState(
5862
+ const [innerIndex, setInnerIndex] = React32.useState(
5496
5863
  useLoop ? cloneCount + initialIdx : initialIdx
5497
5864
  );
5498
- const [isDragging, setIsDragging] = React31.useState(false);
5499
- const [dragOffset, setDragOffset] = React31.useState(0);
5500
- const [animated, setAnimated] = React31.useState(false);
5501
- const [containerWidth, setContainerWidth] = React31.useState(0);
5502
- const containerRef = React31.useRef(null);
5503
- const startXRef = React31.useRef(0);
5504
- const startTimeRef = React31.useRef(0);
5505
- const autoplayTimerRef = React31.useRef(null);
5506
- const resumeTimeoutRef = React31.useRef(null);
5507
- const [paused, setPaused] = React31.useState(false);
5508
- const initializedRef = React31.useRef(false);
5509
- React31.useEffect(() => {
5865
+ const [isDragging, setIsDragging] = React32.useState(false);
5866
+ const [dragOffset, setDragOffset] = React32.useState(0);
5867
+ const [animated, setAnimated] = React32.useState(false);
5868
+ const [containerWidth, setContainerWidth] = React32.useState(0);
5869
+ const containerRef = React32.useRef(null);
5870
+ const startXRef = React32.useRef(0);
5871
+ const startTimeRef = React32.useRef(0);
5872
+ const autoplayTimerRef = React32.useRef(null);
5873
+ const resumeTimeoutRef = React32.useRef(null);
5874
+ const [paused, setPaused] = React32.useState(false);
5875
+ const initializedRef = React32.useRef(false);
5876
+ React32.useEffect(() => {
5510
5877
  const el = containerRef.current;
5511
5878
  if (!el) return;
5512
5879
  const ro = new ResizeObserver((entries) => {
@@ -5529,7 +5896,7 @@ var Swiper = (props) => {
5529
5896
  return ((inner - cloneCount) % totalSlides + totalSlides) % totalSlides;
5530
5897
  };
5531
5898
  const realIndex = getRealIndex(innerIndex);
5532
- const moveToInner = React31.useCallback(
5899
+ const moveToInner = React32.useCallback(
5533
5900
  (idx, withAnim = true) => {
5534
5901
  if (!useLoop) {
5535
5902
  setAnimated(withAnim);
@@ -5557,7 +5924,7 @@ var Swiper = (props) => {
5557
5924
  },
5558
5925
  [useLoop, cloneCount, totalSlides]
5559
5926
  );
5560
- const handleTransitionEnd = React31.useCallback(() => {
5927
+ const handleTransitionEnd = React32.useCallback(() => {
5561
5928
  if (!useLoop) return;
5562
5929
  const real = getRealIndex(innerIndex);
5563
5930
  const canonical = cloneCount + real;
@@ -5567,7 +5934,7 @@ var Swiper = (props) => {
5567
5934
  }
5568
5935
  onChange?.(Math.min(real, maxIndex));
5569
5936
  }, [useLoop, innerIndex, cloneCount, totalSlides, maxIndex, onChange]);
5570
- const slideTo = React31.useCallback(
5937
+ const slideTo = React32.useCallback(
5571
5938
  (logicalIndex) => {
5572
5939
  if (!canSlide) return;
5573
5940
  const clamped = useLoop ? logicalIndex : Math.max(0, Math.min(logicalIndex, maxIndex));
@@ -5577,7 +5944,7 @@ var Swiper = (props) => {
5577
5944
  },
5578
5945
  [canSlide, useLoop, cloneCount, maxIndex, onChange, moveToInner]
5579
5946
  );
5580
- const slideNext = React31.useCallback(() => {
5947
+ const slideNext = React32.useCallback(() => {
5581
5948
  if (!canSlide) return;
5582
5949
  const nextInner = innerIndex + slideBy;
5583
5950
  if (useLoop) {
@@ -5586,7 +5953,7 @@ var Swiper = (props) => {
5586
5953
  moveToInner(Math.min(nextInner, maxIndex), true);
5587
5954
  }
5588
5955
  }, [canSlide, useLoop, innerIndex, slideBy, maxIndex, moveToInner]);
5589
- const slidePrev = React31.useCallback(() => {
5956
+ const slidePrev = React32.useCallback(() => {
5590
5957
  if (!canSlide) return;
5591
5958
  const prevInner = innerIndex - slideBy;
5592
5959
  if (useLoop) {
@@ -5595,7 +5962,7 @@ var Swiper = (props) => {
5595
5962
  moveToInner(Math.max(prevInner, 0), true);
5596
5963
  }
5597
5964
  }, [canSlide, useLoop, innerIndex, slideBy, moveToInner]);
5598
- React31.useEffect(() => {
5965
+ React32.useEffect(() => {
5599
5966
  if (indexProp === void 0) return;
5600
5967
  const clamped = Math.max(0, Math.min(indexProp, maxIndex));
5601
5968
  const target = useLoop ? cloneCount + clamped : clamped;
@@ -5603,12 +5970,12 @@ var Swiper = (props) => {
5603
5970
  moveToInner(target, true);
5604
5971
  }
5605
5972
  }, [indexProp]);
5606
- React31.useImperativeHandle(swiperRef, () => ({
5973
+ React32.useImperativeHandle(swiperRef, () => ({
5607
5974
  slidePrev,
5608
5975
  slideNext,
5609
5976
  slideTo
5610
5977
  }));
5611
- React31.useEffect(() => {
5978
+ React32.useEffect(() => {
5612
5979
  if (!auto || !canSlide || paused) return;
5613
5980
  autoplayTimerRef.current = setInterval(slideNext, autoplayDelay);
5614
5981
  return () => {
@@ -5634,7 +6001,7 @@ var Swiper = (props) => {
5634
6001
  resumeTimeoutRef.current = null;
5635
6002
  }, pauseOnInteraction);
5636
6003
  };
5637
- React31.useEffect(() => {
6004
+ React32.useEffect(() => {
5638
6005
  return () => {
5639
6006
  if (resumeTimeoutRef.current) clearTimeout(resumeTimeoutRef.current);
5640
6007
  };
@@ -5652,7 +6019,7 @@ var Swiper = (props) => {
5652
6019
  startXRef.current = getClientX(e);
5653
6020
  startTimeRef.current = Date.now();
5654
6021
  };
5655
- React31.useEffect(() => {
6022
+ React32.useEffect(() => {
5656
6023
  if (!isDragging) return;
5657
6024
  const handleMove = (e) => {
5658
6025
  setDragOffset(getClientX(e) - startXRef.current);
@@ -5691,8 +6058,8 @@ var Swiper = (props) => {
5691
6058
  }, [isDragging, dragOffset, innerIndex, useLoop, maxIndex, slideStep, moveToInner]);
5692
6059
  const slideWidthPercent = 100 / viewItemCount;
5693
6060
  const gapAdjust = spaceBetween * (viewItemCount - 1) / viewItemCount;
5694
- const slideElements = React31.useMemo(
5695
- () => extendedItems.map((item, idx) => /* @__PURE__ */ jsx341(
6061
+ const slideElements = React32.useMemo(
6062
+ () => extendedItems.map((item, idx) => /* @__PURE__ */ jsx342(
5696
6063
  "div",
5697
6064
  {
5698
6065
  className: "lib-xplat-swiper__slide",
@@ -5711,15 +6078,15 @@ var Swiper = (props) => {
5711
6078
  Math.floor(realIndex / slideBy),
5712
6079
  totalSteps - 1
5713
6080
  );
5714
- return /* @__PURE__ */ jsxs219("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
5715
- /* @__PURE__ */ jsx341(
6081
+ return /* @__PURE__ */ jsxs220("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
6082
+ /* @__PURE__ */ jsx342(
5716
6083
  "div",
5717
6084
  {
5718
6085
  className: "lib-xplat-swiper__viewport",
5719
6086
  onMouseDown: handleDragStart,
5720
6087
  onTouchStart: handleDragStart,
5721
6088
  onDragStart: (e) => e.preventDefault(),
5722
- children: /* @__PURE__ */ jsx341(
6089
+ children: /* @__PURE__ */ jsx342(
5723
6090
  "div",
5724
6091
  {
5725
6092
  className: clsx_default(
@@ -5737,7 +6104,7 @@ var Swiper = (props) => {
5737
6104
  )
5738
6105
  }
5739
6106
  ),
5740
- showProgress && canSlide && /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ jsx341(
6107
+ showProgress && canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ jsx342(
5741
6108
  "span",
5742
6109
  {
5743
6110
  className: "lib-xplat-swiper__progress-fill",
@@ -5747,7 +6114,7 @@ var Swiper = (props) => {
5747
6114
  }
5748
6115
  }
5749
6116
  ) }) }),
5750
- canSlide && /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ jsx341(
6117
+ canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ jsx342(
5751
6118
  "button",
5752
6119
  {
5753
6120
  className: clsx_default(
@@ -5765,8 +6132,8 @@ Swiper.displayName = "Swiper";
5765
6132
  var Swiper_default = Swiper;
5766
6133
 
5767
6134
  // src/components/Switch/Switch.tsx
5768
- import React32 from "react";
5769
- import { jsx as jsx342 } from "react/jsx-runtime";
6135
+ import React33 from "react";
6136
+ import { jsx as jsx343 } from "react/jsx-runtime";
5770
6137
  var KNOB_TRANSITION_MS = 250;
5771
6138
  var Switch = (props) => {
5772
6139
  const {
@@ -5775,12 +6142,15 @@ var Switch = (props) => {
5775
6142
  type = "primary",
5776
6143
  disabled,
5777
6144
  onChange,
5778
- validations
6145
+ validations,
6146
+ label,
6147
+ required
5779
6148
  } = props;
6149
+ const fieldId = React33.useId();
5780
6150
  const statusType = normalizeStatus(type);
5781
- const [isAnimating, setIsAnimating] = React32.useState(false);
5782
- const timeoutRef = React32.useRef(null);
5783
- React32.useEffect(() => {
6151
+ const [isAnimating, setIsAnimating] = React33.useState(false);
6152
+ const timeoutRef = React33.useRef(null);
6153
+ React33.useEffect(() => {
5784
6154
  return () => {
5785
6155
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
5786
6156
  };
@@ -5795,9 +6165,10 @@ var Switch = (props) => {
5795
6165
  timeoutRef.current = null;
5796
6166
  }, KNOB_TRANSITION_MS);
5797
6167
  };
5798
- const control = /* @__PURE__ */ jsx342(
6168
+ const control = /* @__PURE__ */ jsx343(
5799
6169
  "div",
5800
6170
  {
6171
+ id: fieldId,
5801
6172
  className: clsx_default(
5802
6173
  "lib-xplat-switch",
5803
6174
  size,
@@ -5809,26 +6180,26 @@ var Switch = (props) => {
5809
6180
  onClick: handleClick,
5810
6181
  "aria-invalid": hasError(validations) || void 0,
5811
6182
  "aria-disabled": disabled || isAnimating,
5812
- children: /* @__PURE__ */ jsx342("div", { className: clsx_default("knob", value ? "checked" : void 0) })
6183
+ children: /* @__PURE__ */ jsx343("div", { className: clsx_default("knob", value ? "checked" : void 0) })
5813
6184
  }
5814
6185
  );
5815
- return /* @__PURE__ */ jsx342(Field, { validations, children: control });
6186
+ return /* @__PURE__ */ jsx343(Field, { validations, label, required, htmlFor: fieldId, children: control });
5816
6187
  };
5817
6188
  Switch.displayName = "Switch";
5818
6189
  var Switch_default = Switch;
5819
6190
 
5820
6191
  // src/components/Table/TableContext.tsx
5821
- import React33 from "react";
5822
- var TableContext = React33.createContext(null);
6192
+ import React34 from "react";
6193
+ var TableContext = React34.createContext(null);
5823
6194
  var useTableContext = () => {
5824
- const ctx = React33.useContext(TableContext);
6195
+ const ctx = React34.useContext(TableContext);
5825
6196
  if (!ctx) throw new Error("Table components must be used inside <Table>");
5826
6197
  return ctx;
5827
6198
  };
5828
6199
  var TableContext_default = TableContext;
5829
6200
 
5830
6201
  // src/components/Table/Table.tsx
5831
- import { jsx as jsx343 } from "react/jsx-runtime";
6202
+ import { jsx as jsx344 } from "react/jsx-runtime";
5832
6203
  var Table = (props) => {
5833
6204
  const {
5834
6205
  children,
@@ -5838,7 +6209,7 @@ var Table = (props) => {
5838
6209
  headerSticky = false,
5839
6210
  stickyShadow = true
5840
6211
  } = props;
5841
- return /* @__PURE__ */ jsx343("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx343(
6212
+ return /* @__PURE__ */ jsx344("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx344(
5842
6213
  TableContext_default.Provider,
5843
6214
  {
5844
6215
  value: {
@@ -5847,7 +6218,7 @@ var Table = (props) => {
5847
6218
  headerSticky,
5848
6219
  stickyShadow
5849
6220
  },
5850
- children: /* @__PURE__ */ jsx343("table", { className: "lib-xplat-table", children })
6221
+ children: /* @__PURE__ */ jsx344("table", { className: "lib-xplat-table", children })
5851
6222
  }
5852
6223
  ) });
5853
6224
  };
@@ -5855,41 +6226,41 @@ Table.displayName = "Table";
5855
6226
  var Table_default = Table;
5856
6227
 
5857
6228
  // src/components/Table/TableBody.tsx
5858
- import { jsx as jsx344 } from "react/jsx-runtime";
6229
+ import { jsx as jsx345 } from "react/jsx-runtime";
5859
6230
  var TableBody = (props) => {
5860
6231
  const { children } = props;
5861
- return /* @__PURE__ */ jsx344("tbody", { children });
6232
+ return /* @__PURE__ */ jsx345("tbody", { children });
5862
6233
  };
5863
6234
  TableBody.displayName = "TableBody";
5864
6235
  var TableBody_default = TableBody;
5865
6236
 
5866
6237
  // src/components/Table/TableCell.tsx
5867
- import React36 from "react";
6238
+ import React37 from "react";
5868
6239
 
5869
6240
  // src/components/Table/TableHeadContext.tsx
5870
- import React34 from "react";
5871
- var TableHeadContext = React34.createContext(
6241
+ import React35 from "react";
6242
+ var TableHeadContext = React35.createContext(
5872
6243
  null
5873
6244
  );
5874
6245
  var useTableHeadContext = () => {
5875
- const ctx = React34.useContext(TableHeadContext);
6246
+ const ctx = React35.useContext(TableHeadContext);
5876
6247
  return ctx;
5877
6248
  };
5878
6249
  var TableHeadContext_default = TableHeadContext;
5879
6250
 
5880
6251
  // src/components/Table/TableRowContext.tsx
5881
- import React35 from "react";
5882
- var TableRowContext = React35.createContext(null);
6252
+ import React36 from "react";
6253
+ var TableRowContext = React36.createContext(null);
5883
6254
  var useTableRowContext = () => {
5884
- const ctx = React35.useContext(TableRowContext);
6255
+ const ctx = React36.useContext(TableRowContext);
5885
6256
  if (!ctx) throw new Error("Table components must be used inside <Table>");
5886
6257
  return ctx;
5887
6258
  };
5888
6259
  var TableRowContext_default = TableRowContext;
5889
6260
 
5890
6261
  // src/components/Table/TableCell.tsx
5891
- import { jsx as jsx345 } from "react/jsx-runtime";
5892
- var TableCell = React36.memo((props) => {
6262
+ import { jsx as jsx346 } from "react/jsx-runtime";
6263
+ var TableCell = React37.memo((props) => {
5893
6264
  const {
5894
6265
  children,
5895
6266
  align = "center",
@@ -5903,9 +6274,9 @@ var TableCell = React36.memo((props) => {
5903
6274
  const { registerStickyCell, stickyCells } = useTableRowContext();
5904
6275
  const { stickyShadow } = useTableContext();
5905
6276
  const headContext = useTableHeadContext();
5906
- const [left, setLeft] = React36.useState(0);
5907
- const cellRef = React36.useRef(null);
5908
- const calculateLeft = React36.useCallback(() => {
6277
+ const [left, setLeft] = React37.useState(0);
6278
+ const cellRef = React37.useRef(null);
6279
+ const calculateLeft = React37.useCallback(() => {
5909
6280
  if (!cellRef.current) return 0;
5910
6281
  let totalLeft = 0;
5911
6282
  for (const ref of stickyCells) {
@@ -5914,7 +6285,7 @@ var TableCell = React36.memo((props) => {
5914
6285
  }
5915
6286
  return totalLeft;
5916
6287
  }, [stickyCells]);
5917
- React36.useEffect(() => {
6288
+ React37.useEffect(() => {
5918
6289
  if (!isSticky || !cellRef.current) return;
5919
6290
  registerStickyCell(cellRef);
5920
6291
  setLeft(calculateLeft());
@@ -5933,7 +6304,7 @@ var TableCell = React36.memo((props) => {
5933
6304
  const CellTag = isHeaderCell ? "th" : "td";
5934
6305
  const isLastSticky = isSticky && stickyCells[stickyCells.length - 1] === cellRef;
5935
6306
  const enableHover = headContext && headContext.cellHover;
5936
- return /* @__PURE__ */ jsx345(
6307
+ return /* @__PURE__ */ jsx346(
5937
6308
  CellTag,
5938
6309
  {
5939
6310
  ref: cellRef,
@@ -5960,21 +6331,21 @@ TableCell.displayName = "TableCell";
5960
6331
  var TableCell_default = TableCell;
5961
6332
 
5962
6333
  // src/components/Table/TableHead.tsx
5963
- import { jsx as jsx346 } from "react/jsx-runtime";
6334
+ import { jsx as jsx347 } from "react/jsx-runtime";
5964
6335
  var TableHead = ({
5965
6336
  children,
5966
6337
  cellHover = false
5967
6338
  }) => {
5968
6339
  const { headerSticky } = useTableContext();
5969
- return /* @__PURE__ */ jsx346(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ jsx346("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
6340
+ return /* @__PURE__ */ jsx347(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ jsx347("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
5970
6341
  };
5971
6342
  TableHead.displayName = "TableHead";
5972
6343
  var TableHead_default = TableHead;
5973
6344
 
5974
6345
  // src/components/Table/TableRow.tsx
5975
- import React37 from "react";
5976
- import { jsx as jsx347 } from "react/jsx-runtime";
5977
- var TableRow = React37.memo((props) => {
6346
+ import React38 from "react";
6347
+ import { jsx as jsx348 } from "react/jsx-runtime";
6348
+ var TableRow = React38.memo((props) => {
5978
6349
  const {
5979
6350
  children,
5980
6351
  type = "secondary",
@@ -5983,14 +6354,14 @@ var TableRow = React37.memo((props) => {
5983
6354
  onClick
5984
6355
  } = props;
5985
6356
  const { rowBorderUse } = useTableContext();
5986
- const [stickyCells, setStickyCells] = React37.useState([]);
6357
+ const [stickyCells, setStickyCells] = React38.useState([]);
5987
6358
  const registerStickyCell = (ref) => {
5988
6359
  setStickyCells((prev) => {
5989
6360
  if (prev.includes(ref)) return prev;
5990
6361
  return [...prev, ref];
5991
6362
  });
5992
6363
  };
5993
- return /* @__PURE__ */ jsx347(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ jsx347(
6364
+ return /* @__PURE__ */ jsx348(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ jsx348(
5994
6365
  "tr",
5995
6366
  {
5996
6367
  className: clsx_default(
@@ -6014,7 +6385,7 @@ TableRow.displayName = "TableRow";
6014
6385
  var TableRow_default = TableRow;
6015
6386
 
6016
6387
  // src/components/Tag/Tag.tsx
6017
- import { jsx as jsx348, jsxs as jsxs220 } from "react/jsx-runtime";
6388
+ import { jsx as jsx349, jsxs as jsxs221 } from "react/jsx-runtime";
6018
6389
  var Tag = (props) => {
6019
6390
  const {
6020
6391
  children,
@@ -6026,7 +6397,7 @@ var Tag = (props) => {
6026
6397
  colorIndex
6027
6398
  } = props;
6028
6399
  const shape = variant ?? type ?? "neutral";
6029
- return /* @__PURE__ */ jsxs220(
6400
+ return /* @__PURE__ */ jsxs221(
6030
6401
  "span",
6031
6402
  {
6032
6403
  className: clsx_default(
@@ -6037,8 +6408,8 @@ var Tag = (props) => {
6037
6408
  disabled && "disabled"
6038
6409
  ),
6039
6410
  children: [
6040
- /* @__PURE__ */ jsx348("span", { className: "tag-label", children }),
6041
- onClose && /* @__PURE__ */ jsx348("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ jsx348(XIcon_default, {}) })
6411
+ /* @__PURE__ */ jsx349("span", { className: "tag-label", children }),
6412
+ onClose && /* @__PURE__ */ jsx349("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ jsx349(XIcon_default, {}) })
6042
6413
  ]
6043
6414
  }
6044
6415
  );
@@ -6047,24 +6418,29 @@ Tag.displayName = "Tag";
6047
6418
  var Tag_default = Tag;
6048
6419
 
6049
6420
  // src/components/TextArea/TextArea.tsx
6050
- import React38 from "react";
6051
- import { jsx as jsx349 } from "react/jsx-runtime";
6052
- var TextArea = React38.forwardRef(
6421
+ import React39 from "react";
6422
+ import { jsx as jsx350 } from "react/jsx-runtime";
6423
+ var TextArea = React39.forwardRef(
6053
6424
  (props, ref) => {
6054
6425
  const {
6055
6426
  className,
6056
6427
  size = "md",
6057
6428
  validations,
6429
+ label,
6430
+ required,
6058
6431
  resize = "vertical",
6059
6432
  rows = 3,
6060
6433
  disabled,
6061
6434
  ...textareaProps
6062
6435
  } = props;
6063
- const control = /* @__PURE__ */ jsx349("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx349(
6436
+ const autoId = React39.useId();
6437
+ const fieldId = props.id ?? autoId;
6438
+ const control = /* @__PURE__ */ jsx350("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx350(
6064
6439
  "textarea",
6065
6440
  {
6066
6441
  ...textareaProps,
6067
6442
  ref,
6443
+ id: fieldId,
6068
6444
  rows,
6069
6445
  disabled,
6070
6446
  "aria-invalid": hasError(validations) || void 0,
@@ -6072,32 +6448,166 @@ var TextArea = React38.forwardRef(
6072
6448
  style: { resize }
6073
6449
  }
6074
6450
  ) });
6075
- return /* @__PURE__ */ jsx349(Field, { validations, children: control });
6451
+ return /* @__PURE__ */ jsx350(Field, { validations, label, required, htmlFor: fieldId, children: control });
6076
6452
  }
6077
6453
  );
6078
6454
  TextArea.displayName = "TextArea";
6079
6455
  var TextArea_default = TextArea;
6080
6456
 
6457
+ // src/components/TimePicker/TimePicker.tsx
6458
+ import React40 from "react";
6459
+ import { jsx as jsx351, jsxs as jsxs222 } from "react/jsx-runtime";
6460
+ var ANIMATION_DURATION_MS4 = 200;
6461
+ var toMinutes = (hhmm) => {
6462
+ if (!hhmm) return null;
6463
+ const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
6464
+ if (!m) return null;
6465
+ const h = Number(m[1]);
6466
+ const min = Number(m[2]);
6467
+ if (h > 23 || min > 59) return null;
6468
+ return h * 60 + min;
6469
+ };
6470
+ var toHHmm = (minutes) => `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
6471
+ var display = (hhmm, use12Hours) => {
6472
+ if (!use12Hours) return hhmm;
6473
+ const total = toMinutes(hhmm);
6474
+ if (total === null) return hhmm;
6475
+ const h24 = Math.floor(total / 60);
6476
+ const mm = String(total % 60).padStart(2, "0");
6477
+ const period = h24 < 12 ? "\uC624\uC804" : "\uC624\uD6C4";
6478
+ const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
6479
+ return `${period} ${h12}:${mm}`;
6480
+ };
6481
+ var TimePicker = (props) => {
6482
+ const {
6483
+ value,
6484
+ onChange,
6485
+ step = 30,
6486
+ min,
6487
+ max,
6488
+ use12Hours = false,
6489
+ placeholder = "\uC2DC\uAC01 \uC120\uD0DD",
6490
+ disabled = false,
6491
+ size = "md",
6492
+ label,
6493
+ required,
6494
+ validations
6495
+ } = props;
6496
+ const fieldId = React40.useId();
6497
+ const triggerRef = React40.useRef(null);
6498
+ const contentRef = React40.useRef(null);
6499
+ const [isOpen, setOpen] = React40.useState(false);
6500
+ const [mounted, setMounted] = React40.useState(false);
6501
+ const [visible, setVisible] = React40.useState(false);
6502
+ const options = React40.useMemo(() => {
6503
+ const safeStep = step > 0 && step <= 720 ? step : 30;
6504
+ const lo = toMinutes(min) ?? 0;
6505
+ const hi = toMinutes(max) ?? 24 * 60 - 1;
6506
+ const out = [];
6507
+ for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
6508
+ return out;
6509
+ }, [step, min, max]);
6510
+ const close = React40.useCallback(() => setOpen(false), []);
6511
+ useClickOutside_default([triggerRef, contentRef], close, isOpen);
6512
+ useEscapeKey(isOpen, () => {
6513
+ close();
6514
+ triggerRef.current?.focus({ preventScroll: true });
6515
+ });
6516
+ const position = useAutoPosition_default(triggerRef, contentRef, mounted);
6517
+ React40.useEffect(() => {
6518
+ if (disabled && isOpen) setOpen(false);
6519
+ }, [disabled, isOpen]);
6520
+ React40.useEffect(() => {
6521
+ if (isOpen) {
6522
+ setMounted(true);
6523
+ const t2 = setTimeout(() => setVisible(true), 1);
6524
+ return () => clearTimeout(t2);
6525
+ }
6526
+ setVisible(false);
6527
+ const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS4);
6528
+ return () => clearTimeout(t);
6529
+ }, [isOpen]);
6530
+ const pick = (hhmm) => {
6531
+ onChange?.(hhmm);
6532
+ close();
6533
+ triggerRef.current?.focus({ preventScroll: true });
6534
+ };
6535
+ const control = /* @__PURE__ */ jsxs222("div", { className: clsx_default("lib-xplat-time-picker", size, disabled && "disabled"), children: [
6536
+ /* @__PURE__ */ jsx351(
6537
+ "div",
6538
+ {
6539
+ id: fieldId,
6540
+ ref: triggerRef,
6541
+ className: clsx_default("time-picker-trigger", hasError(validations) && "error"),
6542
+ role: "combobox",
6543
+ "aria-expanded": isOpen,
6544
+ "aria-haspopup": "listbox",
6545
+ "aria-invalid": hasError(validations) || void 0,
6546
+ tabIndex: disabled ? void 0 : 0,
6547
+ onClick: () => !disabled && setOpen((p) => !p),
6548
+ onKeyDown: (e) => {
6549
+ if (disabled) return;
6550
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
6551
+ e.preventDefault();
6552
+ setOpen(true);
6553
+ }
6554
+ },
6555
+ children: /* @__PURE__ */ jsx351("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
6556
+ }
6557
+ ),
6558
+ mounted && /* @__PURE__ */ jsx351(Portal_default, { children: /* @__PURE__ */ jsx351(
6559
+ "div",
6560
+ {
6561
+ ref: contentRef,
6562
+ className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit"),
6563
+ style: { ...position.position, width: triggerRef.current?.offsetWidth },
6564
+ role: "listbox",
6565
+ children: options.map((t) => /* @__PURE__ */ jsx351(
6566
+ "div",
6567
+ {
6568
+ className: clsx_default("time-picker-item", t === value && "is-selected"),
6569
+ role: "option",
6570
+ "aria-selected": t === value,
6571
+ tabIndex: 0,
6572
+ onClick: () => pick(t),
6573
+ onKeyDown: (e) => {
6574
+ if (e.key === "Enter" || e.key === " ") {
6575
+ e.preventDefault();
6576
+ pick(t);
6577
+ }
6578
+ },
6579
+ children: display(t, use12Hours)
6580
+ },
6581
+ t
6582
+ ))
6583
+ }
6584
+ ) })
6585
+ ] });
6586
+ return /* @__PURE__ */ jsx351(Field, { validations, label, required, htmlFor: fieldId, children: control });
6587
+ };
6588
+ TimePicker.displayName = "TimePicker";
6589
+ var TimePicker_default = TimePicker;
6590
+
6081
6591
  // src/components/Toast/Toast.tsx
6082
- import React39 from "react";
6592
+ import React41 from "react";
6083
6593
  import { createPortal as createPortal3 } from "react-dom";
6084
- import { jsx as jsx350, jsxs as jsxs221 } from "react/jsx-runtime";
6085
- var ToastContext = React39.createContext(null);
6594
+ import { jsx as jsx352, jsxs as jsxs223 } from "react/jsx-runtime";
6595
+ var ToastContext = React41.createContext(null);
6086
6596
  var useToast = () => {
6087
- const ctx = React39.useContext(ToastContext);
6597
+ const ctx = React41.useContext(ToastContext);
6088
6598
  if (!ctx) throw new Error("useToast must be used within ToastProvider");
6089
6599
  return ctx;
6090
6600
  };
6091
6601
  var EXIT_DURATION = 300;
6092
6602
  var ToastItemComponent = ({ item, isExiting, onClose }) => {
6093
- const ref = React39.useRef(null);
6094
- const [height, setHeight] = React39.useState(void 0);
6095
- React39.useEffect(() => {
6603
+ const ref = React41.useRef(null);
6604
+ const [height, setHeight] = React41.useState(void 0);
6605
+ React41.useEffect(() => {
6096
6606
  if (ref.current && !isExiting) {
6097
6607
  setHeight(ref.current.offsetHeight);
6098
6608
  }
6099
6609
  }, [isExiting]);
6100
- return /* @__PURE__ */ jsx350(
6610
+ return /* @__PURE__ */ jsx352(
6101
6611
  "div",
6102
6612
  {
6103
6613
  className: clsx_default("lib-xplat-toast-wrapper", { exit: isExiting }),
@@ -6105,15 +6615,15 @@ var ToastItemComponent = ({ item, isExiting, onClose }) => {
6105
6615
  maxHeight: isExiting ? 0 : height ?? "none",
6106
6616
  marginBottom: isExiting ? 0 : void 0
6107
6617
  },
6108
- children: /* @__PURE__ */ jsxs221(
6618
+ children: /* @__PURE__ */ jsxs223(
6109
6619
  "div",
6110
6620
  {
6111
6621
  ref,
6112
6622
  className: clsx_default("lib-xplat-toast", item.type, { exit: isExiting }),
6113
6623
  role: "alert",
6114
6624
  children: [
6115
- /* @__PURE__ */ jsx350("span", { className: "message", children: item.message }),
6116
- /* @__PURE__ */ jsx350("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
6625
+ /* @__PURE__ */ jsx352("span", { className: "message", children: item.message }),
6626
+ /* @__PURE__ */ jsx352("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
6117
6627
  ]
6118
6628
  }
6119
6629
  )
@@ -6124,13 +6634,13 @@ var ToastProvider = ({
6124
6634
  children,
6125
6635
  position = "top-right"
6126
6636
  }) => {
6127
- const [toasts, setToasts] = React39.useState([]);
6128
- const [removing, setRemoving] = React39.useState(/* @__PURE__ */ new Set());
6129
- const [mounted, setMounted] = React39.useState(false);
6130
- React39.useEffect(() => {
6637
+ const [toasts, setToasts] = React41.useState([]);
6638
+ const [removing, setRemoving] = React41.useState(/* @__PURE__ */ new Set());
6639
+ const [mounted, setMounted] = React41.useState(false);
6640
+ React41.useEffect(() => {
6131
6641
  setMounted(true);
6132
6642
  }, []);
6133
- const remove = React39.useCallback((id) => {
6643
+ const remove = React41.useCallback((id) => {
6134
6644
  setRemoving((prev) => new Set(prev).add(id));
6135
6645
  setTimeout(() => {
6136
6646
  setToasts((prev) => prev.filter((t) => t.id !== id));
@@ -6141,7 +6651,7 @@ var ToastProvider = ({
6141
6651
  });
6142
6652
  }, EXIT_DURATION);
6143
6653
  }, []);
6144
- const toast = React39.useCallback(
6654
+ const toast = React41.useCallback(
6145
6655
  (type, message, duration = 3e3) => {
6146
6656
  const id = `${Date.now()}-${Math.random()}`;
6147
6657
  setToasts((prev) => [...prev, { id, type, message }]);
@@ -6151,10 +6661,10 @@ var ToastProvider = ({
6151
6661
  },
6152
6662
  [remove]
6153
6663
  );
6154
- return /* @__PURE__ */ jsxs221(ToastContext.Provider, { value: { toast }, children: [
6664
+ return /* @__PURE__ */ jsxs223(ToastContext.Provider, { value: { toast }, children: [
6155
6665
  children,
6156
6666
  mounted && createPortal3(
6157
- /* @__PURE__ */ jsx350("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ jsx350(
6667
+ /* @__PURE__ */ jsx352("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ jsx352(
6158
6668
  ToastItemComponent,
6159
6669
  {
6160
6670
  item: t,
@@ -6170,8 +6680,8 @@ var ToastProvider = ({
6170
6680
  ToastProvider.displayName = "ToastProvider";
6171
6681
 
6172
6682
  // src/components/Tooltip/Tooltip.tsx
6173
- import React40 from "react";
6174
- import { Fragment as Fragment6, jsx as jsx351, jsxs as jsxs222 } from "react/jsx-runtime";
6683
+ import React42 from "react";
6684
+ import { Fragment as Fragment6, jsx as jsx353, jsxs as jsxs224 } from "react/jsx-runtime";
6175
6685
  var OFFSET = 12;
6176
6686
  var GAP = 8;
6177
6687
  var SHOW_DELAY = 300;
@@ -6186,14 +6696,14 @@ var Tooltip = (props) => {
6186
6696
  disabled = false
6187
6697
  } = props;
6188
6698
  const shape = variant ?? type ?? "dark";
6189
- const triggerRef = React40.useRef(null);
6190
- const tooltipRef = React40.useRef(null);
6191
- const [visible, setVisible] = React40.useState(false);
6192
- const [pos, setPos] = React40.useState({ left: 0, top: 0 });
6193
- const delayTimer = React40.useRef(0);
6194
- const rafRef = React40.useRef(0);
6195
- const cursor = React40.useRef(null);
6196
- const clamp = React40.useCallback((left, top, w, h) => {
6699
+ const triggerRef = React42.useRef(null);
6700
+ const tooltipRef = React42.useRef(null);
6701
+ const [visible, setVisible] = React42.useState(false);
6702
+ const [pos, setPos] = React42.useState({ left: 0, top: 0 });
6703
+ const delayTimer = React42.useRef(0);
6704
+ const rafRef = React42.useRef(0);
6705
+ const cursor = React42.useRef(null);
6706
+ const clamp = React42.useCallback((left, top, w, h) => {
6197
6707
  const vw = window.innerWidth;
6198
6708
  const vh = window.innerHeight;
6199
6709
  return {
@@ -6201,7 +6711,7 @@ var Tooltip = (props) => {
6201
6711
  top: Math.min(Math.max(GAP, top), Math.max(GAP, vh - h - GAP))
6202
6712
  };
6203
6713
  }, []);
6204
- const placeAtCursor = React40.useCallback((x, y) => {
6714
+ const placeAtCursor = React42.useCallback((x, y) => {
6205
6715
  const el = tooltipRef.current;
6206
6716
  if (!el) return;
6207
6717
  const w = el.offsetWidth;
@@ -6212,7 +6722,7 @@ var Tooltip = (props) => {
6212
6722
  if (top < GAP) top = y + OFFSET;
6213
6723
  setPos(clamp(left, top, w, h));
6214
6724
  }, [clamp]);
6215
- const placeAtTrigger = React40.useCallback(() => {
6725
+ const placeAtTrigger = React42.useCallback(() => {
6216
6726
  const el = tooltipRef.current;
6217
6727
  const trigger = triggerRef.current;
6218
6728
  if (!el || !trigger) return;
@@ -6224,19 +6734,19 @@ var Tooltip = (props) => {
6224
6734
  const left = rect.left + rect.width / 2 - w / 2;
6225
6735
  setPos(clamp(left, top, w, h));
6226
6736
  }, [clamp]);
6227
- const reposition = React40.useCallback(() => {
6737
+ const reposition = React42.useCallback(() => {
6228
6738
  if (follow && cursor.current) {
6229
6739
  placeAtCursor(cursor.current.x, cursor.current.y);
6230
6740
  } else {
6231
6741
  placeAtTrigger();
6232
6742
  }
6233
6743
  }, [follow, placeAtCursor, placeAtTrigger]);
6234
- const handleMouseEnter = React40.useCallback((e) => {
6744
+ const handleMouseEnter = React42.useCallback((e) => {
6235
6745
  if (disabled) return;
6236
6746
  cursor.current = { x: e.clientX, y: e.clientY };
6237
6747
  delayTimer.current = window.setTimeout(() => setVisible(true), SHOW_DELAY);
6238
6748
  }, [disabled]);
6239
- const handleMouseMove = React40.useCallback((e) => {
6749
+ const handleMouseMove = React42.useCallback((e) => {
6240
6750
  cursor.current = { x: e.clientX, y: e.clientY };
6241
6751
  if (!visible || !follow) return;
6242
6752
  cancelAnimationFrame(rafRef.current);
@@ -6244,25 +6754,25 @@ var Tooltip = (props) => {
6244
6754
  if (cursor.current) placeAtCursor(cursor.current.x, cursor.current.y);
6245
6755
  });
6246
6756
  }, [visible, follow, placeAtCursor]);
6247
- const close = React40.useCallback(() => {
6757
+ const close = React42.useCallback(() => {
6248
6758
  window.clearTimeout(delayTimer.current);
6249
6759
  cancelAnimationFrame(rafRef.current);
6250
6760
  setVisible(false);
6251
6761
  }, []);
6252
- const handleMouseLeave = React40.useCallback(() => {
6762
+ const handleMouseLeave = React42.useCallback(() => {
6253
6763
  cursor.current = null;
6254
6764
  close();
6255
6765
  }, [close]);
6256
- const handleFocus = React40.useCallback(() => {
6766
+ const handleFocus = React42.useCallback(() => {
6257
6767
  if (disabled) return;
6258
6768
  cursor.current = null;
6259
6769
  setVisible(true);
6260
6770
  }, [disabled]);
6261
- React40.useLayoutEffect(() => {
6771
+ React42.useLayoutEffect(() => {
6262
6772
  if (!visible) return;
6263
6773
  reposition();
6264
6774
  }, [visible, reposition]);
6265
- React40.useEffect(() => {
6775
+ React42.useEffect(() => {
6266
6776
  if (!visible || follow) return;
6267
6777
  const onChange = () => placeAtTrigger();
6268
6778
  window.addEventListener("scroll", onChange, true);
@@ -6272,12 +6782,12 @@ var Tooltip = (props) => {
6272
6782
  window.removeEventListener("resize", onChange);
6273
6783
  };
6274
6784
  }, [visible, follow, placeAtTrigger]);
6275
- React40.useEffect(() => () => {
6785
+ React42.useEffect(() => () => {
6276
6786
  window.clearTimeout(delayTimer.current);
6277
6787
  cancelAnimationFrame(rafRef.current);
6278
6788
  }, []);
6279
- if (!title && !description) return /* @__PURE__ */ jsx351(Fragment6, { children });
6280
- return /* @__PURE__ */ jsxs222(
6789
+ if (!title && !description) return /* @__PURE__ */ jsx353(Fragment6, { children });
6790
+ return /* @__PURE__ */ jsxs224(
6281
6791
  "div",
6282
6792
  {
6283
6793
  ref: triggerRef,
@@ -6290,7 +6800,7 @@ var Tooltip = (props) => {
6290
6800
  onBlur: close,
6291
6801
  children: [
6292
6802
  children,
6293
- visible && /* @__PURE__ */ jsx351(Portal_default, { children: /* @__PURE__ */ jsxs222(
6803
+ visible && /* @__PURE__ */ jsx353(Portal_default, { children: /* @__PURE__ */ jsxs224(
6294
6804
  "div",
6295
6805
  {
6296
6806
  ref: tooltipRef,
@@ -6298,8 +6808,8 @@ var Tooltip = (props) => {
6298
6808
  className: clsx_default("lib-xplat-tooltip", shape),
6299
6809
  style: { position: "fixed", left: pos.left, top: pos.top },
6300
6810
  children: [
6301
- title && /* @__PURE__ */ jsx351("div", { className: "tooltip-title", children: title }),
6302
- description && /* @__PURE__ */ jsx351("div", { className: "tooltip-desc", children: description })
6811
+ title && /* @__PURE__ */ jsx353("div", { className: "tooltip-title", children: title }),
6812
+ description && /* @__PURE__ */ jsx353("div", { className: "tooltip-desc", children: description })
6303
6813
  ]
6304
6814
  }
6305
6815
  ) })
@@ -6311,11 +6821,11 @@ Tooltip.displayName = "Tooltip";
6311
6821
  var Tooltip_default = Tooltip;
6312
6822
 
6313
6823
  // src/components/Video/Video.tsx
6314
- import React41 from "react";
6315
- import { jsx as jsx352, jsxs as jsxs223 } from "react/jsx-runtime";
6316
- var PipIcon = () => /* @__PURE__ */ jsxs223("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
6317
- /* @__PURE__ */ jsx352("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
6318
- /* @__PURE__ */ jsx352("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
6824
+ import React43 from "react";
6825
+ import { jsx as jsx354, jsxs as jsxs225 } from "react/jsx-runtime";
6826
+ var PipIcon = () => /* @__PURE__ */ jsxs225("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
6827
+ /* @__PURE__ */ jsx354("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
6828
+ /* @__PURE__ */ jsx354("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
6319
6829
  ] });
6320
6830
  var formatTime = (sec) => {
6321
6831
  if (!Number.isFinite(sec) || sec < 0) return "0:00";
@@ -6323,7 +6833,7 @@ var formatTime = (sec) => {
6323
6833
  const s = Math.floor(sec % 60);
6324
6834
  return `${m}:${s.toString().padStart(2, "0")}`;
6325
6835
  };
6326
- var Video = React41.forwardRef((props, ref) => {
6836
+ var Video = React43.forwardRef((props, ref) => {
6327
6837
  const {
6328
6838
  src,
6329
6839
  poster,
@@ -6347,21 +6857,21 @@ var Video = React41.forwardRef((props, ref) => {
6347
6857
  children,
6348
6858
  ...rest
6349
6859
  } = props;
6350
- const containerRef = React41.useRef(null);
6351
- const videoRef = React41.useRef(null);
6352
- const [isPlaying, setIsPlaying] = React41.useState(Boolean(autoPlay));
6353
- const [isLoaded, setIsLoaded] = React41.useState(false);
6354
- const [currentTime, setCurrentTime] = React41.useState(0);
6355
- const [duration, setDuration] = React41.useState(0);
6356
- const [buffered, setBuffered] = React41.useState(0);
6357
- const [volume, setVolume] = React41.useState(1);
6358
- const [isMuted, setIsMuted] = React41.useState(Boolean(muted));
6359
- const [isFullscreen, setIsFullscreen] = React41.useState(false);
6360
- const [playbackRate, setPlaybackRate] = React41.useState(1);
6361
- const [rateMenuOpen, setRateMenuOpen] = React41.useState(false);
6362
- const [captionsOn, setCaptionsOn] = React41.useState(false);
6363
- const [isPip, setIsPip] = React41.useState(false);
6364
- const setRefs = React41.useCallback(
6860
+ const containerRef = React43.useRef(null);
6861
+ const videoRef = React43.useRef(null);
6862
+ const [isPlaying, setIsPlaying] = React43.useState(Boolean(autoPlay));
6863
+ const [isLoaded, setIsLoaded] = React43.useState(false);
6864
+ const [currentTime, setCurrentTime] = React43.useState(0);
6865
+ const [duration, setDuration] = React43.useState(0);
6866
+ const [buffered, setBuffered] = React43.useState(0);
6867
+ const [volume, setVolume] = React43.useState(1);
6868
+ const [isMuted, setIsMuted] = React43.useState(Boolean(muted));
6869
+ const [isFullscreen, setIsFullscreen] = React43.useState(false);
6870
+ const [playbackRate, setPlaybackRate] = React43.useState(1);
6871
+ const [rateMenuOpen, setRateMenuOpen] = React43.useState(false);
6872
+ const [captionsOn, setCaptionsOn] = React43.useState(false);
6873
+ const [isPip, setIsPip] = React43.useState(false);
6874
+ const setRefs = React43.useCallback(
6365
6875
  (el) => {
6366
6876
  videoRef.current = el;
6367
6877
  if (typeof ref === "function") ref(el);
@@ -6369,14 +6879,14 @@ var Video = React41.forwardRef((props, ref) => {
6369
6879
  },
6370
6880
  [ref]
6371
6881
  );
6372
- React41.useEffect(() => {
6882
+ React43.useEffect(() => {
6373
6883
  const onFsChange = () => {
6374
6884
  setIsFullscreen(document.fullscreenElement === containerRef.current);
6375
6885
  };
6376
6886
  document.addEventListener("fullscreenchange", onFsChange);
6377
6887
  return () => document.removeEventListener("fullscreenchange", onFsChange);
6378
6888
  }, []);
6379
- React41.useEffect(() => {
6889
+ React43.useEffect(() => {
6380
6890
  const v = videoRef.current;
6381
6891
  if (!v) return;
6382
6892
  const onEnter = () => setIsPip(true);
@@ -6490,13 +7000,13 @@ var Video = React41.forwardRef((props, ref) => {
6490
7000
  const volumePct = (isMuted ? 0 : volume) * 100;
6491
7001
  const VolumeGlyph = isMuted || volume === 0 ? VolumeXIcon_default : volume < 0.5 ? VolumeIcon_default : Volume2Icon_default;
6492
7002
  const pipSupported = typeof document !== "undefined" && "pictureInPictureEnabled" in document && document.pictureInPictureEnabled;
6493
- return /* @__PURE__ */ jsxs223(
7003
+ return /* @__PURE__ */ jsxs225(
6494
7004
  "div",
6495
7005
  {
6496
7006
  ref: containerRef,
6497
7007
  className: clsx_default("lib-xplat-video", showControls && "has-controls"),
6498
7008
  children: [
6499
- /* @__PURE__ */ jsx352(
7009
+ /* @__PURE__ */ jsx354(
6500
7010
  "video",
6501
7011
  {
6502
7012
  ref: setRefs,
@@ -6517,7 +7027,7 @@ var Video = React41.forwardRef((props, ref) => {
6517
7027
  children
6518
7028
  }
6519
7029
  ),
6520
- showCenterPlay && /* @__PURE__ */ jsx352(
7030
+ showCenterPlay && /* @__PURE__ */ jsx354(
6521
7031
  "button",
6522
7032
  {
6523
7033
  type: "button",
@@ -6529,11 +7039,11 @@ var Video = React41.forwardRef((props, ref) => {
6529
7039
  onClick: togglePlay,
6530
7040
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
6531
7041
  tabIndex: -1,
6532
- children: /* @__PURE__ */ jsx352("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx352(PlayCircleIcon_default, {}) })
7042
+ children: /* @__PURE__ */ jsx354("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx354(PlayCircleIcon_default, {}) })
6533
7043
  }
6534
7044
  ),
6535
- showControls && /* @__PURE__ */ jsxs223("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
6536
- /* @__PURE__ */ jsx352(
7045
+ showControls && /* @__PURE__ */ jsxs225("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
7046
+ /* @__PURE__ */ jsx354(
6537
7047
  "input",
6538
7048
  {
6539
7049
  type: "range",
@@ -6550,29 +7060,29 @@ var Video = React41.forwardRef((props, ref) => {
6550
7060
  }
6551
7061
  }
6552
7062
  ),
6553
- /* @__PURE__ */ jsxs223("div", { className: "controls-row", children: [
6554
- /* @__PURE__ */ jsx352(
7063
+ /* @__PURE__ */ jsxs225("div", { className: "controls-row", children: [
7064
+ /* @__PURE__ */ jsx354(
6555
7065
  "button",
6556
7066
  {
6557
7067
  type: "button",
6558
7068
  className: "control-btn",
6559
7069
  onClick: togglePlay,
6560
7070
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
6561
- children: isPlaying ? /* @__PURE__ */ jsx352(PauseIcon_default, {}) : /* @__PURE__ */ jsx352(PlayIcon_default, {})
7071
+ children: isPlaying ? /* @__PURE__ */ jsx354(PauseIcon_default, {}) : /* @__PURE__ */ jsx354(PlayIcon_default, {})
6562
7072
  }
6563
7073
  ),
6564
- /* @__PURE__ */ jsxs223("div", { className: "volume-group", children: [
6565
- /* @__PURE__ */ jsx352(
7074
+ /* @__PURE__ */ jsxs225("div", { className: "volume-group", children: [
7075
+ /* @__PURE__ */ jsx354(
6566
7076
  "button",
6567
7077
  {
6568
7078
  type: "button",
6569
7079
  className: "control-btn",
6570
7080
  onClick: toggleMute,
6571
7081
  "aria-label": isMuted ? "\uC74C\uC18C\uAC70 \uD574\uC81C" : "\uC74C\uC18C\uAC70",
6572
- children: /* @__PURE__ */ jsx352(VolumeGlyph, {})
7082
+ children: /* @__PURE__ */ jsx354(VolumeGlyph, {})
6573
7083
  }
6574
7084
  ),
6575
- /* @__PURE__ */ jsx352(
7085
+ /* @__PURE__ */ jsx354(
6576
7086
  "input",
6577
7087
  {
6578
7088
  type: "range",
@@ -6587,14 +7097,14 @@ var Video = React41.forwardRef((props, ref) => {
6587
7097
  }
6588
7098
  )
6589
7099
  ] }),
6590
- /* @__PURE__ */ jsxs223("span", { className: "time", children: [
7100
+ /* @__PURE__ */ jsxs225("span", { className: "time", children: [
6591
7101
  formatTime(currentTime),
6592
7102
  " / ",
6593
7103
  formatTime(duration)
6594
7104
  ] }),
6595
- /* @__PURE__ */ jsx352("div", { className: "controls-spacer" }),
6596
- playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs223("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
6597
- /* @__PURE__ */ jsxs223(
7105
+ /* @__PURE__ */ jsx354("div", { className: "controls-spacer" }),
7106
+ playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs225("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
7107
+ /* @__PURE__ */ jsxs225(
6598
7108
  "button",
6599
7109
  {
6600
7110
  type: "button",
@@ -6608,7 +7118,7 @@ var Video = React41.forwardRef((props, ref) => {
6608
7118
  ]
6609
7119
  }
6610
7120
  ),
6611
- rateMenuOpen && /* @__PURE__ */ jsx352("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx352("li", { children: /* @__PURE__ */ jsxs223(
7121
+ rateMenuOpen && /* @__PURE__ */ jsx354("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx354("li", { children: /* @__PURE__ */ jsxs225(
6612
7122
  "button",
6613
7123
  {
6614
7124
  type: "button",
@@ -6622,7 +7132,7 @@ var Video = React41.forwardRef((props, ref) => {
6622
7132
  }
6623
7133
  ) }, r2)) })
6624
7134
  ] }),
6625
- showCaptions && /* @__PURE__ */ jsx352(
7135
+ showCaptions && /* @__PURE__ */ jsx354(
6626
7136
  "button",
6627
7137
  {
6628
7138
  type: "button",
@@ -6630,37 +7140,37 @@ var Video = React41.forwardRef((props, ref) => {
6630
7140
  onClick: toggleCaptions,
6631
7141
  "aria-label": captionsOn ? "\uC790\uB9C9 \uB044\uAE30" : "\uC790\uB9C9 \uCF1C\uAE30",
6632
7142
  "aria-pressed": captionsOn,
6633
- children: /* @__PURE__ */ jsx352(TypeIcon_default, {})
7143
+ children: /* @__PURE__ */ jsx354(TypeIcon_default, {})
6634
7144
  }
6635
7145
  ),
6636
- showPip && pipSupported && /* @__PURE__ */ jsx352(
7146
+ showPip && pipSupported && /* @__PURE__ */ jsx354(
6637
7147
  "button",
6638
7148
  {
6639
7149
  type: "button",
6640
7150
  className: clsx_default("control-btn", isPip && "is-active"),
6641
7151
  onClick: togglePip,
6642
7152
  "aria-label": isPip ? "PIP \uC885\uB8CC" : "PIP",
6643
- children: /* @__PURE__ */ jsx352(PipIcon, {})
7153
+ children: /* @__PURE__ */ jsx354(PipIcon, {})
6644
7154
  }
6645
7155
  ),
6646
- showDownload && /* @__PURE__ */ jsx352(
7156
+ showDownload && /* @__PURE__ */ jsx354(
6647
7157
  "a",
6648
7158
  {
6649
7159
  className: "control-btn",
6650
7160
  href: src,
6651
7161
  download: downloadFileName ?? true,
6652
7162
  "aria-label": "\uB2E4\uC6B4\uB85C\uB4DC",
6653
- children: /* @__PURE__ */ jsx352(DownloadIcon_default, {})
7163
+ children: /* @__PURE__ */ jsx354(DownloadIcon_default, {})
6654
7164
  }
6655
7165
  ),
6656
- /* @__PURE__ */ jsx352(
7166
+ /* @__PURE__ */ jsx354(
6657
7167
  "button",
6658
7168
  {
6659
7169
  type: "button",
6660
7170
  className: "control-btn",
6661
7171
  onClick: toggleFullscreen,
6662
7172
  "aria-label": isFullscreen ? "\uC804\uCCB4\uD654\uBA74 \uC885\uB8CC" : "\uC804\uCCB4\uD654\uBA74",
6663
- children: isFullscreen ? /* @__PURE__ */ jsx352(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx352(MaximizeIcon_default, {})
7173
+ children: isFullscreen ? /* @__PURE__ */ jsx354(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx354(MaximizeIcon_default, {})
6664
7174
  }
6665
7175
  )
6666
7176
  ] })
@@ -6717,6 +7227,7 @@ export {
6717
7227
  SingleDatePicker_default as SingleDatePicker,
6718
7228
  Skeleton_default as Skeleton,
6719
7229
  Spinner_default as Spinner,
7230
+ Stat_default as Stat,
6720
7231
  Steps_default as Steps,
6721
7232
  Swiper_default as Swiper,
6722
7233
  Switch_default as Switch,
@@ -6728,6 +7239,7 @@ export {
6728
7239
  TableRow_default as TableRow,
6729
7240
  Tag_default as Tag,
6730
7241
  TextArea_default as TextArea,
7242
+ TimePicker_default as TimePicker,
6731
7243
  ToastProvider,
6732
7244
  Tooltip_default as Tooltip,
6733
7245
  Video_default as Video,