@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
package/dist/index.js CHANGED
@@ -5622,11 +5622,16 @@ var FieldMessage = (props) => {
5622
5622
  FieldMessage.displayName = "FieldMessage";
5623
5623
  var FieldMessage_default = FieldMessage;
5624
5624
  var Field = (props) => {
5625
- const { validations, children } = props;
5626
- if (!validations || validations.length === 0) return /* @__PURE__ */ jsx297(Fragment, { children });
5625
+ const { label, required = false, htmlFor, validations, children } = props;
5626
+ const hasMessages = !!validations && validations.length > 0;
5627
+ if (!label && !hasMessages) return /* @__PURE__ */ jsx297(Fragment, { children });
5627
5628
  return /* @__PURE__ */ jsxs191("div", { className: "lib-xplat-field", children: [
5629
+ label && /* @__PURE__ */ jsxs191("label", { className: "lib-xplat-field-label", htmlFor, children: [
5630
+ label,
5631
+ required && /* @__PURE__ */ jsx297("span", { className: "required", "aria-hidden": "true", children: "*" })
5632
+ ] }),
5628
5633
  children,
5629
- /* @__PURE__ */ jsx297(FieldMessage, { validations })
5634
+ hasMessages && /* @__PURE__ */ jsx297(FieldMessage, { validations })
5630
5635
  ] });
5631
5636
  };
5632
5637
  Field.displayName = "Field";
@@ -5637,7 +5642,9 @@ import { jsx as jsx298 } from "react/jsx-runtime";
5637
5642
  var MAX_HEIGHT = 400;
5638
5643
  var AutoResizeTextArea = React2.forwardRef(
5639
5644
  (props, ref) => {
5640
- const { value, className, onChange, disabled, bare = false, validations, ...textareaProps } = props;
5645
+ const { value, className, onChange, disabled, bare = false, validations, label, required, ...textareaProps } = props;
5646
+ const autoId = React2.useId();
5647
+ const fieldId = props.id ?? autoId;
5641
5648
  const localRef = React2.useRef(null);
5642
5649
  const setRefs = (el) => {
5643
5650
  localRef.current = el;
@@ -5671,6 +5678,7 @@ var AutoResizeTextArea = React2.forwardRef(
5671
5678
  "aria-invalid": hasError(validations) || void 0,
5672
5679
  ...textareaProps,
5673
5680
  ref: setRefs,
5681
+ id: fieldId,
5674
5682
  className,
5675
5683
  disabled,
5676
5684
  value,
@@ -5684,12 +5692,13 @@ var AutoResizeTextArea = React2.forwardRef(
5684
5692
  "aria-invalid": hasError(validations) || void 0,
5685
5693
  ...textareaProps,
5686
5694
  ref: setRefs,
5695
+ id: fieldId,
5687
5696
  disabled,
5688
5697
  value,
5689
5698
  onChange: handleChange
5690
5699
  }
5691
5700
  ) }) });
5692
- return /* @__PURE__ */ jsx298(Field, { validations, children: control });
5701
+ return /* @__PURE__ */ jsx298(Field, { validations, label, required, htmlFor: fieldId, children: control });
5693
5702
  }
5694
5703
  );
5695
5704
  AutoResizeTextArea.displayName = "AutoResizeTextArea";
@@ -6907,8 +6916,11 @@ var ChatInput = React7.forwardRef(
6907
6916
  buttonType = "primary",
6908
6917
  onSubmit,
6909
6918
  onChange,
6910
- validations
6919
+ validations,
6920
+ label,
6921
+ required
6911
6922
  } = props;
6923
+ const fieldId = React7.useId();
6912
6924
  const isControlled = valueProp !== void 0;
6913
6925
  const [internalValue, setInternalValue] = React7.useState("");
6914
6926
  const value = isControlled ? valueProp : internalValue;
@@ -6933,6 +6945,7 @@ var ChatInput = React7.forwardRef(
6933
6945
  /* @__PURE__ */ jsx308(
6934
6946
  AutoResizeTextArea_default,
6935
6947
  {
6948
+ id: fieldId,
6936
6949
  ref,
6937
6950
  bare: true,
6938
6951
  className: "chat-input-textarea",
@@ -6957,7 +6970,7 @@ var ChatInput = React7.forwardRef(
6957
6970
  }
6958
6971
  )
6959
6972
  ] });
6960
- return /* @__PURE__ */ jsx308(Field, { validations, children: control });
6973
+ return /* @__PURE__ */ jsx308(Field, { validations, label, required, htmlFor: fieldId, children: control });
6961
6974
  }
6962
6975
  );
6963
6976
  ChatInput.displayName = "ChatInput";
@@ -7041,7 +7054,7 @@ Chip.displayName = "Chip";
7041
7054
  var Chip_default = Chip;
7042
7055
 
7043
7056
  // src/components/DatePicker/InputDatePicker/index.tsx
7044
- import React12 from "react";
7057
+ import React13 from "react";
7045
7058
 
7046
7059
  // src/components/Input/Input.tsx
7047
7060
  import React8 from "react";
@@ -7139,8 +7152,12 @@ var Input = React8.forwardRef((props, ref) => {
7139
7152
  suffix,
7140
7153
  disabled,
7141
7154
  validations,
7155
+ label,
7156
+ required,
7142
7157
  ...inputProps
7143
7158
  } = props;
7159
+ const autoId = React8.useId();
7160
+ const fieldId = inputProps.id ?? autoId;
7144
7161
  const localValue = formatValue(type, value);
7145
7162
  const handleChange = (e) => {
7146
7163
  let val = e.target.value;
@@ -7156,7 +7173,7 @@ var Input = React8.forwardRef((props, ref) => {
7156
7173
  onChange(event);
7157
7174
  }
7158
7175
  };
7159
- return /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
7176
+ return /* @__PURE__ */ jsx311(Field, { label, required, htmlFor: fieldId, children: /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
7160
7177
  /* @__PURE__ */ jsxs199(
7161
7178
  "div",
7162
7179
  {
@@ -7167,6 +7184,7 @@ var Input = React8.forwardRef((props, ref) => {
7167
7184
  {
7168
7185
  ...inputProps,
7169
7186
  ref,
7187
+ id: fieldId,
7170
7188
  disabled,
7171
7189
  type: type === "number" ? "text" : type,
7172
7190
  value: localValue,
@@ -7179,7 +7197,7 @@ var Input = React8.forwardRef((props, ref) => {
7179
7197
  }
7180
7198
  ),
7181
7199
  /* @__PURE__ */ jsx311(FieldMessage_default, { validations })
7182
- ] });
7200
+ ] }) });
7183
7201
  });
7184
7202
  Input.displayName = "Input";
7185
7203
  var Input_default = Input;
@@ -7209,16 +7227,96 @@ PasswordInput.displayName = "PasswordInput";
7209
7227
  var PasswordInput_default = PasswordInput;
7210
7228
 
7211
7229
  // src/components/Modal/Modal.tsx
7212
- import React10 from "react";
7230
+ import React11 from "react";
7213
7231
  import { createPortal } from "react-dom";
7232
+
7233
+ // src/tokens/hooks/useOverlayKeyboard.ts
7234
+ import React10 from "react";
7235
+ var FOCUSABLE = [
7236
+ "a[href]",
7237
+ "button:not([disabled])",
7238
+ "input:not([disabled]):not([type='hidden'])",
7239
+ "select:not([disabled])",
7240
+ "textarea:not([disabled])",
7241
+ "[tabindex]:not([tabindex='-1'])"
7242
+ ].join(",");
7243
+ var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
7244
+ // 화면에 없는 것은 제외 (display:none 등)
7245
+ (n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
7246
+ );
7247
+ var useEscapeKey = (enabled, onEscape) => {
7248
+ React10.useEffect(() => {
7249
+ if (!enabled) return;
7250
+ const onKey = (e) => {
7251
+ if (e.key !== "Escape") return;
7252
+ if (e.defaultPrevented) return;
7253
+ e.preventDefault();
7254
+ onEscape();
7255
+ };
7256
+ document.addEventListener("keydown", onKey);
7257
+ return () => document.removeEventListener("keydown", onKey);
7258
+ }, [enabled, onEscape]);
7259
+ };
7260
+ var useFocusTrap = (containerRef, enabled, options = {}) => {
7261
+ const { trap = false, initialFocus } = options;
7262
+ const restoreRef = React10.useRef(null);
7263
+ React10.useEffect(() => {
7264
+ if (!enabled) return;
7265
+ restoreRef.current = document.activeElement;
7266
+ const raf = requestAnimationFrame(() => {
7267
+ const el = containerRef.current;
7268
+ if (!el) return;
7269
+ const target = initialFocus?.current ?? focusableIn(el)[0] ?? el;
7270
+ if (!target.hasAttribute("tabindex") && !focusableIn(el).includes(target)) {
7271
+ target.setAttribute("tabindex", "-1");
7272
+ }
7273
+ target.focus({ preventScroll: true });
7274
+ });
7275
+ return () => {
7276
+ cancelAnimationFrame(raf);
7277
+ const prev = restoreRef.current;
7278
+ if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
7279
+ };
7280
+ }, [enabled, containerRef, initialFocus]);
7281
+ React10.useEffect(() => {
7282
+ if (!enabled || !trap) return;
7283
+ const onKey = (e) => {
7284
+ if (e.key !== "Tab") return;
7285
+ const el = containerRef.current;
7286
+ if (!el) return;
7287
+ const items = focusableIn(el);
7288
+ if (items.length === 0) {
7289
+ e.preventDefault();
7290
+ return;
7291
+ }
7292
+ const first = items[0];
7293
+ const last = items[items.length - 1];
7294
+ const active = document.activeElement;
7295
+ if (e.shiftKey && (active === first || !el.contains(active))) {
7296
+ e.preventDefault();
7297
+ last.focus();
7298
+ } else if (!e.shiftKey && (active === last || !el.contains(active))) {
7299
+ e.preventDefault();
7300
+ first.focus();
7301
+ }
7302
+ };
7303
+ document.addEventListener("keydown", onKey);
7304
+ return () => document.removeEventListener("keydown", onKey);
7305
+ }, [enabled, trap, containerRef]);
7306
+ };
7307
+
7308
+ // src/components/Modal/Modal.tsx
7214
7309
  import { jsx as jsx313 } from "react/jsx-runtime";
7215
7310
  var ANIMATION_DURATION_MS = 200;
7216
7311
  var Modal = (props) => {
7217
7312
  const { isOpen, onClose, children } = props;
7218
- const [mounted, setMounted] = React10.useState(false);
7219
- const [visible, setVisible] = React10.useState(false);
7220
- const [settled, setSettled] = React10.useState(false);
7221
- React10.useEffect(() => {
7313
+ const [mounted, setMounted] = React11.useState(false);
7314
+ const [visible, setVisible] = React11.useState(false);
7315
+ const [settled, setSettled] = React11.useState(false);
7316
+ const boxRef = React11.useRef(null);
7317
+ useEscapeKey(isOpen, onClose);
7318
+ useFocusTrap(boxRef, isOpen && mounted, { trap: true });
7319
+ React11.useEffect(() => {
7222
7320
  if (isOpen) {
7223
7321
  setMounted(true);
7224
7322
  const show = setTimeout(() => setVisible(true), 1);
@@ -7245,6 +7343,7 @@ var Modal = (props) => {
7245
7343
  children: /* @__PURE__ */ jsx313(
7246
7344
  "div",
7247
7345
  {
7346
+ ref: boxRef,
7248
7347
  className: clsx_default("lib-xplat-modal", "modal-box", stateClass, settled && "settled"),
7249
7348
  role: "dialog",
7250
7349
  "aria-modal": "true",
@@ -7261,9 +7360,9 @@ Modal.displayName = "Modal";
7261
7360
  var Modal_default = Modal;
7262
7361
 
7263
7362
  // src/components/DatePicker/SingleDatePicker/index.tsx
7264
- import React11 from "react";
7363
+ import React12 from "react";
7265
7364
  import { Fragment as Fragment4, jsx as jsx314, jsxs as jsxs200 } from "react/jsx-runtime";
7266
- var DayCell2 = React11.memo(
7365
+ var DayCell2 = React12.memo(
7267
7366
  ({
7268
7367
  day,
7269
7368
  disabled,
@@ -7315,26 +7414,26 @@ var SingleDatePicker = (props) => {
7315
7414
  initialYear,
7316
7415
  initialMonth
7317
7416
  );
7318
- const [pickerMode, setPickerMode] = React11.useState("days");
7319
- const [yearRangeStart, setYearRangeStart] = React11.useState(
7417
+ const [pickerMode, setPickerMode] = React12.useState("days");
7418
+ const [yearRangeStart, setYearRangeStart] = React12.useState(
7320
7419
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
7321
7420
  );
7322
- const minTime = React11.useMemo(
7421
+ const minTime = React12.useMemo(
7323
7422
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
7324
7423
  [minDate]
7325
7424
  );
7326
- const maxTime = React11.useMemo(
7425
+ const maxTime = React12.useMemo(
7327
7426
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
7328
7427
  [maxDate]
7329
7428
  );
7330
- const highlightSet = React11.useMemo(() => {
7429
+ const highlightSet = React12.useMemo(() => {
7331
7430
  const set = /* @__PURE__ */ new Set();
7332
7431
  for (const h of highlightDates) {
7333
7432
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
7334
7433
  }
7335
7434
  return set;
7336
7435
  }, [highlightDates]);
7337
- const handleSelect = React11.useCallback(
7436
+ const handleSelect = React12.useCallback(
7338
7437
  (date) => {
7339
7438
  onChange?.(date);
7340
7439
  },
@@ -7463,8 +7562,8 @@ var formatDate = (date) => {
7463
7562
  };
7464
7563
  var InputDatePicker = (props) => {
7465
7564
  const { value, onChange, minDate, maxDate, disabled, locale = "ko", placeholder } = props;
7466
- const [isOpen, setIsOpen] = React12.useState(false);
7467
- const [tempDate, setTempDate] = React12.useState(value ?? /* @__PURE__ */ new Date());
7565
+ const [isOpen, setIsOpen] = React13.useState(false);
7566
+ const [tempDate, setTempDate] = React13.useState(value ?? /* @__PURE__ */ new Date());
7468
7567
  const handleOpen = () => {
7469
7568
  if (disabled) return;
7470
7569
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -7513,23 +7612,27 @@ InputDatePicker.displayName = "InputDatePicker";
7513
7612
  var InputDatePicker_default = InputDatePicker;
7514
7613
 
7515
7614
  // src/components/DatePicker/PopupPicker/index.tsx
7516
- import React16 from "react";
7615
+ import React17 from "react";
7517
7616
 
7518
7617
  // src/components/DatePicker/RangePicker/index.tsx
7519
- import React15 from "react";
7618
+ import React16 from "react";
7520
7619
 
7521
7620
  // src/components/Tab/Tab.tsx
7522
- import React14 from "react";
7621
+ import React15 from "react";
7523
7622
 
7524
7623
  // src/components/Tab/TabItem.tsx
7525
- import React13 from "react";
7624
+ import React14 from "react";
7526
7625
  import { jsx as jsx316 } from "react/jsx-runtime";
7527
- var TabItem = React13.forwardRef((props, ref) => {
7626
+ var TabItem = React14.forwardRef((props, ref) => {
7528
7627
  const { isActive: isActive2, title, onClick } = props;
7529
7628
  return /* @__PURE__ */ jsx316(
7530
- "div",
7629
+ "button",
7531
7630
  {
7532
7631
  ref,
7632
+ type: "button",
7633
+ role: "tab",
7634
+ "aria-selected": isActive2,
7635
+ tabIndex: isActive2 ? 0 : -1,
7533
7636
  className: clsx_default("tab-item", isActive2 ? "active" : null),
7534
7637
  onClick,
7535
7638
  children: title
@@ -7544,44 +7647,64 @@ import { jsx as jsx317, jsxs as jsxs202 } from "react/jsx-runtime";
7544
7647
  var Tab = (props) => {
7545
7648
  const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
7546
7649
  const shape = variant ?? type ?? "default";
7547
- const [underlineStyle, setUnderlineStyle] = React14.useState({
7650
+ const [underlineStyle, setUnderlineStyle] = React15.useState({
7548
7651
  left: 0,
7549
7652
  width: 0
7550
7653
  });
7551
- const itemRefs = React14.useRef([]);
7654
+ const itemRefs = React15.useRef([]);
7655
+ const handleKeyDown = (e) => {
7656
+ const last = tabs.length - 1;
7657
+ let next = null;
7658
+ if (e.key === "ArrowRight") next = activeIndex >= last ? 0 : activeIndex + 1;
7659
+ else if (e.key === "ArrowLeft") next = activeIndex <= 0 ? last : activeIndex - 1;
7660
+ else if (e.key === "Home") next = 0;
7661
+ else if (e.key === "End") next = last;
7662
+ if (next === null) return;
7663
+ e.preventDefault();
7664
+ onChange(tabs[next], next);
7665
+ itemRefs.current[next]?.focus();
7666
+ };
7552
7667
  const handleChangeActiveTab = (tabItem, tabIdx) => {
7553
7668
  onChange(tabItem, tabIdx);
7554
7669
  };
7555
- React14.useEffect(() => {
7670
+ React15.useEffect(() => {
7556
7671
  const el = itemRefs.current[activeIndex];
7557
7672
  if (el) {
7558
7673
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
7559
7674
  }
7560
7675
  }, [activeIndex, tabs.length]);
7561
- return /* @__PURE__ */ jsxs202("div", { className: clsx_default("lib-xplat-tab", `type-${shape}`, size), children: [
7562
- tabs.map((tab, idx) => /* @__PURE__ */ jsx317(
7563
- TabItem_default,
7564
- {
7565
- onClick: () => handleChangeActiveTab(tab, idx),
7566
- isActive: activeIndex === idx,
7567
- ref: (el) => {
7568
- itemRefs.current[idx] = el;
7569
- },
7570
- title: tab.title
7571
- },
7572
- `${tab.value}_${idx}`
7573
- )),
7574
- shape === "toggle" && /* @__PURE__ */ jsx317(
7575
- "div",
7576
- {
7577
- className: "tab-toggle-underline",
7578
- style: {
7579
- left: underlineStyle.left,
7580
- width: underlineStyle.width
7581
- }
7582
- }
7583
- )
7584
- ] });
7676
+ return /* @__PURE__ */ jsxs202(
7677
+ "div",
7678
+ {
7679
+ className: clsx_default("lib-xplat-tab", `type-${shape}`, size),
7680
+ role: "tablist",
7681
+ onKeyDown: handleKeyDown,
7682
+ children: [
7683
+ tabs.map((tab, idx) => /* @__PURE__ */ jsx317(
7684
+ TabItem_default,
7685
+ {
7686
+ onClick: () => handleChangeActiveTab(tab, idx),
7687
+ isActive: activeIndex === idx,
7688
+ ref: (el) => {
7689
+ itemRefs.current[idx] = el;
7690
+ },
7691
+ title: tab.title
7692
+ },
7693
+ `${tab.value}_${idx}`
7694
+ )),
7695
+ shape === "toggle" && /* @__PURE__ */ jsx317(
7696
+ "div",
7697
+ {
7698
+ className: "tab-toggle-underline",
7699
+ style: {
7700
+ left: underlineStyle.left,
7701
+ width: underlineStyle.width
7702
+ }
7703
+ }
7704
+ )
7705
+ ]
7706
+ }
7707
+ );
7585
7708
  };
7586
7709
  Tab.displayName = "Tab";
7587
7710
  var Tab_default = Tab;
@@ -7597,7 +7720,7 @@ var RangePicker = (props) => {
7597
7720
  maxDate,
7598
7721
  locale = "ko"
7599
7722
  } = props;
7600
- const [activeTab, setActiveTab] = React15.useState("start");
7723
+ const [activeTab, setActiveTab] = React16.useState("start");
7601
7724
  const handleStartChange = (date) => {
7602
7725
  if (!date) return;
7603
7726
  const newStart = date > endDate ? endDate : date;
@@ -7682,7 +7805,7 @@ var RangePicker_default = RangePicker;
7682
7805
  import { jsx as jsx319, jsxs as jsxs204 } from "react/jsx-runtime";
7683
7806
  var PopupPicker = (props) => {
7684
7807
  const { component, type, locale } = props;
7685
- const [isOpen, setIsOpen] = React16.useState(false);
7808
+ const [isOpen, setIsOpen] = React17.useState(false);
7686
7809
  const handleClick = () => setIsOpen(true);
7687
7810
  const handleClose = () => setIsOpen(false);
7688
7811
  const handleSingleChange = (date) => {
@@ -7691,7 +7814,7 @@ var PopupPicker = (props) => {
7691
7814
  handleClose();
7692
7815
  };
7693
7816
  return /* @__PURE__ */ jsxs204("div", { className: "lib-xplat-popup-datepicker", children: [
7694
- React16.cloneElement(component, { onClick: handleClick }),
7817
+ React17.cloneElement(component, { onClick: handleClick }),
7695
7818
  /* @__PURE__ */ jsx319(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ jsxs204("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
7696
7819
  /* @__PURE__ */ jsxs204("div", { className: "popup-datepicker-content", children: [
7697
7820
  type === "single" && /* @__PURE__ */ jsx319(
@@ -7750,15 +7873,18 @@ Divider.displayName = "Divider";
7750
7873
  var Divider_default = Divider;
7751
7874
 
7752
7875
  // src/components/Drawer/Drawer.tsx
7753
- import React17 from "react";
7876
+ import React18 from "react";
7754
7877
  import { createPortal as createPortal2 } from "react-dom";
7755
7878
  import { jsx as jsx321, jsxs as jsxs205 } from "react/jsx-runtime";
7756
7879
  var ANIMATION_DURATION_MS2 = 250;
7757
7880
  var Drawer = (props) => {
7758
7881
  const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
7759
- const [mounted, setMounted] = React17.useState(false);
7760
- const [visible, setVisible] = React17.useState(false);
7761
- React17.useEffect(() => {
7882
+ const [mounted, setMounted] = React18.useState(false);
7883
+ const [visible, setVisible] = React18.useState(false);
7884
+ const panelRef = React18.useRef(null);
7885
+ useEscapeKey(isOpen, onClose);
7886
+ useFocusTrap(panelRef, isOpen && mounted, { trap: true });
7887
+ React18.useEffect(() => {
7762
7888
  if (isOpen) {
7763
7889
  setMounted(true);
7764
7890
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -7780,6 +7906,7 @@ var Drawer = (props) => {
7780
7906
  children: /* @__PURE__ */ jsxs205(
7781
7907
  "div",
7782
7908
  {
7909
+ ref: panelRef,
7783
7910
  className: clsx_default("lib-xplat-drawer", placement, size, stateClass),
7784
7911
  role: "dialog",
7785
7912
  "aria-modal": "true",
@@ -7802,7 +7929,7 @@ Drawer.displayName = "Drawer";
7802
7929
  var Drawer_default = Drawer;
7803
7930
 
7804
7931
  // src/components/Dropdown/Dropdown.tsx
7805
- import React20 from "react";
7932
+ import React21 from "react";
7806
7933
 
7807
7934
  // src/tokens/hooks/Portal.tsx
7808
7935
  import ReactDOM from "react-dom";
@@ -7814,13 +7941,13 @@ Portal.displayName = "Portal";
7814
7941
  var Portal_default = Portal;
7815
7942
 
7816
7943
  // src/tokens/hooks/useAutoPosition.ts
7817
- import React18 from "react";
7944
+ import React19 from "react";
7818
7945
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7819
- const [position, setPosition] = React18.useState({
7946
+ const [position, setPosition] = React19.useState({
7820
7947
  position: {},
7821
7948
  direction: "bottom"
7822
7949
  });
7823
- const calculatePosition = React18.useCallback(() => {
7950
+ const calculatePosition = React19.useCallback(() => {
7824
7951
  if (!triggerRef.current || !popRef.current) return;
7825
7952
  const triggerRect = triggerRef.current.getBoundingClientRect();
7826
7953
  const popW = popRef.current.offsetWidth;
@@ -7847,13 +7974,13 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7847
7974
  direction
7848
7975
  });
7849
7976
  }, [triggerRef, popRef]);
7850
- React18.useLayoutEffect(() => {
7977
+ React19.useLayoutEffect(() => {
7851
7978
  if (!enabled) return;
7852
7979
  calculatePosition();
7853
7980
  const raf = requestAnimationFrame(calculatePosition);
7854
7981
  return () => cancelAnimationFrame(raf);
7855
7982
  }, [calculatePosition, enabled]);
7856
- React18.useEffect(() => {
7983
+ React19.useEffect(() => {
7857
7984
  if (!enabled || !popRef.current) return;
7858
7985
  const observer = new ResizeObserver(() => {
7859
7986
  calculatePosition();
@@ -7861,7 +7988,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7861
7988
  observer.observe(popRef.current);
7862
7989
  return () => observer.disconnect();
7863
7990
  }, [calculatePosition, enabled, popRef]);
7864
- React18.useEffect(() => {
7991
+ React19.useEffect(() => {
7865
7992
  if (!enabled) return;
7866
7993
  window.addEventListener("resize", calculatePosition);
7867
7994
  window.addEventListener("scroll", calculatePosition, true);
@@ -7875,9 +8002,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7875
8002
  var useAutoPosition_default = useAutoPosition;
7876
8003
 
7877
8004
  // src/tokens/hooks/useClickOutside.ts
7878
- import React19 from "react";
8005
+ import React20 from "react";
7879
8006
  var useClickOutside = (refs, handler, enabled = true) => {
7880
- React19.useEffect(() => {
8007
+ React20.useEffect(() => {
7881
8008
  if (!enabled) return;
7882
8009
  const refArray = Array.isArray(refs) ? refs : [refs];
7883
8010
  const listener = (event) => {
@@ -7903,14 +8030,18 @@ var useClickOutside_default = useClickOutside;
7903
8030
  import { jsx as jsx322, jsxs as jsxs206 } from "react/jsx-runtime";
7904
8031
  var Dropdown = (props) => {
7905
8032
  const { items, children } = props;
7906
- const [isOpen, setIsOpen] = React20.useState(false);
7907
- const [mounted, setMounted] = React20.useState(false);
7908
- const [visible, setVisible] = React20.useState(false);
7909
- const triggerRef = React20.useRef(null);
7910
- const menuRef = React20.useRef(null);
8033
+ const [isOpen, setIsOpen] = React21.useState(false);
8034
+ const [mounted, setMounted] = React21.useState(false);
8035
+ const [visible, setVisible] = React21.useState(false);
8036
+ const triggerRef = React21.useRef(null);
8037
+ const menuRef = React21.useRef(null);
7911
8038
  const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
7912
8039
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
7913
- React20.useEffect(() => {
8040
+ useEscapeKey(isOpen, () => {
8041
+ setIsOpen(false);
8042
+ triggerRef.current?.focus({ preventScroll: true });
8043
+ });
8044
+ React21.useEffect(() => {
7914
8045
  if (isOpen) {
7915
8046
  setMounted(true);
7916
8047
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -7964,7 +8095,7 @@ Dropdown.displayName = "Dropdown";
7964
8095
  var Dropdown_default = Dropdown;
7965
8096
 
7966
8097
  // src/components/Editor/Editor.tsx
7967
- import React21 from "react";
8098
+ import React22 from "react";
7968
8099
  import { jsx as jsx323, jsxs as jsxs207 } from "react/jsx-runtime";
7969
8100
  var DEFAULT_TOOLBAR = [
7970
8101
  "bold",
@@ -8014,6 +8145,15 @@ var ALLOWED_ATTRS = {
8014
8145
  a: ["href", "target", "rel"],
8015
8146
  img: ["src", "alt"]
8016
8147
  };
8148
+ var DROP_WITH_CONTENT = /* @__PURE__ */ new Set([
8149
+ "script",
8150
+ "style",
8151
+ "noscript",
8152
+ "iframe",
8153
+ "object",
8154
+ "embed",
8155
+ "template"
8156
+ ]);
8017
8157
  var sanitizeHtml = (input) => {
8018
8158
  const doc = new DOMParser().parseFromString(`<div>${input}</div>`, "text/html");
8019
8159
  const root = doc.body.firstElementChild;
@@ -8022,6 +8162,10 @@ var sanitizeHtml = (input) => {
8022
8162
  const children = Array.from(node.children);
8023
8163
  for (const child of children) {
8024
8164
  const tag = child.tagName.toLowerCase();
8165
+ if (DROP_WITH_CONTENT.has(tag)) {
8166
+ node.removeChild(child);
8167
+ continue;
8168
+ }
8025
8169
  if (!ALLOWED_TAGS.has(tag)) {
8026
8170
  while (child.firstChild) node.insertBefore(child.firstChild, child);
8027
8171
  node.removeChild(child);
@@ -8072,26 +8216,30 @@ var Editor = (props) => {
8072
8216
  onImageUpload,
8073
8217
  minHeight = 200
8074
8218
  } = props;
8075
- const editorRef = React21.useRef(null);
8076
- const lastRangeRef = React21.useRef(null);
8077
- const composingRef = React21.useRef(false);
8078
- const [isFocused, setIsFocused] = React21.useState(false);
8079
- const [isEmpty, setIsEmpty] = React21.useState(!value);
8080
- const [activeFormats, setActiveFormats] = React21.useState(/* @__PURE__ */ new Set());
8081
- const [slashOpen, setSlashOpen] = React21.useState(false);
8082
- const [slashFilter, setSlashFilter] = React21.useState("");
8083
- const [slashIdx, setSlashIdx] = React21.useState(0);
8084
- const [slashPos, setSlashPos] = React21.useState({ top: 0, left: 0 });
8085
- const slashStartRangeRef = React21.useRef(null);
8086
- const [linkOpen, setLinkOpen] = React21.useState(false);
8087
- const [linkValue, setLinkValue] = React21.useState("");
8088
- const [linkPos, setLinkPos] = React21.useState({ top: 0, left: 0 });
8089
- React21.useEffect(() => {
8090
- if (!editorRef.current) return;
8091
- if (editorRef.current.innerHTML !== value) {
8092
- editorRef.current.innerHTML = sanitizeHtml(value || "");
8093
- updateEmpty();
8094
- }
8219
+ const editorRef = React22.useRef(null);
8220
+ const lastRangeRef = React22.useRef(null);
8221
+ const composingRef = React22.useRef(false);
8222
+ const [isFocused, setIsFocused] = React22.useState(false);
8223
+ const [isEmpty, setIsEmpty] = React22.useState(!value);
8224
+ const [activeFormats, setActiveFormats] = React22.useState(/* @__PURE__ */ new Set());
8225
+ const [slashOpen, setSlashOpen] = React22.useState(false);
8226
+ const [slashFilter, setSlashFilter] = React22.useState("");
8227
+ const [slashIdx, setSlashIdx] = React22.useState(0);
8228
+ const [slashPos, setSlashPos] = React22.useState({ top: 0, left: 0 });
8229
+ const slashStartRangeRef = React22.useRef(null);
8230
+ const [linkOpen, setLinkOpen] = React22.useState(false);
8231
+ const [linkValue, setLinkValue] = React22.useState("");
8232
+ const [linkPos, setLinkPos] = React22.useState({ top: 0, left: 0 });
8233
+ const lastEmittedRef = React22.useRef(null);
8234
+ React22.useEffect(() => {
8235
+ const el = editorRef.current;
8236
+ if (!el) return;
8237
+ if (value === lastEmittedRef.current) return;
8238
+ if (el.innerHTML === value) return;
8239
+ el.innerHTML = sanitizeHtml(value || "");
8240
+ if (!el.firstChild) el.innerHTML = "<p><br></p>";
8241
+ lastEmittedRef.current = null;
8242
+ updateEmpty();
8095
8243
  }, [value]);
8096
8244
  const updateEmpty = () => {
8097
8245
  const el = editorRef.current;
@@ -8107,10 +8255,19 @@ var Editor = (props) => {
8107
8255
  }
8108
8256
  };
8109
8257
  const restoreSelection = () => {
8110
- if (!lastRangeRef.current) return;
8258
+ const range = lastRangeRef.current;
8259
+ if (!range) return;
8260
+ if (!editorRef.current?.contains(range.startContainer)) {
8261
+ lastRangeRef.current = null;
8262
+ return;
8263
+ }
8111
8264
  const sel = window.getSelection();
8112
- sel?.removeAllRanges();
8113
- sel?.addRange(lastRangeRef.current);
8265
+ try {
8266
+ sel?.removeAllRanges();
8267
+ sel?.addRange(range);
8268
+ } catch {
8269
+ lastRangeRef.current = null;
8270
+ }
8114
8271
  };
8115
8272
  const updateActiveFormats = () => {
8116
8273
  if (!editorRef.current) return;
@@ -8139,6 +8296,96 @@ var Editor = (props) => {
8139
8296
  const setBlock = (tag) => {
8140
8297
  exec("formatBlock", tag);
8141
8298
  };
8299
+ const closestPre = () => {
8300
+ const sel = window.getSelection();
8301
+ const node = sel?.anchorNode;
8302
+ if (!node || !editorRef.current?.contains(node)) return null;
8303
+ const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
8304
+ return el?.closest("pre") ?? null;
8305
+ };
8306
+ const insertCodeBlock = () => {
8307
+ const el = editorRef.current;
8308
+ const sel = window.getSelection();
8309
+ if (!el || !sel || sel.rangeCount === 0) return;
8310
+ const existing = closestPre();
8311
+ if (existing) {
8312
+ const p = document.createElement("p");
8313
+ p.textContent = existing.textContent || "";
8314
+ if (!p.textContent) p.innerHTML = "<br>";
8315
+ existing.replaceWith(p);
8316
+ placeCaretAtEnd(p);
8317
+ handleInput();
8318
+ return;
8319
+ }
8320
+ const range = sel.getRangeAt(0);
8321
+ const frag = range.cloneContents();
8322
+ const holder = document.createElement("div");
8323
+ holder.appendChild(frag);
8324
+ const BLOCK = /^(p|div|h[1-6]|li|blockquote|pre|tr)$/i;
8325
+ const linesOf = (node) => {
8326
+ const out = [];
8327
+ let cur = "";
8328
+ for (const child of Array.from(node.childNodes)) {
8329
+ if (child.nodeType === Node.TEXT_NODE) {
8330
+ cur += child.textContent || "";
8331
+ } else if (child.nodeName === "BR") {
8332
+ out.push(cur);
8333
+ cur = "";
8334
+ } else if (BLOCK.test(child.nodeName)) {
8335
+ if (cur) {
8336
+ out.push(cur);
8337
+ cur = "";
8338
+ }
8339
+ const sub = linesOf(child);
8340
+ out.push(...sub.length > 0 ? sub : [""]);
8341
+ } else {
8342
+ cur += linesOf(child).join("\n");
8343
+ }
8344
+ }
8345
+ if (cur) out.push(cur);
8346
+ return out;
8347
+ };
8348
+ const text = linesOf(holder).join("\n").replace(/\n+$/, "");
8349
+ const pre = document.createElement("pre");
8350
+ const code = document.createElement("code");
8351
+ code.textContent = text || "";
8352
+ pre.appendChild(code);
8353
+ range.deleteContents();
8354
+ range.insertNode(pre);
8355
+ ensureParagraphAfter(pre);
8356
+ placeCaretAtEnd(code);
8357
+ handleInput();
8358
+ };
8359
+ const insertTextAtCaret = (text) => {
8360
+ const sel = window.getSelection();
8361
+ if (!sel || sel.rangeCount === 0) return;
8362
+ const range = sel.getRangeAt(0);
8363
+ range.deleteContents();
8364
+ const node = document.createTextNode(text);
8365
+ range.insertNode(node);
8366
+ range.setStartAfter(node);
8367
+ range.collapse(true);
8368
+ sel.removeAllRanges();
8369
+ sel.addRange(range);
8370
+ handleInput();
8371
+ };
8372
+ const ensureParagraphAfter = (node) => {
8373
+ const next = node.nextElementSibling;
8374
+ if (next && next.tagName === "P") return;
8375
+ const p = document.createElement("p");
8376
+ p.innerHTML = "<br>";
8377
+ node.after(p);
8378
+ };
8379
+ const placeCaretAtEnd = (node) => {
8380
+ const sel = window.getSelection();
8381
+ if (!sel) return;
8382
+ const r2 = document.createRange();
8383
+ r2.selectNodeContents(node);
8384
+ r2.collapse(false);
8385
+ sel.removeAllRanges();
8386
+ sel.addRange(r2);
8387
+ editorRef.current?.focus();
8388
+ };
8142
8389
  const insertDivider = () => {
8143
8390
  exec("insertHorizontalRule");
8144
8391
  const el = editorRef.current;
@@ -8185,7 +8432,9 @@ var Editor = (props) => {
8185
8432
  const range = sel.getRangeAt(0);
8186
8433
  slashStartRangeRef.current = range.cloneRange();
8187
8434
  const rect = range.getBoundingClientRect();
8188
- const editorRect = editorRef.current.getBoundingClientRect();
8435
+ const editorEl = editorRef.current;
8436
+ if (!editorEl) return;
8437
+ const editorRect = editorEl.getBoundingClientRect();
8189
8438
  setSlashPos({
8190
8439
  top: rect.bottom - editorRect.top + 4,
8191
8440
  left: rect.left - editorRect.left
@@ -8200,7 +8449,7 @@ var Editor = (props) => {
8200
8449
  setSlashIdx(0);
8201
8450
  slashStartRangeRef.current = null;
8202
8451
  };
8203
- const filteredSlashItems = React21.useMemo(() => {
8452
+ const filteredSlashItems = React22.useMemo(() => {
8204
8453
  if (!slashFilter) return SLASH_ITEMS;
8205
8454
  const f = slashFilter.toLowerCase();
8206
8455
  return SLASH_ITEMS.filter((it) => it.label.toLowerCase().includes(f) || it.key.includes(f));
@@ -8243,7 +8492,7 @@ var Editor = (props) => {
8243
8492
  setBlock("blockquote");
8244
8493
  break;
8245
8494
  case "code-block":
8246
- setBlock("pre");
8495
+ insertCodeBlock();
8247
8496
  break;
8248
8497
  case "divider":
8249
8498
  insertDivider();
@@ -8261,7 +8510,9 @@ var Editor = (props) => {
8261
8510
  if (!sel || sel.rangeCount === 0) return;
8262
8511
  const range = sel.getRangeAt(0);
8263
8512
  const rect = range.getBoundingClientRect();
8264
- const editorRect = editorRef.current.getBoundingClientRect();
8513
+ const editorEl2 = editorRef.current;
8514
+ if (!editorEl2) return;
8515
+ const editorRect = editorEl2.getBoundingClientRect();
8265
8516
  setLinkPos({
8266
8517
  top: rect.bottom - editorRect.top + 4,
8267
8518
  left: rect.left - editorRect.left
@@ -8294,13 +8545,13 @@ var Editor = (props) => {
8294
8545
  if (node.nodeType !== Node.TEXT_NODE) return false;
8295
8546
  const text = (node.textContent || "").slice(0, range.startOffset);
8296
8547
  const patterns = [
8297
- [/^###\s$/, () => setBlock("h3")],
8298
- [/^##\s$/, () => setBlock("h2")],
8299
- [/^#\s$/, () => setBlock("h1")],
8300
- [/^-\s$/, () => exec("insertUnorderedList")],
8301
- [/^\*\s$/, () => exec("insertUnorderedList")],
8302
- [/^1\.\s$/, () => exec("insertOrderedList")],
8303
- [/^>\s$/, () => setBlock("blockquote")]
8548
+ [/^###$/, () => setBlock("h3")],
8549
+ [/^##$/, () => setBlock("h2")],
8550
+ [/^#$/, () => setBlock("h1")],
8551
+ [/^-$/, () => exec("insertUnorderedList")],
8552
+ [/^\*$/, () => exec("insertUnorderedList")],
8553
+ [/^1\.$/, () => exec("insertOrderedList")],
8554
+ [/^>$/, () => setBlock("blockquote")]
8304
8555
  ];
8305
8556
  for (const [re, fn] of patterns) {
8306
8557
  if (re.test(text)) {
@@ -8320,7 +8571,9 @@ var Editor = (props) => {
8320
8571
  if (composingRef.current) return;
8321
8572
  const el = editorRef.current;
8322
8573
  if (!el) return;
8323
- onChange?.(el.innerHTML);
8574
+ const html = el.innerHTML;
8575
+ lastEmittedRef.current = html;
8576
+ onChange?.(html);
8324
8577
  updateEmpty();
8325
8578
  updateActiveFormats();
8326
8579
  if (slashOpen) {
@@ -8348,6 +8601,31 @@ var Editor = (props) => {
8348
8601
  };
8349
8602
  const handleKeyDown = (e) => {
8350
8603
  if (readOnly) return;
8604
+ if (composingRef.current || e.nativeEvent.isComposing || e.keyCode === 229) return;
8605
+ const pre = closestPre();
8606
+ if (pre && !slashOpen) {
8607
+ if (e.key === "Enter" && !e.shiftKey) {
8608
+ const text = pre.textContent || "";
8609
+ if (text.endsWith("\n\n")) {
8610
+ e.preventDefault();
8611
+ const code = pre.querySelector("code") ?? pre;
8612
+ code.textContent = text.replace(/\n\n$/, "");
8613
+ ensureParagraphAfter(pre);
8614
+ const next = pre.nextElementSibling;
8615
+ if (next) placeCaretAtEnd(next);
8616
+ handleInput();
8617
+ return;
8618
+ }
8619
+ e.preventDefault();
8620
+ insertTextAtCaret("\n");
8621
+ return;
8622
+ }
8623
+ if (e.key === "Tab") {
8624
+ e.preventDefault();
8625
+ insertTextAtCaret(" ");
8626
+ return;
8627
+ }
8628
+ }
8351
8629
  if (slashOpen) {
8352
8630
  if (e.key === "ArrowDown") {
8353
8631
  e.preventDefault();
@@ -8394,6 +8672,7 @@ var Editor = (props) => {
8394
8672
  return;
8395
8673
  }
8396
8674
  }
8675
+ if (pre) return;
8397
8676
  if (enableSlashCommand && e.key === "/") {
8398
8677
  setTimeout(openSlashMenu, 0);
8399
8678
  }
@@ -8406,8 +8685,12 @@ var Editor = (props) => {
8406
8685
  const handlePaste = (e) => {
8407
8686
  if (readOnly) return;
8408
8687
  e.preventDefault();
8409
- const html = e.clipboardData.getData("text/html");
8410
8688
  const text = e.clipboardData.getData("text/plain");
8689
+ if (closestPre()) {
8690
+ insertTextAtCaret(text);
8691
+ return;
8692
+ }
8693
+ const html = e.clipboardData.getData("text/html");
8411
8694
  const clean = html ? sanitizeHtml(html) : escapeHtml(text);
8412
8695
  document.execCommand("insertHTML", false, clean);
8413
8696
  handleInput();
@@ -8431,6 +8714,7 @@ var Editor = (props) => {
8431
8714
  updateActiveFormats();
8432
8715
  };
8433
8716
  const onToolbarAction = (item) => {
8717
+ if (closestPre() && item !== "code-block") return;
8434
8718
  switch (item) {
8435
8719
  case "bold":
8436
8720
  exec("bold");
@@ -8472,7 +8756,7 @@ var Editor = (props) => {
8472
8756
  setBlock("blockquote");
8473
8757
  break;
8474
8758
  case "code-block":
8475
- setBlock("pre");
8759
+ insertCodeBlock();
8476
8760
  break;
8477
8761
  case "link":
8478
8762
  openLinkEditor();
@@ -8502,6 +8786,10 @@ var Editor = (props) => {
8502
8786
  ref: editorRef,
8503
8787
  contentEditable: !readOnly,
8504
8788
  suppressContentEditableWarning: true,
8789
+ role: "textbox",
8790
+ "aria-multiline": "true",
8791
+ "aria-readonly": readOnly || void 0,
8792
+ "aria-label": placeholder,
8505
8793
  className: "lib-xplat-editor__editable",
8506
8794
  onInput: handleInput,
8507
8795
  onKeyDown: handleKeyDown,
@@ -8593,7 +8881,7 @@ var EditorToolbar = ({ items, active, onAction }) => {
8593
8881
  )) });
8594
8882
  };
8595
8883
  var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
8596
- React21.useEffect(() => {
8884
+ React22.useEffect(() => {
8597
8885
  const handleClickOutside = (e) => {
8598
8886
  const target = e.target;
8599
8887
  const menu = document.querySelector(".lib-xplat-editor__slash-menu");
@@ -8627,8 +8915,8 @@ var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
8627
8915
  );
8628
8916
  };
8629
8917
  var LinkPopover = ({ position, value, onChange, onConfirm, onClose }) => {
8630
- const inputRef = React21.useRef(null);
8631
- React21.useEffect(() => {
8918
+ const inputRef = React22.useRef(null);
8919
+ React22.useEffect(() => {
8632
8920
  inputRef.current?.focus();
8633
8921
  }, []);
8634
8922
  return /* @__PURE__ */ jsxs207(
@@ -8686,7 +8974,7 @@ EmptyState.displayName = "EmptyState";
8686
8974
  var EmptyState_default = EmptyState;
8687
8975
 
8688
8976
  // src/components/FileUpload/FileUpload.tsx
8689
- import React22 from "react";
8977
+ import React23 from "react";
8690
8978
  import { jsx as jsx325, jsxs as jsxs209 } from "react/jsx-runtime";
8691
8979
  var FileUpload = (props) => {
8692
8980
  const {
@@ -8698,8 +8986,8 @@ var FileUpload = (props) => {
8698
8986
  description,
8699
8987
  validations
8700
8988
  } = props;
8701
- const [isDragOver, setIsDragOver] = React22.useState(false);
8702
- const inputRef = React22.useRef(null);
8989
+ const [isDragOver, setIsDragOver] = React23.useState(false);
8990
+ const inputRef = React23.useRef(null);
8703
8991
  const handleFiles = (fileList) => {
8704
8992
  let files = Array.from(fileList);
8705
8993
  if (maxSize) {
@@ -8761,10 +9049,10 @@ FileUpload.displayName = "FileUpload";
8761
9049
  var FileUpload_default = FileUpload;
8762
9050
 
8763
9051
  // src/components/HtmlTypeWriter/HtmlTypeWriter.tsx
8764
- import React24 from "react";
9052
+ import React25 from "react";
8765
9053
 
8766
9054
  // src/components/HtmlTypeWriter/utils.ts
8767
- import React23 from "react";
9055
+ import React24 from "react";
8768
9056
  var voidTags = /* @__PURE__ */ new Set([
8769
9057
  "br",
8770
9058
  "img",
@@ -8832,15 +9120,15 @@ var convertNodeToReactWithRange = (node, typedLen, rangeMap) => {
8832
9120
  props[attr.name] = attr.value;
8833
9121
  });
8834
9122
  if (voidTags.has(tag)) {
8835
- return React23.createElement(tag, props);
9123
+ return React24.createElement(tag, props);
8836
9124
  }
8837
9125
  const children = Array.from(element.childNodes).map((child) => convertNodeToReactWithRange(child, typedLen, rangeMap)).filter((n) => n != null);
8838
- return React23.createElement(tag, props, ...children);
9126
+ return React24.createElement(tag, props, ...children);
8839
9127
  };
8840
9128
  var htmlToReactProgressive = (root, typedLen, rangeMap) => {
8841
9129
  const nodes = Array.from(root.childNodes).map((child, idx) => {
8842
9130
  const node = convertNodeToReactWithRange(child, typedLen, rangeMap);
8843
- return node == null ? null : React23.createElement(React23.Fragment, { key: idx }, node);
9131
+ return node == null ? null : React24.createElement(React24.Fragment, { key: idx }, node);
8844
9132
  }).filter(Boolean);
8845
9133
  return nodes.length === 0 ? null : nodes;
8846
9134
  };
@@ -8853,20 +9141,20 @@ var HtmlTypeWriter = ({
8853
9141
  onDone,
8854
9142
  onChange
8855
9143
  }) => {
8856
- const [typedLen, setTypedLen] = React24.useState(0);
8857
- const doneCalledRef = React24.useRef(false);
8858
- const { doc, rangeMap, totalLength } = React24.useMemo(() => {
9144
+ const [typedLen, setTypedLen] = React25.useState(0);
9145
+ const doneCalledRef = React25.useRef(false);
9146
+ const { doc, rangeMap, totalLength } = React25.useMemo(() => {
8859
9147
  if (typeof window === "undefined") return { doc: null, rangeMap: /* @__PURE__ */ new Map(), totalLength: 0 };
8860
9148
  const decoded = decodeHtmlEntities(html);
8861
9149
  const doc2 = new DOMParser().parseFromString(decoded, "text/html");
8862
9150
  const { rangeMap: rangeMap2, totalLength: totalLength2 } = buildRangeMap(doc2.body);
8863
9151
  return { doc: doc2, rangeMap: rangeMap2, totalLength: totalLength2 };
8864
9152
  }, [html]);
8865
- React24.useEffect(() => {
9153
+ React25.useEffect(() => {
8866
9154
  setTypedLen(0);
8867
9155
  doneCalledRef.current = false;
8868
9156
  }, [html]);
8869
- React24.useEffect(() => {
9157
+ React25.useEffect(() => {
8870
9158
  if (!totalLength) return;
8871
9159
  if (typedLen >= totalLength) return;
8872
9160
  const timer = window.setInterval(() => {
@@ -8874,18 +9162,18 @@ var HtmlTypeWriter = ({
8874
9162
  }, duration);
8875
9163
  return () => window.clearInterval(timer);
8876
9164
  }, [typedLen, totalLength, duration]);
8877
- React24.useEffect(() => {
9165
+ React25.useEffect(() => {
8878
9166
  if (typedLen > 0 && typedLen < totalLength) {
8879
9167
  onChange?.();
8880
9168
  }
8881
9169
  }, [typedLen, totalLength, onChange]);
8882
- React24.useEffect(() => {
9170
+ React25.useEffect(() => {
8883
9171
  if (typedLen === totalLength && totalLength > 0 && !doneCalledRef.current) {
8884
9172
  doneCalledRef.current = true;
8885
9173
  onDone?.();
8886
9174
  }
8887
9175
  }, [typedLen, totalLength, onDone]);
8888
- const parsed = React24.useMemo(
9176
+ const parsed = React25.useMemo(
8889
9177
  () => doc ? htmlToReactProgressive(doc.body, typedLen, rangeMap) : null,
8890
9178
  [doc, typedLen, rangeMap]
8891
9179
  );
@@ -8895,12 +9183,12 @@ HtmlTypeWriter.displayName = "HtmlTypeWriter";
8895
9183
  var HtmlTypeWriter_default = HtmlTypeWriter;
8896
9184
 
8897
9185
  // src/components/ImageSelector/ImageSelector.tsx
8898
- import React25 from "react";
9186
+ import React26 from "react";
8899
9187
  import { jsx as jsx327, jsxs as jsxs210 } from "react/jsx-runtime";
8900
9188
  var ImageSelector = (props) => {
8901
9189
  const { value, label, onChange, validations } = props;
8902
- const [previewUrl, setPreviewUrl] = React25.useState();
8903
- React25.useEffect(() => {
9190
+ const [previewUrl, setPreviewUrl] = React26.useState();
9191
+ React26.useEffect(() => {
8904
9192
  if (!value) {
8905
9193
  setPreviewUrl(void 0);
8906
9194
  return;
@@ -8909,7 +9197,7 @@ var ImageSelector = (props) => {
8909
9197
  setPreviewUrl(url);
8910
9198
  return () => URL.revokeObjectURL(url);
8911
9199
  }, [value]);
8912
- const inputRef = React25.useRef(null);
9200
+ const inputRef = React26.useRef(null);
8913
9201
  const handleFileChange = (e) => {
8914
9202
  const selectedFile = e.target.files?.[0];
8915
9203
  if (selectedFile) {
@@ -9092,17 +9380,21 @@ Pagination.displayName = "Pagination";
9092
9380
  var Pagination_default = Pagination;
9093
9381
 
9094
9382
  // src/components/PopOver/PopOver.tsx
9095
- import React26 from "react";
9383
+ import React27 from "react";
9096
9384
  import { jsx as jsx332, jsxs as jsxs213 } from "react/jsx-runtime";
9097
9385
  var PopOver = (props) => {
9098
9386
  const { children, isOpen, onClose, PopOverEl } = props;
9099
- const popRef = React26.useRef(null);
9100
- const triggerRef = React26.useRef(null);
9101
- const [localOpen, setLocalOpen] = React26.useState(false);
9102
- const [eventTrigger, setEventTrigger] = React26.useState(false);
9387
+ const popRef = React27.useRef(null);
9388
+ const triggerRef = React27.useRef(null);
9389
+ const [localOpen, setLocalOpen] = React27.useState(false);
9390
+ const [eventTrigger, setEventTrigger] = React27.useState(false);
9103
9391
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
9392
+ useEscapeKey(isOpen, () => {
9393
+ onClose();
9394
+ triggerRef.current?.focus({ preventScroll: true });
9395
+ });
9104
9396
  const position = useAutoPosition_default(triggerRef, popRef, localOpen);
9105
- React26.useEffect(() => {
9397
+ React27.useEffect(() => {
9106
9398
  if (isOpen) {
9107
9399
  setLocalOpen(isOpen);
9108
9400
  setTimeout(() => {
@@ -9187,12 +9479,12 @@ Progress.displayName = "Progress";
9187
9479
  var Progress_default = Progress;
9188
9480
 
9189
9481
  // src/components/Radio/RadioGroupContext.tsx
9190
- import React27 from "react";
9191
- var RadioGroupContext = React27.createContext(
9482
+ import React28 from "react";
9483
+ var RadioGroupContext = React28.createContext(
9192
9484
  null
9193
9485
  );
9194
9486
  var useRadioGroupContext = () => {
9195
- return React27.useContext(RadioGroupContext);
9487
+ return React28.useContext(RadioGroupContext);
9196
9488
  };
9197
9489
  var RadioGroupContext_default = RadioGroupContext;
9198
9490
 
@@ -9268,19 +9560,19 @@ RadioGroup.displayName = "RadioGroup";
9268
9560
  var RadioGroup_default = RadioGroup;
9269
9561
 
9270
9562
  // src/components/Select/Select.tsx
9271
- import React30 from "react";
9563
+ import React31 from "react";
9272
9564
 
9273
9565
  // src/components/Select/context.ts
9274
- import React28 from "react";
9275
- var SelectContext = React28.createContext(null);
9566
+ import React29 from "react";
9567
+ var SelectContext = React29.createContext(null);
9276
9568
  var context_default = SelectContext;
9277
9569
 
9278
9570
  // src/components/Select/SelectItem.tsx
9279
- import React29 from "react";
9571
+ import React30 from "react";
9280
9572
  import { jsx as jsx336 } from "react/jsx-runtime";
9281
9573
  var SelectItem = (props) => {
9282
9574
  const { children, value, onClick, disabled = false } = props;
9283
- const ctx = React29.useContext(context_default);
9575
+ const ctx = React30.useContext(context_default);
9284
9576
  const handleClick = (e) => {
9285
9577
  e.preventDefault();
9286
9578
  e.stopPropagation();
@@ -9320,32 +9612,37 @@ var SelectRoot = (props) => {
9320
9612
  onChange,
9321
9613
  children,
9322
9614
  disabled = false,
9615
+ searchable = false,
9616
+ searchPlaceholder = "\uAC80\uC0C9",
9323
9617
  error = false,
9324
9618
  validations,
9619
+ label,
9620
+ required,
9325
9621
  size = "md"
9326
9622
  } = props;
9327
- const itemChildren = React30.Children.toArray(children).filter(
9328
- (child) => React30.isValidElement(child) && child.type === SelectItem_default
9623
+ const fieldId = React31.useId();
9624
+ const itemChildren = React31.Children.toArray(children).filter(
9625
+ (child) => React31.isValidElement(child) && child.type === SelectItem_default
9329
9626
  );
9330
9627
  const isControlled = valueProp !== void 0;
9331
- const [isOpen, setOpen] = React30.useState(false);
9332
- const [uncontrolledLabel, setUncontrolledLabel] = React30.useState(null);
9333
- const [uncontrolledValue, setUncontrolledValue] = React30.useState(void 0);
9334
- const controlledLabel = React30.useMemo(() => {
9628
+ const [isOpen, setOpen] = React31.useState(false);
9629
+ const [uncontrolledLabel, setUncontrolledLabel] = React31.useState(null);
9630
+ const [uncontrolledValue, setUncontrolledValue] = React31.useState(void 0);
9631
+ const controlledLabel = React31.useMemo(() => {
9335
9632
  if (!isControlled) return null;
9336
9633
  const match = itemChildren.find((child) => child.props.value === valueProp);
9337
9634
  return match ? match.props.children : null;
9338
9635
  }, [isControlled, valueProp, itemChildren]);
9339
9636
  const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
9340
9637
  const selectedValue = isControlled ? valueProp : uncontrolledValue;
9341
- const triggerRef = React30.useRef(null);
9342
- const contentRef = React30.useRef(null);
9343
- const [mounted, setMounted] = React30.useState(false);
9344
- const [visible, setVisible] = React30.useState(false);
9345
- React30.useEffect(() => {
9638
+ const triggerRef = React31.useRef(null);
9639
+ const contentRef = React31.useRef(null);
9640
+ const [mounted, setMounted] = React31.useState(false);
9641
+ const [visible, setVisible] = React31.useState(false);
9642
+ React31.useEffect(() => {
9346
9643
  if (disabled && isOpen) setOpen(false);
9347
9644
  }, [disabled, isOpen]);
9348
- React30.useEffect(() => {
9645
+ React31.useEffect(() => {
9349
9646
  if (isOpen) {
9350
9647
  setMounted(true);
9351
9648
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -9355,22 +9652,42 @@ var SelectRoot = (props) => {
9355
9652
  const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS3);
9356
9653
  return () => clearTimeout(t);
9357
9654
  }, [isOpen]);
9358
- const open = React30.useCallback(() => setOpen(true), []);
9359
- const close = React30.useCallback(() => setOpen(false), []);
9360
- const toggle = React30.useCallback(() => setOpen((prev) => !prev), []);
9655
+ const [query, setQuery] = React31.useState("");
9656
+ const textOf = (node) => {
9657
+ if (node === null || node === void 0 || typeof node === "boolean") return "";
9658
+ if (typeof node === "string" || typeof node === "number") return String(node);
9659
+ if (Array.isArray(node)) return node.map(textOf).join("");
9660
+ if (React31.isValidElement(node)) return textOf(node.props.children);
9661
+ return "";
9662
+ };
9663
+ const visibleItems = React31.useMemo(() => {
9664
+ if (!searchable || !query.trim()) return itemChildren;
9665
+ const q = query.trim().toLowerCase();
9666
+ return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
9667
+ }, [searchable, query, itemChildren]);
9668
+ const open = React31.useCallback(() => setOpen(true), []);
9669
+ const close = React31.useCallback(() => {
9670
+ setOpen(false);
9671
+ setQuery("");
9672
+ }, []);
9673
+ const toggle = React31.useCallback(() => setOpen((prev) => !prev), []);
9361
9674
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
9675
+ useEscapeKey(isOpen, () => {
9676
+ close();
9677
+ triggerRef.current?.focus({ preventScroll: true });
9678
+ });
9362
9679
  const position = useAutoPosition_default(triggerRef, contentRef, mounted);
9363
- const setSelected = React30.useCallback(
9364
- (label, itemValue) => {
9680
+ const setSelected = React31.useCallback(
9681
+ (label2, itemValue) => {
9365
9682
  if (!isControlled) {
9366
- setUncontrolledLabel(label);
9683
+ setUncontrolledLabel(label2);
9367
9684
  setUncontrolledValue(itemValue);
9368
9685
  }
9369
- onChange?.(itemValue, label);
9686
+ onChange?.(itemValue, label2);
9370
9687
  },
9371
9688
  [isControlled, onChange]
9372
9689
  );
9373
- const ctxValue = React30.useMemo(
9690
+ const ctxValue = React31.useMemo(
9374
9691
  () => ({
9375
9692
  isOpen,
9376
9693
  mounted,
@@ -9406,6 +9723,7 @@ var SelectRoot = (props) => {
9406
9723
  /* @__PURE__ */ jsxs216(
9407
9724
  "div",
9408
9725
  {
9726
+ id: fieldId,
9409
9727
  ref: triggerRef,
9410
9728
  className: clsx_default(
9411
9729
  "select-trigger",
@@ -9448,20 +9766,33 @@ var SelectRoot = (props) => {
9448
9766
  ]
9449
9767
  }
9450
9768
  ),
9451
- mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsx337(
9769
+ mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsxs216(
9452
9770
  "div",
9453
9771
  {
9454
9772
  className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
9455
9773
  ref: contentRef,
9456
9774
  style: { ...position.position, width: triggerRef.current?.offsetWidth },
9457
9775
  role: "listbox",
9458
- children: /* @__PURE__ */ jsx337(context_default.Provider, { value: ctxValue, children: itemChildren })
9776
+ children: [
9777
+ searchable && /* @__PURE__ */ jsx337("div", { className: "select-search", children: /* @__PURE__ */ jsx337(
9778
+ "input",
9779
+ {
9780
+ type: "text",
9781
+ value: query,
9782
+ placeholder: searchPlaceholder,
9783
+ onChange: (e) => setQuery(e.target.value),
9784
+ autoFocus: true,
9785
+ "aria-label": searchPlaceholder
9786
+ }
9787
+ ) }),
9788
+ /* @__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" }) })
9789
+ ]
9459
9790
  }
9460
9791
  ) })
9461
9792
  ]
9462
9793
  }
9463
9794
  ) });
9464
- return /* @__PURE__ */ jsx337(Field, { validations, children: control });
9795
+ return /* @__PURE__ */ jsx337(Field, { validations, label, required, htmlFor: fieldId, children: control });
9465
9796
  };
9466
9797
  SelectRoot.displayName = "Select";
9467
9798
  var Select = Object.assign(SelectRoot, {
@@ -9541,8 +9872,44 @@ var Spinner = (props) => {
9541
9872
  Spinner.displayName = "Spinner";
9542
9873
  var Spinner_default = Spinner;
9543
9874
 
9544
- // src/components/Steps/Steps.tsx
9875
+ // src/components/Stat/Stat.tsx
9545
9876
  import { jsx as jsx340, jsxs as jsxs218 } from "react/jsx-runtime";
9877
+ var ARROW = {
9878
+ up: "\u25B2",
9879
+ down: "\u25BC",
9880
+ flat: "\u2014"
9881
+ };
9882
+ var Stat = (props) => {
9883
+ const {
9884
+ label,
9885
+ value,
9886
+ unit,
9887
+ description,
9888
+ trend,
9889
+ icon,
9890
+ size = "md",
9891
+ type = "primary"
9892
+ } = props;
9893
+ const statusType = normalizeStatus(type);
9894
+ return /* @__PURE__ */ jsxs218("div", { className: clsx_default("lib-xplat-stat", size, statusType), children: [
9895
+ /* @__PURE__ */ jsx340("div", { className: "stat-label", children: label }),
9896
+ /* @__PURE__ */ jsxs218("div", { className: "stat-value-row", children: [
9897
+ icon && /* @__PURE__ */ jsx340("span", { className: "stat-icon", children: icon }),
9898
+ /* @__PURE__ */ jsx340("span", { className: "stat-value", children: value }),
9899
+ unit && /* @__PURE__ */ jsx340("span", { className: "stat-unit", children: unit }),
9900
+ trend && /* @__PURE__ */ jsxs218("span", { className: clsx_default("stat-trend", trend.direction), children: [
9901
+ /* @__PURE__ */ jsx340("span", { "aria-hidden": "true", children: ARROW[trend.direction] }),
9902
+ trend.value
9903
+ ] })
9904
+ ] }),
9905
+ description && /* @__PURE__ */ jsx340("div", { className: "stat-description", children: description })
9906
+ ] });
9907
+ };
9908
+ Stat.displayName = "Stat";
9909
+ var Stat_default = Stat;
9910
+
9911
+ // src/components/Steps/Steps.tsx
9912
+ import { jsx as jsx341, jsxs as jsxs219 } from "react/jsx-runtime";
9546
9913
  var Steps = (props) => {
9547
9914
  const {
9548
9915
  items,
@@ -9550,13 +9917,13 @@ var Steps = (props) => {
9550
9917
  type = "primary"
9551
9918
  } = props;
9552
9919
  const statusType = normalizeStatus(type);
9553
- return /* @__PURE__ */ jsx340("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
9920
+ return /* @__PURE__ */ jsx341("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
9554
9921
  const status = index < current ? "completed" : index === current ? "active" : "pending";
9555
- return /* @__PURE__ */ jsxs218("div", { className: clsx_default("step-item", status), children: [
9556
- /* @__PURE__ */ jsx340("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ jsx340(CheckIcon_default, {}) : /* @__PURE__ */ jsx340("span", { children: index + 1 }) }),
9557
- /* @__PURE__ */ jsxs218("div", { className: "step-content", children: [
9558
- /* @__PURE__ */ jsx340("span", { className: "step-title", children: item.title }),
9559
- item.description && /* @__PURE__ */ jsx340("span", { className: "step-description", children: item.description })
9922
+ return /* @__PURE__ */ jsxs219("div", { className: clsx_default("step-item", status), children: [
9923
+ /* @__PURE__ */ jsx341("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ jsx341(CheckIcon_default, {}) : /* @__PURE__ */ jsx341("span", { children: index + 1 }) }),
9924
+ /* @__PURE__ */ jsxs219("div", { className: "step-content", children: [
9925
+ /* @__PURE__ */ jsx341("span", { className: "step-title", children: item.title }),
9926
+ item.description && /* @__PURE__ */ jsx341("span", { className: "step-description", children: item.description })
9560
9927
  ] })
9561
9928
  ] }, index);
9562
9929
  }) });
@@ -9565,8 +9932,8 @@ Steps.displayName = "Steps";
9565
9932
  var Steps_default = Steps;
9566
9933
 
9567
9934
  // src/components/Swiper/Swiper.tsx
9568
- import React31 from "react";
9569
- import { jsx as jsx341, jsxs as jsxs219 } from "react/jsx-runtime";
9935
+ import React32 from "react";
9936
+ import { jsx as jsx342, jsxs as jsxs220 } from "react/jsx-runtime";
9570
9937
  var Swiper = (props) => {
9571
9938
  const {
9572
9939
  auto = false,
@@ -9590,26 +9957,26 @@ var Swiper = (props) => {
9590
9957
  const maxIndex = Math.max(0, totalSlides - viewItemCount);
9591
9958
  const useLoop = loop && canSlide;
9592
9959
  const cloneCount = useLoop ? totalSlides : 0;
9593
- const extendedItems = React31.useMemo(() => {
9960
+ const extendedItems = React32.useMemo(() => {
9594
9961
  if (!useLoop) return items;
9595
9962
  return [...items, ...items, ...items];
9596
9963
  }, [items, useLoop]);
9597
9964
  const initialIdx = Math.max(0, Math.min(indexProp ?? 0, maxIndex));
9598
- const [innerIndex, setInnerIndex] = React31.useState(
9965
+ const [innerIndex, setInnerIndex] = React32.useState(
9599
9966
  useLoop ? cloneCount + initialIdx : initialIdx
9600
9967
  );
9601
- const [isDragging, setIsDragging] = React31.useState(false);
9602
- const [dragOffset, setDragOffset] = React31.useState(0);
9603
- const [animated, setAnimated] = React31.useState(false);
9604
- const [containerWidth, setContainerWidth] = React31.useState(0);
9605
- const containerRef = React31.useRef(null);
9606
- const startXRef = React31.useRef(0);
9607
- const startTimeRef = React31.useRef(0);
9608
- const autoplayTimerRef = React31.useRef(null);
9609
- const resumeTimeoutRef = React31.useRef(null);
9610
- const [paused, setPaused] = React31.useState(false);
9611
- const initializedRef = React31.useRef(false);
9612
- React31.useEffect(() => {
9968
+ const [isDragging, setIsDragging] = React32.useState(false);
9969
+ const [dragOffset, setDragOffset] = React32.useState(0);
9970
+ const [animated, setAnimated] = React32.useState(false);
9971
+ const [containerWidth, setContainerWidth] = React32.useState(0);
9972
+ const containerRef = React32.useRef(null);
9973
+ const startXRef = React32.useRef(0);
9974
+ const startTimeRef = React32.useRef(0);
9975
+ const autoplayTimerRef = React32.useRef(null);
9976
+ const resumeTimeoutRef = React32.useRef(null);
9977
+ const [paused, setPaused] = React32.useState(false);
9978
+ const initializedRef = React32.useRef(false);
9979
+ React32.useEffect(() => {
9613
9980
  const el = containerRef.current;
9614
9981
  if (!el) return;
9615
9982
  const ro = new ResizeObserver((entries) => {
@@ -9632,7 +9999,7 @@ var Swiper = (props) => {
9632
9999
  return ((inner - cloneCount) % totalSlides + totalSlides) % totalSlides;
9633
10000
  };
9634
10001
  const realIndex = getRealIndex(innerIndex);
9635
- const moveToInner = React31.useCallback(
10002
+ const moveToInner = React32.useCallback(
9636
10003
  (idx, withAnim = true) => {
9637
10004
  if (!useLoop) {
9638
10005
  setAnimated(withAnim);
@@ -9660,7 +10027,7 @@ var Swiper = (props) => {
9660
10027
  },
9661
10028
  [useLoop, cloneCount, totalSlides]
9662
10029
  );
9663
- const handleTransitionEnd = React31.useCallback(() => {
10030
+ const handleTransitionEnd = React32.useCallback(() => {
9664
10031
  if (!useLoop) return;
9665
10032
  const real = getRealIndex(innerIndex);
9666
10033
  const canonical = cloneCount + real;
@@ -9670,7 +10037,7 @@ var Swiper = (props) => {
9670
10037
  }
9671
10038
  onChange?.(Math.min(real, maxIndex));
9672
10039
  }, [useLoop, innerIndex, cloneCount, totalSlides, maxIndex, onChange]);
9673
- const slideTo = React31.useCallback(
10040
+ const slideTo = React32.useCallback(
9674
10041
  (logicalIndex) => {
9675
10042
  if (!canSlide) return;
9676
10043
  const clamped = useLoop ? logicalIndex : Math.max(0, Math.min(logicalIndex, maxIndex));
@@ -9680,7 +10047,7 @@ var Swiper = (props) => {
9680
10047
  },
9681
10048
  [canSlide, useLoop, cloneCount, maxIndex, onChange, moveToInner]
9682
10049
  );
9683
- const slideNext = React31.useCallback(() => {
10050
+ const slideNext = React32.useCallback(() => {
9684
10051
  if (!canSlide) return;
9685
10052
  const nextInner = innerIndex + slideBy;
9686
10053
  if (useLoop) {
@@ -9689,7 +10056,7 @@ var Swiper = (props) => {
9689
10056
  moveToInner(Math.min(nextInner, maxIndex), true);
9690
10057
  }
9691
10058
  }, [canSlide, useLoop, innerIndex, slideBy, maxIndex, moveToInner]);
9692
- const slidePrev = React31.useCallback(() => {
10059
+ const slidePrev = React32.useCallback(() => {
9693
10060
  if (!canSlide) return;
9694
10061
  const prevInner = innerIndex - slideBy;
9695
10062
  if (useLoop) {
@@ -9698,7 +10065,7 @@ var Swiper = (props) => {
9698
10065
  moveToInner(Math.max(prevInner, 0), true);
9699
10066
  }
9700
10067
  }, [canSlide, useLoop, innerIndex, slideBy, moveToInner]);
9701
- React31.useEffect(() => {
10068
+ React32.useEffect(() => {
9702
10069
  if (indexProp === void 0) return;
9703
10070
  const clamped = Math.max(0, Math.min(indexProp, maxIndex));
9704
10071
  const target = useLoop ? cloneCount + clamped : clamped;
@@ -9706,12 +10073,12 @@ var Swiper = (props) => {
9706
10073
  moveToInner(target, true);
9707
10074
  }
9708
10075
  }, [indexProp]);
9709
- React31.useImperativeHandle(swiperRef, () => ({
10076
+ React32.useImperativeHandle(swiperRef, () => ({
9710
10077
  slidePrev,
9711
10078
  slideNext,
9712
10079
  slideTo
9713
10080
  }));
9714
- React31.useEffect(() => {
10081
+ React32.useEffect(() => {
9715
10082
  if (!auto || !canSlide || paused) return;
9716
10083
  autoplayTimerRef.current = setInterval(slideNext, autoplayDelay);
9717
10084
  return () => {
@@ -9737,7 +10104,7 @@ var Swiper = (props) => {
9737
10104
  resumeTimeoutRef.current = null;
9738
10105
  }, pauseOnInteraction);
9739
10106
  };
9740
- React31.useEffect(() => {
10107
+ React32.useEffect(() => {
9741
10108
  return () => {
9742
10109
  if (resumeTimeoutRef.current) clearTimeout(resumeTimeoutRef.current);
9743
10110
  };
@@ -9755,7 +10122,7 @@ var Swiper = (props) => {
9755
10122
  startXRef.current = getClientX(e);
9756
10123
  startTimeRef.current = Date.now();
9757
10124
  };
9758
- React31.useEffect(() => {
10125
+ React32.useEffect(() => {
9759
10126
  if (!isDragging) return;
9760
10127
  const handleMove = (e) => {
9761
10128
  setDragOffset(getClientX(e) - startXRef.current);
@@ -9794,8 +10161,8 @@ var Swiper = (props) => {
9794
10161
  }, [isDragging, dragOffset, innerIndex, useLoop, maxIndex, slideStep, moveToInner]);
9795
10162
  const slideWidthPercent = 100 / viewItemCount;
9796
10163
  const gapAdjust = spaceBetween * (viewItemCount - 1) / viewItemCount;
9797
- const slideElements = React31.useMemo(
9798
- () => extendedItems.map((item, idx) => /* @__PURE__ */ jsx341(
10164
+ const slideElements = React32.useMemo(
10165
+ () => extendedItems.map((item, idx) => /* @__PURE__ */ jsx342(
9799
10166
  "div",
9800
10167
  {
9801
10168
  className: "lib-xplat-swiper__slide",
@@ -9814,15 +10181,15 @@ var Swiper = (props) => {
9814
10181
  Math.floor(realIndex / slideBy),
9815
10182
  totalSteps - 1
9816
10183
  );
9817
- return /* @__PURE__ */ jsxs219("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
9818
- /* @__PURE__ */ jsx341(
10184
+ return /* @__PURE__ */ jsxs220("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
10185
+ /* @__PURE__ */ jsx342(
9819
10186
  "div",
9820
10187
  {
9821
10188
  className: "lib-xplat-swiper__viewport",
9822
10189
  onMouseDown: handleDragStart,
9823
10190
  onTouchStart: handleDragStart,
9824
10191
  onDragStart: (e) => e.preventDefault(),
9825
- children: /* @__PURE__ */ jsx341(
10192
+ children: /* @__PURE__ */ jsx342(
9826
10193
  "div",
9827
10194
  {
9828
10195
  className: clsx_default(
@@ -9840,7 +10207,7 @@ var Swiper = (props) => {
9840
10207
  )
9841
10208
  }
9842
10209
  ),
9843
- showProgress && canSlide && /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ jsx341(
10210
+ showProgress && canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ jsx342(
9844
10211
  "span",
9845
10212
  {
9846
10213
  className: "lib-xplat-swiper__progress-fill",
@@ -9850,7 +10217,7 @@ var Swiper = (props) => {
9850
10217
  }
9851
10218
  }
9852
10219
  ) }) }),
9853
- canSlide && /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ jsx341(
10220
+ canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ jsx342(
9854
10221
  "button",
9855
10222
  {
9856
10223
  className: clsx_default(
@@ -9868,8 +10235,8 @@ Swiper.displayName = "Swiper";
9868
10235
  var Swiper_default = Swiper;
9869
10236
 
9870
10237
  // src/components/Switch/Switch.tsx
9871
- import React32 from "react";
9872
- import { jsx as jsx342 } from "react/jsx-runtime";
10238
+ import React33 from "react";
10239
+ import { jsx as jsx343 } from "react/jsx-runtime";
9873
10240
  var KNOB_TRANSITION_MS = 250;
9874
10241
  var Switch = (props) => {
9875
10242
  const {
@@ -9878,12 +10245,15 @@ var Switch = (props) => {
9878
10245
  type = "primary",
9879
10246
  disabled,
9880
10247
  onChange,
9881
- validations
10248
+ validations,
10249
+ label,
10250
+ required
9882
10251
  } = props;
10252
+ const fieldId = React33.useId();
9883
10253
  const statusType = normalizeStatus(type);
9884
- const [isAnimating, setIsAnimating] = React32.useState(false);
9885
- const timeoutRef = React32.useRef(null);
9886
- React32.useEffect(() => {
10254
+ const [isAnimating, setIsAnimating] = React33.useState(false);
10255
+ const timeoutRef = React33.useRef(null);
10256
+ React33.useEffect(() => {
9887
10257
  return () => {
9888
10258
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
9889
10259
  };
@@ -9898,9 +10268,10 @@ var Switch = (props) => {
9898
10268
  timeoutRef.current = null;
9899
10269
  }, KNOB_TRANSITION_MS);
9900
10270
  };
9901
- const control = /* @__PURE__ */ jsx342(
10271
+ const control = /* @__PURE__ */ jsx343(
9902
10272
  "div",
9903
10273
  {
10274
+ id: fieldId,
9904
10275
  className: clsx_default(
9905
10276
  "lib-xplat-switch",
9906
10277
  size,
@@ -9912,26 +10283,26 @@ var Switch = (props) => {
9912
10283
  onClick: handleClick,
9913
10284
  "aria-invalid": hasError(validations) || void 0,
9914
10285
  "aria-disabled": disabled || isAnimating,
9915
- children: /* @__PURE__ */ jsx342("div", { className: clsx_default("knob", value ? "checked" : void 0) })
10286
+ children: /* @__PURE__ */ jsx343("div", { className: clsx_default("knob", value ? "checked" : void 0) })
9916
10287
  }
9917
10288
  );
9918
- return /* @__PURE__ */ jsx342(Field, { validations, children: control });
10289
+ return /* @__PURE__ */ jsx343(Field, { validations, label, required, htmlFor: fieldId, children: control });
9919
10290
  };
9920
10291
  Switch.displayName = "Switch";
9921
10292
  var Switch_default = Switch;
9922
10293
 
9923
10294
  // src/components/Table/TableContext.tsx
9924
- import React33 from "react";
9925
- var TableContext = React33.createContext(null);
10295
+ import React34 from "react";
10296
+ var TableContext = React34.createContext(null);
9926
10297
  var useTableContext = () => {
9927
- const ctx = React33.useContext(TableContext);
10298
+ const ctx = React34.useContext(TableContext);
9928
10299
  if (!ctx) throw new Error("Table components must be used inside <Table>");
9929
10300
  return ctx;
9930
10301
  };
9931
10302
  var TableContext_default = TableContext;
9932
10303
 
9933
10304
  // src/components/Table/Table.tsx
9934
- import { jsx as jsx343 } from "react/jsx-runtime";
10305
+ import { jsx as jsx344 } from "react/jsx-runtime";
9935
10306
  var Table = (props) => {
9936
10307
  const {
9937
10308
  children,
@@ -9941,7 +10312,7 @@ var Table = (props) => {
9941
10312
  headerSticky = false,
9942
10313
  stickyShadow = true
9943
10314
  } = props;
9944
- return /* @__PURE__ */ jsx343("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx343(
10315
+ return /* @__PURE__ */ jsx344("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx344(
9945
10316
  TableContext_default.Provider,
9946
10317
  {
9947
10318
  value: {
@@ -9950,7 +10321,7 @@ var Table = (props) => {
9950
10321
  headerSticky,
9951
10322
  stickyShadow
9952
10323
  },
9953
- children: /* @__PURE__ */ jsx343("table", { className: "lib-xplat-table", children })
10324
+ children: /* @__PURE__ */ jsx344("table", { className: "lib-xplat-table", children })
9954
10325
  }
9955
10326
  ) });
9956
10327
  };
@@ -9958,41 +10329,41 @@ Table.displayName = "Table";
9958
10329
  var Table_default = Table;
9959
10330
 
9960
10331
  // src/components/Table/TableBody.tsx
9961
- import { jsx as jsx344 } from "react/jsx-runtime";
10332
+ import { jsx as jsx345 } from "react/jsx-runtime";
9962
10333
  var TableBody = (props) => {
9963
10334
  const { children } = props;
9964
- return /* @__PURE__ */ jsx344("tbody", { children });
10335
+ return /* @__PURE__ */ jsx345("tbody", { children });
9965
10336
  };
9966
10337
  TableBody.displayName = "TableBody";
9967
10338
  var TableBody_default = TableBody;
9968
10339
 
9969
10340
  // src/components/Table/TableCell.tsx
9970
- import React36 from "react";
10341
+ import React37 from "react";
9971
10342
 
9972
10343
  // src/components/Table/TableHeadContext.tsx
9973
- import React34 from "react";
9974
- var TableHeadContext = React34.createContext(
10344
+ import React35 from "react";
10345
+ var TableHeadContext = React35.createContext(
9975
10346
  null
9976
10347
  );
9977
10348
  var useTableHeadContext = () => {
9978
- const ctx = React34.useContext(TableHeadContext);
10349
+ const ctx = React35.useContext(TableHeadContext);
9979
10350
  return ctx;
9980
10351
  };
9981
10352
  var TableHeadContext_default = TableHeadContext;
9982
10353
 
9983
10354
  // src/components/Table/TableRowContext.tsx
9984
- import React35 from "react";
9985
- var TableRowContext = React35.createContext(null);
10355
+ import React36 from "react";
10356
+ var TableRowContext = React36.createContext(null);
9986
10357
  var useTableRowContext = () => {
9987
- const ctx = React35.useContext(TableRowContext);
10358
+ const ctx = React36.useContext(TableRowContext);
9988
10359
  if (!ctx) throw new Error("Table components must be used inside <Table>");
9989
10360
  return ctx;
9990
10361
  };
9991
10362
  var TableRowContext_default = TableRowContext;
9992
10363
 
9993
10364
  // src/components/Table/TableCell.tsx
9994
- import { jsx as jsx345 } from "react/jsx-runtime";
9995
- var TableCell = React36.memo((props) => {
10365
+ import { jsx as jsx346 } from "react/jsx-runtime";
10366
+ var TableCell = React37.memo((props) => {
9996
10367
  const {
9997
10368
  children,
9998
10369
  align = "center",
@@ -10006,9 +10377,9 @@ var TableCell = React36.memo((props) => {
10006
10377
  const { registerStickyCell, stickyCells } = useTableRowContext();
10007
10378
  const { stickyShadow } = useTableContext();
10008
10379
  const headContext = useTableHeadContext();
10009
- const [left, setLeft] = React36.useState(0);
10010
- const cellRef = React36.useRef(null);
10011
- const calculateLeft = React36.useCallback(() => {
10380
+ const [left, setLeft] = React37.useState(0);
10381
+ const cellRef = React37.useRef(null);
10382
+ const calculateLeft = React37.useCallback(() => {
10012
10383
  if (!cellRef.current) return 0;
10013
10384
  let totalLeft = 0;
10014
10385
  for (const ref of stickyCells) {
@@ -10017,7 +10388,7 @@ var TableCell = React36.memo((props) => {
10017
10388
  }
10018
10389
  return totalLeft;
10019
10390
  }, [stickyCells]);
10020
- React36.useEffect(() => {
10391
+ React37.useEffect(() => {
10021
10392
  if (!isSticky || !cellRef.current) return;
10022
10393
  registerStickyCell(cellRef);
10023
10394
  setLeft(calculateLeft());
@@ -10036,7 +10407,7 @@ var TableCell = React36.memo((props) => {
10036
10407
  const CellTag = isHeaderCell ? "th" : "td";
10037
10408
  const isLastSticky = isSticky && stickyCells[stickyCells.length - 1] === cellRef;
10038
10409
  const enableHover = headContext && headContext.cellHover;
10039
- return /* @__PURE__ */ jsx345(
10410
+ return /* @__PURE__ */ jsx346(
10040
10411
  CellTag,
10041
10412
  {
10042
10413
  ref: cellRef,
@@ -10063,21 +10434,21 @@ TableCell.displayName = "TableCell";
10063
10434
  var TableCell_default = TableCell;
10064
10435
 
10065
10436
  // src/components/Table/TableHead.tsx
10066
- import { jsx as jsx346 } from "react/jsx-runtime";
10437
+ import { jsx as jsx347 } from "react/jsx-runtime";
10067
10438
  var TableHead = ({
10068
10439
  children,
10069
10440
  cellHover = false
10070
10441
  }) => {
10071
10442
  const { headerSticky } = useTableContext();
10072
- return /* @__PURE__ */ jsx346(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ jsx346("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
10443
+ return /* @__PURE__ */ jsx347(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ jsx347("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
10073
10444
  };
10074
10445
  TableHead.displayName = "TableHead";
10075
10446
  var TableHead_default = TableHead;
10076
10447
 
10077
10448
  // src/components/Table/TableRow.tsx
10078
- import React37 from "react";
10079
- import { jsx as jsx347 } from "react/jsx-runtime";
10080
- var TableRow = React37.memo((props) => {
10449
+ import React38 from "react";
10450
+ import { jsx as jsx348 } from "react/jsx-runtime";
10451
+ var TableRow = React38.memo((props) => {
10081
10452
  const {
10082
10453
  children,
10083
10454
  type = "secondary",
@@ -10086,14 +10457,14 @@ var TableRow = React37.memo((props) => {
10086
10457
  onClick
10087
10458
  } = props;
10088
10459
  const { rowBorderUse } = useTableContext();
10089
- const [stickyCells, setStickyCells] = React37.useState([]);
10460
+ const [stickyCells, setStickyCells] = React38.useState([]);
10090
10461
  const registerStickyCell = (ref) => {
10091
10462
  setStickyCells((prev) => {
10092
10463
  if (prev.includes(ref)) return prev;
10093
10464
  return [...prev, ref];
10094
10465
  });
10095
10466
  };
10096
- return /* @__PURE__ */ jsx347(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ jsx347(
10467
+ return /* @__PURE__ */ jsx348(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ jsx348(
10097
10468
  "tr",
10098
10469
  {
10099
10470
  className: clsx_default(
@@ -10117,7 +10488,7 @@ TableRow.displayName = "TableRow";
10117
10488
  var TableRow_default = TableRow;
10118
10489
 
10119
10490
  // src/components/Tag/Tag.tsx
10120
- import { jsx as jsx348, jsxs as jsxs220 } from "react/jsx-runtime";
10491
+ import { jsx as jsx349, jsxs as jsxs221 } from "react/jsx-runtime";
10121
10492
  var Tag = (props) => {
10122
10493
  const {
10123
10494
  children,
@@ -10129,7 +10500,7 @@ var Tag = (props) => {
10129
10500
  colorIndex
10130
10501
  } = props;
10131
10502
  const shape = variant ?? type ?? "neutral";
10132
- return /* @__PURE__ */ jsxs220(
10503
+ return /* @__PURE__ */ jsxs221(
10133
10504
  "span",
10134
10505
  {
10135
10506
  className: clsx_default(
@@ -10140,8 +10511,8 @@ var Tag = (props) => {
10140
10511
  disabled && "disabled"
10141
10512
  ),
10142
10513
  children: [
10143
- /* @__PURE__ */ jsx348("span", { className: "tag-label", children }),
10144
- onClose && /* @__PURE__ */ jsx348("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ jsx348(XIcon_default, {}) })
10514
+ /* @__PURE__ */ jsx349("span", { className: "tag-label", children }),
10515
+ onClose && /* @__PURE__ */ jsx349("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ jsx349(XIcon_default, {}) })
10145
10516
  ]
10146
10517
  }
10147
10518
  );
@@ -10150,24 +10521,29 @@ Tag.displayName = "Tag";
10150
10521
  var Tag_default = Tag;
10151
10522
 
10152
10523
  // src/components/TextArea/TextArea.tsx
10153
- import React38 from "react";
10154
- import { jsx as jsx349 } from "react/jsx-runtime";
10155
- var TextArea = React38.forwardRef(
10524
+ import React39 from "react";
10525
+ import { jsx as jsx350 } from "react/jsx-runtime";
10526
+ var TextArea = React39.forwardRef(
10156
10527
  (props, ref) => {
10157
10528
  const {
10158
10529
  className,
10159
10530
  size = "md",
10160
10531
  validations,
10532
+ label,
10533
+ required,
10161
10534
  resize = "vertical",
10162
10535
  rows = 3,
10163
10536
  disabled,
10164
10537
  ...textareaProps
10165
10538
  } = props;
10166
- const control = /* @__PURE__ */ jsx349("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx349(
10539
+ const autoId = React39.useId();
10540
+ const fieldId = props.id ?? autoId;
10541
+ const control = /* @__PURE__ */ jsx350("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx350(
10167
10542
  "textarea",
10168
10543
  {
10169
10544
  ...textareaProps,
10170
10545
  ref,
10546
+ id: fieldId,
10171
10547
  rows,
10172
10548
  disabled,
10173
10549
  "aria-invalid": hasError(validations) || void 0,
@@ -10175,32 +10551,166 @@ var TextArea = React38.forwardRef(
10175
10551
  style: { resize }
10176
10552
  }
10177
10553
  ) });
10178
- return /* @__PURE__ */ jsx349(Field, { validations, children: control });
10554
+ return /* @__PURE__ */ jsx350(Field, { validations, label, required, htmlFor: fieldId, children: control });
10179
10555
  }
10180
10556
  );
10181
10557
  TextArea.displayName = "TextArea";
10182
10558
  var TextArea_default = TextArea;
10183
10559
 
10560
+ // src/components/TimePicker/TimePicker.tsx
10561
+ import React40 from "react";
10562
+ import { jsx as jsx351, jsxs as jsxs222 } from "react/jsx-runtime";
10563
+ var ANIMATION_DURATION_MS4 = 200;
10564
+ var toMinutes = (hhmm) => {
10565
+ if (!hhmm) return null;
10566
+ const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
10567
+ if (!m) return null;
10568
+ const h = Number(m[1]);
10569
+ const min = Number(m[2]);
10570
+ if (h > 23 || min > 59) return null;
10571
+ return h * 60 + min;
10572
+ };
10573
+ var toHHmm = (minutes) => `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
10574
+ var display = (hhmm, use12Hours) => {
10575
+ if (!use12Hours) return hhmm;
10576
+ const total = toMinutes(hhmm);
10577
+ if (total === null) return hhmm;
10578
+ const h24 = Math.floor(total / 60);
10579
+ const mm = String(total % 60).padStart(2, "0");
10580
+ const period = h24 < 12 ? "\uC624\uC804" : "\uC624\uD6C4";
10581
+ const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
10582
+ return `${period} ${h12}:${mm}`;
10583
+ };
10584
+ var TimePicker = (props) => {
10585
+ const {
10586
+ value,
10587
+ onChange,
10588
+ step = 30,
10589
+ min,
10590
+ max,
10591
+ use12Hours = false,
10592
+ placeholder = "\uC2DC\uAC01 \uC120\uD0DD",
10593
+ disabled = false,
10594
+ size = "md",
10595
+ label,
10596
+ required,
10597
+ validations
10598
+ } = props;
10599
+ const fieldId = React40.useId();
10600
+ const triggerRef = React40.useRef(null);
10601
+ const contentRef = React40.useRef(null);
10602
+ const [isOpen, setOpen] = React40.useState(false);
10603
+ const [mounted, setMounted] = React40.useState(false);
10604
+ const [visible, setVisible] = React40.useState(false);
10605
+ const options = React40.useMemo(() => {
10606
+ const safeStep = step > 0 && step <= 720 ? step : 30;
10607
+ const lo = toMinutes(min) ?? 0;
10608
+ const hi = toMinutes(max) ?? 24 * 60 - 1;
10609
+ const out = [];
10610
+ for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
10611
+ return out;
10612
+ }, [step, min, max]);
10613
+ const close = React40.useCallback(() => setOpen(false), []);
10614
+ useClickOutside_default([triggerRef, contentRef], close, isOpen);
10615
+ useEscapeKey(isOpen, () => {
10616
+ close();
10617
+ triggerRef.current?.focus({ preventScroll: true });
10618
+ });
10619
+ const position = useAutoPosition_default(triggerRef, contentRef, mounted);
10620
+ React40.useEffect(() => {
10621
+ if (disabled && isOpen) setOpen(false);
10622
+ }, [disabled, isOpen]);
10623
+ React40.useEffect(() => {
10624
+ if (isOpen) {
10625
+ setMounted(true);
10626
+ const t2 = setTimeout(() => setVisible(true), 1);
10627
+ return () => clearTimeout(t2);
10628
+ }
10629
+ setVisible(false);
10630
+ const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS4);
10631
+ return () => clearTimeout(t);
10632
+ }, [isOpen]);
10633
+ const pick = (hhmm) => {
10634
+ onChange?.(hhmm);
10635
+ close();
10636
+ triggerRef.current?.focus({ preventScroll: true });
10637
+ };
10638
+ const control = /* @__PURE__ */ jsxs222("div", { className: clsx_default("lib-xplat-time-picker", size, disabled && "disabled"), children: [
10639
+ /* @__PURE__ */ jsx351(
10640
+ "div",
10641
+ {
10642
+ id: fieldId,
10643
+ ref: triggerRef,
10644
+ className: clsx_default("time-picker-trigger", hasError(validations) && "error"),
10645
+ role: "combobox",
10646
+ "aria-expanded": isOpen,
10647
+ "aria-haspopup": "listbox",
10648
+ "aria-invalid": hasError(validations) || void 0,
10649
+ tabIndex: disabled ? void 0 : 0,
10650
+ onClick: () => !disabled && setOpen((p) => !p),
10651
+ onKeyDown: (e) => {
10652
+ if (disabled) return;
10653
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
10654
+ e.preventDefault();
10655
+ setOpen(true);
10656
+ }
10657
+ },
10658
+ children: /* @__PURE__ */ jsx351("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
10659
+ }
10660
+ ),
10661
+ mounted && /* @__PURE__ */ jsx351(Portal_default, { children: /* @__PURE__ */ jsx351(
10662
+ "div",
10663
+ {
10664
+ ref: contentRef,
10665
+ className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit"),
10666
+ style: { ...position.position, width: triggerRef.current?.offsetWidth },
10667
+ role: "listbox",
10668
+ children: options.map((t) => /* @__PURE__ */ jsx351(
10669
+ "div",
10670
+ {
10671
+ className: clsx_default("time-picker-item", t === value && "is-selected"),
10672
+ role: "option",
10673
+ "aria-selected": t === value,
10674
+ tabIndex: 0,
10675
+ onClick: () => pick(t),
10676
+ onKeyDown: (e) => {
10677
+ if (e.key === "Enter" || e.key === " ") {
10678
+ e.preventDefault();
10679
+ pick(t);
10680
+ }
10681
+ },
10682
+ children: display(t, use12Hours)
10683
+ },
10684
+ t
10685
+ ))
10686
+ }
10687
+ ) })
10688
+ ] });
10689
+ return /* @__PURE__ */ jsx351(Field, { validations, label, required, htmlFor: fieldId, children: control });
10690
+ };
10691
+ TimePicker.displayName = "TimePicker";
10692
+ var TimePicker_default = TimePicker;
10693
+
10184
10694
  // src/components/Toast/Toast.tsx
10185
- import React39 from "react";
10695
+ import React41 from "react";
10186
10696
  import { createPortal as createPortal3 } from "react-dom";
10187
- import { jsx as jsx350, jsxs as jsxs221 } from "react/jsx-runtime";
10188
- var ToastContext = React39.createContext(null);
10697
+ import { jsx as jsx352, jsxs as jsxs223 } from "react/jsx-runtime";
10698
+ var ToastContext = React41.createContext(null);
10189
10699
  var useToast = () => {
10190
- const ctx = React39.useContext(ToastContext);
10700
+ const ctx = React41.useContext(ToastContext);
10191
10701
  if (!ctx) throw new Error("useToast must be used within ToastProvider");
10192
10702
  return ctx;
10193
10703
  };
10194
10704
  var EXIT_DURATION = 300;
10195
10705
  var ToastItemComponent = ({ item, isExiting, onClose }) => {
10196
- const ref = React39.useRef(null);
10197
- const [height, setHeight] = React39.useState(void 0);
10198
- React39.useEffect(() => {
10706
+ const ref = React41.useRef(null);
10707
+ const [height, setHeight] = React41.useState(void 0);
10708
+ React41.useEffect(() => {
10199
10709
  if (ref.current && !isExiting) {
10200
10710
  setHeight(ref.current.offsetHeight);
10201
10711
  }
10202
10712
  }, [isExiting]);
10203
- return /* @__PURE__ */ jsx350(
10713
+ return /* @__PURE__ */ jsx352(
10204
10714
  "div",
10205
10715
  {
10206
10716
  className: clsx_default("lib-xplat-toast-wrapper", { exit: isExiting }),
@@ -10208,15 +10718,15 @@ var ToastItemComponent = ({ item, isExiting, onClose }) => {
10208
10718
  maxHeight: isExiting ? 0 : height ?? "none",
10209
10719
  marginBottom: isExiting ? 0 : void 0
10210
10720
  },
10211
- children: /* @__PURE__ */ jsxs221(
10721
+ children: /* @__PURE__ */ jsxs223(
10212
10722
  "div",
10213
10723
  {
10214
10724
  ref,
10215
10725
  className: clsx_default("lib-xplat-toast", item.type, { exit: isExiting }),
10216
10726
  role: "alert",
10217
10727
  children: [
10218
- /* @__PURE__ */ jsx350("span", { className: "message", children: item.message }),
10219
- /* @__PURE__ */ jsx350("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
10728
+ /* @__PURE__ */ jsx352("span", { className: "message", children: item.message }),
10729
+ /* @__PURE__ */ jsx352("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
10220
10730
  ]
10221
10731
  }
10222
10732
  )
@@ -10227,13 +10737,13 @@ var ToastProvider = ({
10227
10737
  children,
10228
10738
  position = "top-right"
10229
10739
  }) => {
10230
- const [toasts, setToasts] = React39.useState([]);
10231
- const [removing, setRemoving] = React39.useState(/* @__PURE__ */ new Set());
10232
- const [mounted, setMounted] = React39.useState(false);
10233
- React39.useEffect(() => {
10740
+ const [toasts, setToasts] = React41.useState([]);
10741
+ const [removing, setRemoving] = React41.useState(/* @__PURE__ */ new Set());
10742
+ const [mounted, setMounted] = React41.useState(false);
10743
+ React41.useEffect(() => {
10234
10744
  setMounted(true);
10235
10745
  }, []);
10236
- const remove = React39.useCallback((id) => {
10746
+ const remove = React41.useCallback((id) => {
10237
10747
  setRemoving((prev) => new Set(prev).add(id));
10238
10748
  setTimeout(() => {
10239
10749
  setToasts((prev) => prev.filter((t) => t.id !== id));
@@ -10244,7 +10754,7 @@ var ToastProvider = ({
10244
10754
  });
10245
10755
  }, EXIT_DURATION);
10246
10756
  }, []);
10247
- const toast = React39.useCallback(
10757
+ const toast = React41.useCallback(
10248
10758
  (type, message, duration = 3e3) => {
10249
10759
  const id = `${Date.now()}-${Math.random()}`;
10250
10760
  setToasts((prev) => [...prev, { id, type, message }]);
@@ -10254,10 +10764,10 @@ var ToastProvider = ({
10254
10764
  },
10255
10765
  [remove]
10256
10766
  );
10257
- return /* @__PURE__ */ jsxs221(ToastContext.Provider, { value: { toast }, children: [
10767
+ return /* @__PURE__ */ jsxs223(ToastContext.Provider, { value: { toast }, children: [
10258
10768
  children,
10259
10769
  mounted && createPortal3(
10260
- /* @__PURE__ */ jsx350("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ jsx350(
10770
+ /* @__PURE__ */ jsx352("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ jsx352(
10261
10771
  ToastItemComponent,
10262
10772
  {
10263
10773
  item: t,
@@ -10273,8 +10783,8 @@ var ToastProvider = ({
10273
10783
  ToastProvider.displayName = "ToastProvider";
10274
10784
 
10275
10785
  // src/components/Tooltip/Tooltip.tsx
10276
- import React40 from "react";
10277
- import { Fragment as Fragment6, jsx as jsx351, jsxs as jsxs222 } from "react/jsx-runtime";
10786
+ import React42 from "react";
10787
+ import { Fragment as Fragment6, jsx as jsx353, jsxs as jsxs224 } from "react/jsx-runtime";
10278
10788
  var OFFSET = 12;
10279
10789
  var GAP = 8;
10280
10790
  var SHOW_DELAY = 300;
@@ -10289,14 +10799,14 @@ var Tooltip = (props) => {
10289
10799
  disabled = false
10290
10800
  } = props;
10291
10801
  const shape = variant ?? type ?? "dark";
10292
- const triggerRef = React40.useRef(null);
10293
- const tooltipRef = React40.useRef(null);
10294
- const [visible, setVisible] = React40.useState(false);
10295
- const [pos, setPos] = React40.useState({ left: 0, top: 0 });
10296
- const delayTimer = React40.useRef(0);
10297
- const rafRef = React40.useRef(0);
10298
- const cursor = React40.useRef(null);
10299
- const clamp = React40.useCallback((left, top, w, h) => {
10802
+ const triggerRef = React42.useRef(null);
10803
+ const tooltipRef = React42.useRef(null);
10804
+ const [visible, setVisible] = React42.useState(false);
10805
+ const [pos, setPos] = React42.useState({ left: 0, top: 0 });
10806
+ const delayTimer = React42.useRef(0);
10807
+ const rafRef = React42.useRef(0);
10808
+ const cursor = React42.useRef(null);
10809
+ const clamp = React42.useCallback((left, top, w, h) => {
10300
10810
  const vw = window.innerWidth;
10301
10811
  const vh = window.innerHeight;
10302
10812
  return {
@@ -10304,7 +10814,7 @@ var Tooltip = (props) => {
10304
10814
  top: Math.min(Math.max(GAP, top), Math.max(GAP, vh - h - GAP))
10305
10815
  };
10306
10816
  }, []);
10307
- const placeAtCursor = React40.useCallback((x, y) => {
10817
+ const placeAtCursor = React42.useCallback((x, y) => {
10308
10818
  const el = tooltipRef.current;
10309
10819
  if (!el) return;
10310
10820
  const w = el.offsetWidth;
@@ -10315,7 +10825,7 @@ var Tooltip = (props) => {
10315
10825
  if (top < GAP) top = y + OFFSET;
10316
10826
  setPos(clamp(left, top, w, h));
10317
10827
  }, [clamp]);
10318
- const placeAtTrigger = React40.useCallback(() => {
10828
+ const placeAtTrigger = React42.useCallback(() => {
10319
10829
  const el = tooltipRef.current;
10320
10830
  const trigger = triggerRef.current;
10321
10831
  if (!el || !trigger) return;
@@ -10327,19 +10837,19 @@ var Tooltip = (props) => {
10327
10837
  const left = rect.left + rect.width / 2 - w / 2;
10328
10838
  setPos(clamp(left, top, w, h));
10329
10839
  }, [clamp]);
10330
- const reposition = React40.useCallback(() => {
10840
+ const reposition = React42.useCallback(() => {
10331
10841
  if (follow && cursor.current) {
10332
10842
  placeAtCursor(cursor.current.x, cursor.current.y);
10333
10843
  } else {
10334
10844
  placeAtTrigger();
10335
10845
  }
10336
10846
  }, [follow, placeAtCursor, placeAtTrigger]);
10337
- const handleMouseEnter = React40.useCallback((e) => {
10847
+ const handleMouseEnter = React42.useCallback((e) => {
10338
10848
  if (disabled) return;
10339
10849
  cursor.current = { x: e.clientX, y: e.clientY };
10340
10850
  delayTimer.current = window.setTimeout(() => setVisible(true), SHOW_DELAY);
10341
10851
  }, [disabled]);
10342
- const handleMouseMove = React40.useCallback((e) => {
10852
+ const handleMouseMove = React42.useCallback((e) => {
10343
10853
  cursor.current = { x: e.clientX, y: e.clientY };
10344
10854
  if (!visible || !follow) return;
10345
10855
  cancelAnimationFrame(rafRef.current);
@@ -10347,25 +10857,25 @@ var Tooltip = (props) => {
10347
10857
  if (cursor.current) placeAtCursor(cursor.current.x, cursor.current.y);
10348
10858
  });
10349
10859
  }, [visible, follow, placeAtCursor]);
10350
- const close = React40.useCallback(() => {
10860
+ const close = React42.useCallback(() => {
10351
10861
  window.clearTimeout(delayTimer.current);
10352
10862
  cancelAnimationFrame(rafRef.current);
10353
10863
  setVisible(false);
10354
10864
  }, []);
10355
- const handleMouseLeave = React40.useCallback(() => {
10865
+ const handleMouseLeave = React42.useCallback(() => {
10356
10866
  cursor.current = null;
10357
10867
  close();
10358
10868
  }, [close]);
10359
- const handleFocus = React40.useCallback(() => {
10869
+ const handleFocus = React42.useCallback(() => {
10360
10870
  if (disabled) return;
10361
10871
  cursor.current = null;
10362
10872
  setVisible(true);
10363
10873
  }, [disabled]);
10364
- React40.useLayoutEffect(() => {
10874
+ React42.useLayoutEffect(() => {
10365
10875
  if (!visible) return;
10366
10876
  reposition();
10367
10877
  }, [visible, reposition]);
10368
- React40.useEffect(() => {
10878
+ React42.useEffect(() => {
10369
10879
  if (!visible || follow) return;
10370
10880
  const onChange = () => placeAtTrigger();
10371
10881
  window.addEventListener("scroll", onChange, true);
@@ -10375,12 +10885,12 @@ var Tooltip = (props) => {
10375
10885
  window.removeEventListener("resize", onChange);
10376
10886
  };
10377
10887
  }, [visible, follow, placeAtTrigger]);
10378
- React40.useEffect(() => () => {
10888
+ React42.useEffect(() => () => {
10379
10889
  window.clearTimeout(delayTimer.current);
10380
10890
  cancelAnimationFrame(rafRef.current);
10381
10891
  }, []);
10382
- if (!title && !description) return /* @__PURE__ */ jsx351(Fragment6, { children });
10383
- return /* @__PURE__ */ jsxs222(
10892
+ if (!title && !description) return /* @__PURE__ */ jsx353(Fragment6, { children });
10893
+ return /* @__PURE__ */ jsxs224(
10384
10894
  "div",
10385
10895
  {
10386
10896
  ref: triggerRef,
@@ -10393,7 +10903,7 @@ var Tooltip = (props) => {
10393
10903
  onBlur: close,
10394
10904
  children: [
10395
10905
  children,
10396
- visible && /* @__PURE__ */ jsx351(Portal_default, { children: /* @__PURE__ */ jsxs222(
10906
+ visible && /* @__PURE__ */ jsx353(Portal_default, { children: /* @__PURE__ */ jsxs224(
10397
10907
  "div",
10398
10908
  {
10399
10909
  ref: tooltipRef,
@@ -10401,8 +10911,8 @@ var Tooltip = (props) => {
10401
10911
  className: clsx_default("lib-xplat-tooltip", shape),
10402
10912
  style: { position: "fixed", left: pos.left, top: pos.top },
10403
10913
  children: [
10404
- title && /* @__PURE__ */ jsx351("div", { className: "tooltip-title", children: title }),
10405
- description && /* @__PURE__ */ jsx351("div", { className: "tooltip-desc", children: description })
10914
+ title && /* @__PURE__ */ jsx353("div", { className: "tooltip-title", children: title }),
10915
+ description && /* @__PURE__ */ jsx353("div", { className: "tooltip-desc", children: description })
10406
10916
  ]
10407
10917
  }
10408
10918
  ) })
@@ -10414,11 +10924,11 @@ Tooltip.displayName = "Tooltip";
10414
10924
  var Tooltip_default = Tooltip;
10415
10925
 
10416
10926
  // src/components/Video/Video.tsx
10417
- import React41 from "react";
10418
- import { jsx as jsx352, jsxs as jsxs223 } from "react/jsx-runtime";
10419
- 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: [
10420
- /* @__PURE__ */ jsx352("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
10421
- /* @__PURE__ */ jsx352("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
10927
+ import React43 from "react";
10928
+ import { jsx as jsx354, jsxs as jsxs225 } from "react/jsx-runtime";
10929
+ 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: [
10930
+ /* @__PURE__ */ jsx354("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
10931
+ /* @__PURE__ */ jsx354("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
10422
10932
  ] });
10423
10933
  var formatTime = (sec) => {
10424
10934
  if (!Number.isFinite(sec) || sec < 0) return "0:00";
@@ -10426,7 +10936,7 @@ var formatTime = (sec) => {
10426
10936
  const s = Math.floor(sec % 60);
10427
10937
  return `${m}:${s.toString().padStart(2, "0")}`;
10428
10938
  };
10429
- var Video = React41.forwardRef((props, ref) => {
10939
+ var Video = React43.forwardRef((props, ref) => {
10430
10940
  const {
10431
10941
  src,
10432
10942
  poster,
@@ -10450,21 +10960,21 @@ var Video = React41.forwardRef((props, ref) => {
10450
10960
  children,
10451
10961
  ...rest
10452
10962
  } = props;
10453
- const containerRef = React41.useRef(null);
10454
- const videoRef = React41.useRef(null);
10455
- const [isPlaying, setIsPlaying] = React41.useState(Boolean(autoPlay));
10456
- const [isLoaded, setIsLoaded] = React41.useState(false);
10457
- const [currentTime, setCurrentTime] = React41.useState(0);
10458
- const [duration, setDuration] = React41.useState(0);
10459
- const [buffered, setBuffered] = React41.useState(0);
10460
- const [volume, setVolume] = React41.useState(1);
10461
- const [isMuted, setIsMuted] = React41.useState(Boolean(muted));
10462
- const [isFullscreen, setIsFullscreen] = React41.useState(false);
10463
- const [playbackRate, setPlaybackRate] = React41.useState(1);
10464
- const [rateMenuOpen, setRateMenuOpen] = React41.useState(false);
10465
- const [captionsOn, setCaptionsOn] = React41.useState(false);
10466
- const [isPip, setIsPip] = React41.useState(false);
10467
- const setRefs = React41.useCallback(
10963
+ const containerRef = React43.useRef(null);
10964
+ const videoRef = React43.useRef(null);
10965
+ const [isPlaying, setIsPlaying] = React43.useState(Boolean(autoPlay));
10966
+ const [isLoaded, setIsLoaded] = React43.useState(false);
10967
+ const [currentTime, setCurrentTime] = React43.useState(0);
10968
+ const [duration, setDuration] = React43.useState(0);
10969
+ const [buffered, setBuffered] = React43.useState(0);
10970
+ const [volume, setVolume] = React43.useState(1);
10971
+ const [isMuted, setIsMuted] = React43.useState(Boolean(muted));
10972
+ const [isFullscreen, setIsFullscreen] = React43.useState(false);
10973
+ const [playbackRate, setPlaybackRate] = React43.useState(1);
10974
+ const [rateMenuOpen, setRateMenuOpen] = React43.useState(false);
10975
+ const [captionsOn, setCaptionsOn] = React43.useState(false);
10976
+ const [isPip, setIsPip] = React43.useState(false);
10977
+ const setRefs = React43.useCallback(
10468
10978
  (el) => {
10469
10979
  videoRef.current = el;
10470
10980
  if (typeof ref === "function") ref(el);
@@ -10472,14 +10982,14 @@ var Video = React41.forwardRef((props, ref) => {
10472
10982
  },
10473
10983
  [ref]
10474
10984
  );
10475
- React41.useEffect(() => {
10985
+ React43.useEffect(() => {
10476
10986
  const onFsChange = () => {
10477
10987
  setIsFullscreen(document.fullscreenElement === containerRef.current);
10478
10988
  };
10479
10989
  document.addEventListener("fullscreenchange", onFsChange);
10480
10990
  return () => document.removeEventListener("fullscreenchange", onFsChange);
10481
10991
  }, []);
10482
- React41.useEffect(() => {
10992
+ React43.useEffect(() => {
10483
10993
  const v = videoRef.current;
10484
10994
  if (!v) return;
10485
10995
  const onEnter = () => setIsPip(true);
@@ -10593,13 +11103,13 @@ var Video = React41.forwardRef((props, ref) => {
10593
11103
  const volumePct = (isMuted ? 0 : volume) * 100;
10594
11104
  const VolumeGlyph = isMuted || volume === 0 ? VolumeXIcon_default : volume < 0.5 ? VolumeIcon_default : Volume2Icon_default;
10595
11105
  const pipSupported = typeof document !== "undefined" && "pictureInPictureEnabled" in document && document.pictureInPictureEnabled;
10596
- return /* @__PURE__ */ jsxs223(
11106
+ return /* @__PURE__ */ jsxs225(
10597
11107
  "div",
10598
11108
  {
10599
11109
  ref: containerRef,
10600
11110
  className: clsx_default("lib-xplat-video", showControls && "has-controls"),
10601
11111
  children: [
10602
- /* @__PURE__ */ jsx352(
11112
+ /* @__PURE__ */ jsx354(
10603
11113
  "video",
10604
11114
  {
10605
11115
  ref: setRefs,
@@ -10620,7 +11130,7 @@ var Video = React41.forwardRef((props, ref) => {
10620
11130
  children
10621
11131
  }
10622
11132
  ),
10623
- showCenterPlay && /* @__PURE__ */ jsx352(
11133
+ showCenterPlay && /* @__PURE__ */ jsx354(
10624
11134
  "button",
10625
11135
  {
10626
11136
  type: "button",
@@ -10632,11 +11142,11 @@ var Video = React41.forwardRef((props, ref) => {
10632
11142
  onClick: togglePlay,
10633
11143
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
10634
11144
  tabIndex: -1,
10635
- children: /* @__PURE__ */ jsx352("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx352(PlayCircleIcon_default, {}) })
11145
+ children: /* @__PURE__ */ jsx354("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx354(PlayCircleIcon_default, {}) })
10636
11146
  }
10637
11147
  ),
10638
- showControls && /* @__PURE__ */ jsxs223("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
10639
- /* @__PURE__ */ jsx352(
11148
+ showControls && /* @__PURE__ */ jsxs225("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
11149
+ /* @__PURE__ */ jsx354(
10640
11150
  "input",
10641
11151
  {
10642
11152
  type: "range",
@@ -10653,29 +11163,29 @@ var Video = React41.forwardRef((props, ref) => {
10653
11163
  }
10654
11164
  }
10655
11165
  ),
10656
- /* @__PURE__ */ jsxs223("div", { className: "controls-row", children: [
10657
- /* @__PURE__ */ jsx352(
11166
+ /* @__PURE__ */ jsxs225("div", { className: "controls-row", children: [
11167
+ /* @__PURE__ */ jsx354(
10658
11168
  "button",
10659
11169
  {
10660
11170
  type: "button",
10661
11171
  className: "control-btn",
10662
11172
  onClick: togglePlay,
10663
11173
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
10664
- children: isPlaying ? /* @__PURE__ */ jsx352(PauseIcon_default, {}) : /* @__PURE__ */ jsx352(PlayIcon_default, {})
11174
+ children: isPlaying ? /* @__PURE__ */ jsx354(PauseIcon_default, {}) : /* @__PURE__ */ jsx354(PlayIcon_default, {})
10665
11175
  }
10666
11176
  ),
10667
- /* @__PURE__ */ jsxs223("div", { className: "volume-group", children: [
10668
- /* @__PURE__ */ jsx352(
11177
+ /* @__PURE__ */ jsxs225("div", { className: "volume-group", children: [
11178
+ /* @__PURE__ */ jsx354(
10669
11179
  "button",
10670
11180
  {
10671
11181
  type: "button",
10672
11182
  className: "control-btn",
10673
11183
  onClick: toggleMute,
10674
11184
  "aria-label": isMuted ? "\uC74C\uC18C\uAC70 \uD574\uC81C" : "\uC74C\uC18C\uAC70",
10675
- children: /* @__PURE__ */ jsx352(VolumeGlyph, {})
11185
+ children: /* @__PURE__ */ jsx354(VolumeGlyph, {})
10676
11186
  }
10677
11187
  ),
10678
- /* @__PURE__ */ jsx352(
11188
+ /* @__PURE__ */ jsx354(
10679
11189
  "input",
10680
11190
  {
10681
11191
  type: "range",
@@ -10690,14 +11200,14 @@ var Video = React41.forwardRef((props, ref) => {
10690
11200
  }
10691
11201
  )
10692
11202
  ] }),
10693
- /* @__PURE__ */ jsxs223("span", { className: "time", children: [
11203
+ /* @__PURE__ */ jsxs225("span", { className: "time", children: [
10694
11204
  formatTime(currentTime),
10695
11205
  " / ",
10696
11206
  formatTime(duration)
10697
11207
  ] }),
10698
- /* @__PURE__ */ jsx352("div", { className: "controls-spacer" }),
10699
- playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs223("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
10700
- /* @__PURE__ */ jsxs223(
11208
+ /* @__PURE__ */ jsx354("div", { className: "controls-spacer" }),
11209
+ playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs225("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
11210
+ /* @__PURE__ */ jsxs225(
10701
11211
  "button",
10702
11212
  {
10703
11213
  type: "button",
@@ -10711,7 +11221,7 @@ var Video = React41.forwardRef((props, ref) => {
10711
11221
  ]
10712
11222
  }
10713
11223
  ),
10714
- rateMenuOpen && /* @__PURE__ */ jsx352("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx352("li", { children: /* @__PURE__ */ jsxs223(
11224
+ rateMenuOpen && /* @__PURE__ */ jsx354("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx354("li", { children: /* @__PURE__ */ jsxs225(
10715
11225
  "button",
10716
11226
  {
10717
11227
  type: "button",
@@ -10725,7 +11235,7 @@ var Video = React41.forwardRef((props, ref) => {
10725
11235
  }
10726
11236
  ) }, r2)) })
10727
11237
  ] }),
10728
- showCaptions && /* @__PURE__ */ jsx352(
11238
+ showCaptions && /* @__PURE__ */ jsx354(
10729
11239
  "button",
10730
11240
  {
10731
11241
  type: "button",
@@ -10733,37 +11243,37 @@ var Video = React41.forwardRef((props, ref) => {
10733
11243
  onClick: toggleCaptions,
10734
11244
  "aria-label": captionsOn ? "\uC790\uB9C9 \uB044\uAE30" : "\uC790\uB9C9 \uCF1C\uAE30",
10735
11245
  "aria-pressed": captionsOn,
10736
- children: /* @__PURE__ */ jsx352(TypeIcon_default, {})
11246
+ children: /* @__PURE__ */ jsx354(TypeIcon_default, {})
10737
11247
  }
10738
11248
  ),
10739
- showPip && pipSupported && /* @__PURE__ */ jsx352(
11249
+ showPip && pipSupported && /* @__PURE__ */ jsx354(
10740
11250
  "button",
10741
11251
  {
10742
11252
  type: "button",
10743
11253
  className: clsx_default("control-btn", isPip && "is-active"),
10744
11254
  onClick: togglePip,
10745
11255
  "aria-label": isPip ? "PIP \uC885\uB8CC" : "PIP",
10746
- children: /* @__PURE__ */ jsx352(PipIcon, {})
11256
+ children: /* @__PURE__ */ jsx354(PipIcon, {})
10747
11257
  }
10748
11258
  ),
10749
- showDownload && /* @__PURE__ */ jsx352(
11259
+ showDownload && /* @__PURE__ */ jsx354(
10750
11260
  "a",
10751
11261
  {
10752
11262
  className: "control-btn",
10753
11263
  href: src,
10754
11264
  download: downloadFileName ?? true,
10755
11265
  "aria-label": "\uB2E4\uC6B4\uB85C\uB4DC",
10756
- children: /* @__PURE__ */ jsx352(DownloadIcon_default, {})
11266
+ children: /* @__PURE__ */ jsx354(DownloadIcon_default, {})
10757
11267
  }
10758
11268
  ),
10759
- /* @__PURE__ */ jsx352(
11269
+ /* @__PURE__ */ jsx354(
10760
11270
  "button",
10761
11271
  {
10762
11272
  type: "button",
10763
11273
  className: "control-btn",
10764
11274
  onClick: toggleFullscreen,
10765
11275
  "aria-label": isFullscreen ? "\uC804\uCCB4\uD654\uBA74 \uC885\uB8CC" : "\uC804\uCCB4\uD654\uBA74",
10766
- children: isFullscreen ? /* @__PURE__ */ jsx352(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx352(MaximizeIcon_default, {})
11276
+ children: isFullscreen ? /* @__PURE__ */ jsx354(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx354(MaximizeIcon_default, {})
10767
11277
  }
10768
11278
  )
10769
11279
  ] })
@@ -10776,7 +11286,7 @@ Video.displayName = "Video";
10776
11286
  var Video_default = Video;
10777
11287
 
10778
11288
  // src/layout/Grid/FullGrid/FullGrid.tsx
10779
- import { jsx as jsx353 } from "react/jsx-runtime";
11289
+ import { jsx as jsx355 } from "react/jsx-runtime";
10780
11290
  var GAP_MAP = {
10781
11291
  none: "var(--spacing-space-none)",
10782
11292
  xs: "var(--spacing-space-1)",
@@ -10789,13 +11299,13 @@ var GAP_MAP = {
10789
11299
  var FullGrid = (props) => {
10790
11300
  const { children, gap } = props;
10791
11301
  const style = gap != null ? { gap: GAP_MAP[gap] } : void 0;
10792
- return /* @__PURE__ */ jsx353("div", { className: "lib-xplat-full-grid", style, children });
11302
+ return /* @__PURE__ */ jsx355("div", { className: "lib-xplat-full-grid", style, children });
10793
11303
  };
10794
11304
  FullGrid.displayName = "FullGrid";
10795
11305
  var FullGrid_default = FullGrid;
10796
11306
 
10797
11307
  // src/layout/Grid/FullScreen/FullScreen.tsx
10798
- import { jsx as jsx354 } from "react/jsx-runtime";
11308
+ import { jsx as jsx356 } from "react/jsx-runtime";
10799
11309
  var GAP_MAP2 = {
10800
11310
  none: "var(--spacing-space-none)",
10801
11311
  xs: "var(--spacing-space-1)",
@@ -10808,13 +11318,13 @@ var GAP_MAP2 = {
10808
11318
  var FullScreen = (props) => {
10809
11319
  const { children, gap } = props;
10810
11320
  const style = gap != null ? { gap: GAP_MAP2[gap] } : void 0;
10811
- return /* @__PURE__ */ jsx354("div", { className: "lib-xplat-full-screen", style, children });
11321
+ return /* @__PURE__ */ jsx356("div", { className: "lib-xplat-full-screen", style, children });
10812
11322
  };
10813
11323
  FullScreen.displayName = "FullScreen";
10814
11324
  var FullScreen_default = FullScreen;
10815
11325
 
10816
11326
  // src/layout/Grid/Item/Item.tsx
10817
- import { jsx as jsx355 } from "react/jsx-runtime";
11327
+ import { jsx as jsx357 } from "react/jsx-runtime";
10818
11328
  var calculateSpans = (column) => {
10819
11329
  const spans = {};
10820
11330
  let inherited = column.default;
@@ -10831,35 +11341,35 @@ var GridItem = ({ column, children, className }) => {
10831
11341
  Object.entries(spans).forEach(([key, value]) => {
10832
11342
  style[`--column-${key}`] = value;
10833
11343
  });
10834
- return /* @__PURE__ */ jsx355("div", { className: clsx_default("lib-xplat-grid-item", className), style, children });
11344
+ return /* @__PURE__ */ jsx357("div", { className: clsx_default("lib-xplat-grid-item", className), style, children });
10835
11345
  };
10836
11346
  GridItem.displayName = "GridItem";
10837
11347
  var Item_default = GridItem;
10838
11348
 
10839
11349
  // src/layout/Header/Header.tsx
10840
- import { jsx as jsx356, jsxs as jsxs224 } from "react/jsx-runtime";
11350
+ import { jsx as jsx358, jsxs as jsxs226 } from "react/jsx-runtime";
10841
11351
  var Header = ({
10842
11352
  logo,
10843
11353
  centerContent,
10844
11354
  rightContent
10845
11355
  }) => {
10846
- return /* @__PURE__ */ jsxs224("div", { className: "lib-xplat-layout-header", children: [
10847
- /* @__PURE__ */ jsx356("div", { children: logo }),
10848
- /* @__PURE__ */ jsx356("div", { children: centerContent }),
10849
- /* @__PURE__ */ jsx356("div", { children: rightContent })
11356
+ return /* @__PURE__ */ jsxs226("div", { className: "lib-xplat-layout-header", children: [
11357
+ /* @__PURE__ */ jsx358("div", { children: logo }),
11358
+ /* @__PURE__ */ jsx358("div", { children: centerContent }),
11359
+ /* @__PURE__ */ jsx358("div", { children: rightContent })
10850
11360
  ] });
10851
11361
  };
10852
11362
  Header.displayName = "Header";
10853
11363
  var Header_default = Header;
10854
11364
 
10855
11365
  // src/layout/Layout/Layout.tsx
10856
- import { Fragment as Fragment7, jsx as jsx357, jsxs as jsxs225 } from "react/jsx-runtime";
11366
+ import { Fragment as Fragment7, jsx as jsx359, jsxs as jsxs227 } from "react/jsx-runtime";
10857
11367
  var Layout = (props) => {
10858
11368
  const { header, sideBar, children } = props;
10859
- return /* @__PURE__ */ jsx357("div", { className: "lib-xplat-layout", children: /* @__PURE__ */ jsxs225("div", { className: "lib-xplat-layout-content-wrapper", children: [
10860
- sideBar && /* @__PURE__ */ jsx357(Fragment7, { children: sideBar }),
10861
- /* @__PURE__ */ jsxs225("div", { className: "lib-xplat-layout-content", children: [
10862
- header && /* @__PURE__ */ jsx357("div", { className: "lib-xplat-layout-conent-header", children: header }),
11369
+ return /* @__PURE__ */ jsx359("div", { className: "lib-xplat-layout", children: /* @__PURE__ */ jsxs227("div", { className: "lib-xplat-layout-content-wrapper", children: [
11370
+ sideBar && /* @__PURE__ */ jsx359(Fragment7, { children: sideBar }),
11371
+ /* @__PURE__ */ jsxs227("div", { className: "lib-xplat-layout-content", children: [
11372
+ header && /* @__PURE__ */ jsx359("div", { className: "lib-xplat-layout-conent-header", children: header }),
10863
11373
  children
10864
11374
  ] })
10865
11375
  ] }) });
@@ -10868,31 +11378,31 @@ Layout.displayName = "Layout";
10868
11378
  var Layout_default = Layout;
10869
11379
 
10870
11380
  // src/layout/SideBar/SideBar.tsx
10871
- import React43 from "react";
11381
+ import React45 from "react";
10872
11382
 
10873
11383
  // src/layout/SideBar/SideBarContext.tsx
10874
- import React42 from "react";
10875
- var SideBarContext = React42.createContext(null);
11384
+ import React44 from "react";
11385
+ var SideBarContext = React44.createContext(null);
10876
11386
  var useSideBarContext = () => {
10877
- const ctx = React42.useContext(SideBarContext);
11387
+ const ctx = React44.useContext(SideBarContext);
10878
11388
  if (!ctx) throw new Error("Error");
10879
11389
  return ctx;
10880
11390
  };
10881
11391
  var SideBarContext_default = SideBarContext;
10882
11392
 
10883
11393
  // src/layout/SideBar/SideBar.tsx
10884
- import { jsx as jsx358 } from "react/jsx-runtime";
11394
+ import { jsx as jsx360 } from "react/jsx-runtime";
10885
11395
  var SideBar = (props) => {
10886
11396
  const { children, className } = props;
10887
- const [isOpen, setIsOpen] = React43.useState(true);
11397
+ const [isOpen, setIsOpen] = React45.useState(true);
10888
11398
  const handleSwitchSideBar = () => {
10889
11399
  setIsOpen((prev) => !prev);
10890
11400
  };
10891
- return /* @__PURE__ */ jsx358(
11401
+ return /* @__PURE__ */ jsx360(
10892
11402
  SideBarContext_default.Provider,
10893
11403
  {
10894
11404
  value: { isSidebarOpen: isOpen, handleSwitchSideBar },
10895
- children: /* @__PURE__ */ jsx358(
11405
+ children: /* @__PURE__ */ jsx360(
10896
11406
  "div",
10897
11407
  {
10898
11408
  className: clsx_default(
@@ -11199,6 +11709,7 @@ export {
11199
11709
  Spinner_default as Spinner,
11200
11710
  SquareIcon_default as SquareIcon,
11201
11711
  StarIcon_default as StarIcon,
11712
+ Stat_default as Stat,
11202
11713
  Steps_default as Steps,
11203
11714
  StopCircleIcon_default as StopCircleIcon,
11204
11715
  SuccessIcon_default as SuccessIcon,
@@ -11223,6 +11734,7 @@ export {
11223
11734
  ThermometerIcon_default as ThermometerIcon,
11224
11735
  ThumbsDownIcon_default as ThumbsDownIcon,
11225
11736
  ThumbsUpIcon_default as ThumbsUpIcon,
11737
+ TimePicker_default as TimePicker,
11226
11738
  ToastProvider,
11227
11739
  ToggleLeftIcon_default as ToggleLeftIcon,
11228
11740
  ToggleRightIcon_default as ToggleRightIcon,