@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.cjs CHANGED
@@ -320,6 +320,7 @@ __export(index_exports, {
320
320
  Spinner: () => Spinner_default,
321
321
  SquareIcon: () => SquareIcon_default,
322
322
  StarIcon: () => StarIcon_default,
323
+ Stat: () => Stat_default,
323
324
  Steps: () => Steps_default,
324
325
  StopCircleIcon: () => StopCircleIcon_default,
325
326
  SuccessIcon: () => SuccessIcon_default,
@@ -344,6 +345,7 @@ __export(index_exports, {
344
345
  ThermometerIcon: () => ThermometerIcon_default,
345
346
  ThumbsDownIcon: () => ThumbsDownIcon_default,
346
347
  ThumbsUpIcon: () => ThumbsUpIcon_default,
348
+ TimePicker: () => TimePicker_default,
347
349
  ToastProvider: () => ToastProvider,
348
350
  ToggleLeftIcon: () => ToggleLeftIcon_default,
349
351
  ToggleRightIcon: () => ToggleRightIcon_default,
@@ -6029,11 +6031,16 @@ var FieldMessage = (props) => {
6029
6031
  FieldMessage.displayName = "FieldMessage";
6030
6032
  var FieldMessage_default = FieldMessage;
6031
6033
  var Field = (props) => {
6032
- const { validations, children } = props;
6033
- if (!validations || validations.length === 0) return /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(import_jsx_runtime297.Fragment, { children });
6034
+ const { label, required = false, htmlFor, validations, children } = props;
6035
+ const hasMessages = !!validations && validations.length > 0;
6036
+ if (!label && !hasMessages) return /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(import_jsx_runtime297.Fragment, { children });
6034
6037
  return /* @__PURE__ */ (0, import_jsx_runtime297.jsxs)("div", { className: "lib-xplat-field", children: [
6038
+ label && /* @__PURE__ */ (0, import_jsx_runtime297.jsxs)("label", { className: "lib-xplat-field-label", htmlFor, children: [
6039
+ label,
6040
+ required && /* @__PURE__ */ (0, import_jsx_runtime297.jsx)("span", { className: "required", "aria-hidden": "true", children: "*" })
6041
+ ] }),
6035
6042
  children,
6036
- /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(FieldMessage, { validations })
6043
+ hasMessages && /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(FieldMessage, { validations })
6037
6044
  ] });
6038
6045
  };
6039
6046
  Field.displayName = "Field";
@@ -6044,7 +6051,9 @@ var import_jsx_runtime298 = require("react/jsx-runtime");
6044
6051
  var MAX_HEIGHT = 400;
6045
6052
  var AutoResizeTextArea = import_react2.default.forwardRef(
6046
6053
  (props, ref) => {
6047
- const { value, className, onChange, disabled, bare = false, validations, ...textareaProps } = props;
6054
+ const { value, className, onChange, disabled, bare = false, validations, label, required, ...textareaProps } = props;
6055
+ const autoId = import_react2.default.useId();
6056
+ const fieldId = props.id ?? autoId;
6048
6057
  const localRef = import_react2.default.useRef(null);
6049
6058
  const setRefs = (el) => {
6050
6059
  localRef.current = el;
@@ -6078,6 +6087,7 @@ var AutoResizeTextArea = import_react2.default.forwardRef(
6078
6087
  "aria-invalid": hasError(validations) || void 0,
6079
6088
  ...textareaProps,
6080
6089
  ref: setRefs,
6090
+ id: fieldId,
6081
6091
  className,
6082
6092
  disabled,
6083
6093
  value,
@@ -6091,12 +6101,13 @@ var AutoResizeTextArea = import_react2.default.forwardRef(
6091
6101
  "aria-invalid": hasError(validations) || void 0,
6092
6102
  ...textareaProps,
6093
6103
  ref: setRefs,
6104
+ id: fieldId,
6094
6105
  disabled,
6095
6106
  value,
6096
6107
  onChange: handleChange
6097
6108
  }
6098
6109
  ) }) });
6099
- return /* @__PURE__ */ (0, import_jsx_runtime298.jsx)(Field, { validations, children: control });
6110
+ return /* @__PURE__ */ (0, import_jsx_runtime298.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
6100
6111
  }
6101
6112
  );
6102
6113
  AutoResizeTextArea.displayName = "AutoResizeTextArea";
@@ -7314,8 +7325,11 @@ var ChatInput = import_react7.default.forwardRef(
7314
7325
  buttonType = "primary",
7315
7326
  onSubmit,
7316
7327
  onChange,
7317
- validations
7328
+ validations,
7329
+ label,
7330
+ required
7318
7331
  } = props;
7332
+ const fieldId = import_react7.default.useId();
7319
7333
  const isControlled = valueProp !== void 0;
7320
7334
  const [internalValue, setInternalValue] = import_react7.default.useState("");
7321
7335
  const value = isControlled ? valueProp : internalValue;
@@ -7340,6 +7354,7 @@ var ChatInput = import_react7.default.forwardRef(
7340
7354
  /* @__PURE__ */ (0, import_jsx_runtime308.jsx)(
7341
7355
  AutoResizeTextArea_default,
7342
7356
  {
7357
+ id: fieldId,
7343
7358
  ref,
7344
7359
  bare: true,
7345
7360
  className: "chat-input-textarea",
@@ -7364,7 +7379,7 @@ var ChatInput = import_react7.default.forwardRef(
7364
7379
  }
7365
7380
  )
7366
7381
  ] });
7367
- return /* @__PURE__ */ (0, import_jsx_runtime308.jsx)(Field, { validations, children: control });
7382
+ return /* @__PURE__ */ (0, import_jsx_runtime308.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
7368
7383
  }
7369
7384
  );
7370
7385
  ChatInput.displayName = "ChatInput";
@@ -7448,7 +7463,7 @@ Chip.displayName = "Chip";
7448
7463
  var Chip_default = Chip;
7449
7464
 
7450
7465
  // src/components/DatePicker/InputDatePicker/index.tsx
7451
- var import_react12 = __toESM(require("react"), 1);
7466
+ var import_react13 = __toESM(require("react"), 1);
7452
7467
 
7453
7468
  // src/components/Input/Input.tsx
7454
7469
  var import_react8 = __toESM(require("react"), 1);
@@ -7546,8 +7561,12 @@ var Input = import_react8.default.forwardRef((props, ref) => {
7546
7561
  suffix,
7547
7562
  disabled,
7548
7563
  validations,
7564
+ label,
7565
+ required,
7549
7566
  ...inputProps
7550
7567
  } = props;
7568
+ const autoId = import_react8.default.useId();
7569
+ const fieldId = inputProps.id ?? autoId;
7551
7570
  const localValue = formatValue(type, value);
7552
7571
  const handleChange = (e) => {
7553
7572
  let val = e.target.value;
@@ -7563,7 +7582,7 @@ var Input = import_react8.default.forwardRef((props, ref) => {
7563
7582
  onChange(event);
7564
7583
  }
7565
7584
  };
7566
- return /* @__PURE__ */ (0, import_jsx_runtime311.jsxs)("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
7585
+ return /* @__PURE__ */ (0, import_jsx_runtime311.jsx)(Field, { label, required, htmlFor: fieldId, children: /* @__PURE__ */ (0, import_jsx_runtime311.jsxs)("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
7567
7586
  /* @__PURE__ */ (0, import_jsx_runtime311.jsxs)(
7568
7587
  "div",
7569
7588
  {
@@ -7574,6 +7593,7 @@ var Input = import_react8.default.forwardRef((props, ref) => {
7574
7593
  {
7575
7594
  ...inputProps,
7576
7595
  ref,
7596
+ id: fieldId,
7577
7597
  disabled,
7578
7598
  type: type === "number" ? "text" : type,
7579
7599
  value: localValue,
@@ -7586,7 +7606,7 @@ var Input = import_react8.default.forwardRef((props, ref) => {
7586
7606
  }
7587
7607
  ),
7588
7608
  /* @__PURE__ */ (0, import_jsx_runtime311.jsx)(FieldMessage_default, { validations })
7589
- ] });
7609
+ ] }) });
7590
7610
  });
7591
7611
  Input.displayName = "Input";
7592
7612
  var Input_default = Input;
@@ -7616,16 +7636,96 @@ PasswordInput.displayName = "PasswordInput";
7616
7636
  var PasswordInput_default = PasswordInput;
7617
7637
 
7618
7638
  // src/components/Modal/Modal.tsx
7619
- var import_react10 = __toESM(require("react"), 1);
7639
+ var import_react11 = __toESM(require("react"), 1);
7620
7640
  var import_react_dom = require("react-dom");
7641
+
7642
+ // src/tokens/hooks/useOverlayKeyboard.ts
7643
+ var import_react10 = __toESM(require("react"), 1);
7644
+ var FOCUSABLE = [
7645
+ "a[href]",
7646
+ "button:not([disabled])",
7647
+ "input:not([disabled]):not([type='hidden'])",
7648
+ "select:not([disabled])",
7649
+ "textarea:not([disabled])",
7650
+ "[tabindex]:not([tabindex='-1'])"
7651
+ ].join(",");
7652
+ var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
7653
+ // 화면에 없는 것은 제외 (display:none 등)
7654
+ (n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
7655
+ );
7656
+ var useEscapeKey = (enabled, onEscape) => {
7657
+ import_react10.default.useEffect(() => {
7658
+ if (!enabled) return;
7659
+ const onKey = (e) => {
7660
+ if (e.key !== "Escape") return;
7661
+ if (e.defaultPrevented) return;
7662
+ e.preventDefault();
7663
+ onEscape();
7664
+ };
7665
+ document.addEventListener("keydown", onKey);
7666
+ return () => document.removeEventListener("keydown", onKey);
7667
+ }, [enabled, onEscape]);
7668
+ };
7669
+ var useFocusTrap = (containerRef, enabled, options = {}) => {
7670
+ const { trap = false, initialFocus } = options;
7671
+ const restoreRef = import_react10.default.useRef(null);
7672
+ import_react10.default.useEffect(() => {
7673
+ if (!enabled) return;
7674
+ restoreRef.current = document.activeElement;
7675
+ const raf = requestAnimationFrame(() => {
7676
+ const el = containerRef.current;
7677
+ if (!el) return;
7678
+ const target = initialFocus?.current ?? focusableIn(el)[0] ?? el;
7679
+ if (!target.hasAttribute("tabindex") && !focusableIn(el).includes(target)) {
7680
+ target.setAttribute("tabindex", "-1");
7681
+ }
7682
+ target.focus({ preventScroll: true });
7683
+ });
7684
+ return () => {
7685
+ cancelAnimationFrame(raf);
7686
+ const prev = restoreRef.current;
7687
+ if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
7688
+ };
7689
+ }, [enabled, containerRef, initialFocus]);
7690
+ import_react10.default.useEffect(() => {
7691
+ if (!enabled || !trap) return;
7692
+ const onKey = (e) => {
7693
+ if (e.key !== "Tab") return;
7694
+ const el = containerRef.current;
7695
+ if (!el) return;
7696
+ const items = focusableIn(el);
7697
+ if (items.length === 0) {
7698
+ e.preventDefault();
7699
+ return;
7700
+ }
7701
+ const first = items[0];
7702
+ const last = items[items.length - 1];
7703
+ const active = document.activeElement;
7704
+ if (e.shiftKey && (active === first || !el.contains(active))) {
7705
+ e.preventDefault();
7706
+ last.focus();
7707
+ } else if (!e.shiftKey && (active === last || !el.contains(active))) {
7708
+ e.preventDefault();
7709
+ first.focus();
7710
+ }
7711
+ };
7712
+ document.addEventListener("keydown", onKey);
7713
+ return () => document.removeEventListener("keydown", onKey);
7714
+ }, [enabled, trap, containerRef]);
7715
+ };
7716
+
7717
+ // src/components/Modal/Modal.tsx
7621
7718
  var import_jsx_runtime313 = require("react/jsx-runtime");
7622
7719
  var ANIMATION_DURATION_MS = 200;
7623
7720
  var Modal = (props) => {
7624
7721
  const { isOpen, onClose, children } = props;
7625
- const [mounted, setMounted] = import_react10.default.useState(false);
7626
- const [visible, setVisible] = import_react10.default.useState(false);
7627
- const [settled, setSettled] = import_react10.default.useState(false);
7628
- import_react10.default.useEffect(() => {
7722
+ const [mounted, setMounted] = import_react11.default.useState(false);
7723
+ const [visible, setVisible] = import_react11.default.useState(false);
7724
+ const [settled, setSettled] = import_react11.default.useState(false);
7725
+ const boxRef = import_react11.default.useRef(null);
7726
+ useEscapeKey(isOpen, onClose);
7727
+ useFocusTrap(boxRef, isOpen && mounted, { trap: true });
7728
+ import_react11.default.useEffect(() => {
7629
7729
  if (isOpen) {
7630
7730
  setMounted(true);
7631
7731
  const show = setTimeout(() => setVisible(true), 1);
@@ -7652,6 +7752,7 @@ var Modal = (props) => {
7652
7752
  children: /* @__PURE__ */ (0, import_jsx_runtime313.jsx)(
7653
7753
  "div",
7654
7754
  {
7755
+ ref: boxRef,
7655
7756
  className: clsx_default("lib-xplat-modal", "modal-box", stateClass, settled && "settled"),
7656
7757
  role: "dialog",
7657
7758
  "aria-modal": "true",
@@ -7668,9 +7769,9 @@ Modal.displayName = "Modal";
7668
7769
  var Modal_default = Modal;
7669
7770
 
7670
7771
  // src/components/DatePicker/SingleDatePicker/index.tsx
7671
- var import_react11 = __toESM(require("react"), 1);
7772
+ var import_react12 = __toESM(require("react"), 1);
7672
7773
  var import_jsx_runtime314 = require("react/jsx-runtime");
7673
- var DayCell2 = import_react11.default.memo(
7774
+ var DayCell2 = import_react12.default.memo(
7674
7775
  ({
7675
7776
  day,
7676
7777
  disabled,
@@ -7722,26 +7823,26 @@ var SingleDatePicker = (props) => {
7722
7823
  initialYear,
7723
7824
  initialMonth
7724
7825
  );
7725
- const [pickerMode, setPickerMode] = import_react11.default.useState("days");
7726
- const [yearRangeStart, setYearRangeStart] = import_react11.default.useState(
7826
+ const [pickerMode, setPickerMode] = import_react12.default.useState("days");
7827
+ const [yearRangeStart, setYearRangeStart] = import_react12.default.useState(
7727
7828
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
7728
7829
  );
7729
- const minTime = import_react11.default.useMemo(
7830
+ const minTime = import_react12.default.useMemo(
7730
7831
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
7731
7832
  [minDate]
7732
7833
  );
7733
- const maxTime = import_react11.default.useMemo(
7834
+ const maxTime = import_react12.default.useMemo(
7734
7835
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
7735
7836
  [maxDate]
7736
7837
  );
7737
- const highlightSet = import_react11.default.useMemo(() => {
7838
+ const highlightSet = import_react12.default.useMemo(() => {
7738
7839
  const set = /* @__PURE__ */ new Set();
7739
7840
  for (const h of highlightDates) {
7740
7841
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
7741
7842
  }
7742
7843
  return set;
7743
7844
  }, [highlightDates]);
7744
- const handleSelect = import_react11.default.useCallback(
7845
+ const handleSelect = import_react12.default.useCallback(
7745
7846
  (date) => {
7746
7847
  onChange?.(date);
7747
7848
  },
@@ -7870,8 +7971,8 @@ var formatDate = (date) => {
7870
7971
  };
7871
7972
  var InputDatePicker = (props) => {
7872
7973
  const { value, onChange, minDate, maxDate, disabled, locale = "ko", placeholder } = props;
7873
- const [isOpen, setIsOpen] = import_react12.default.useState(false);
7874
- const [tempDate, setTempDate] = import_react12.default.useState(value ?? /* @__PURE__ */ new Date());
7974
+ const [isOpen, setIsOpen] = import_react13.default.useState(false);
7975
+ const [tempDate, setTempDate] = import_react13.default.useState(value ?? /* @__PURE__ */ new Date());
7875
7976
  const handleOpen = () => {
7876
7977
  if (disabled) return;
7877
7978
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -7920,23 +8021,27 @@ InputDatePicker.displayName = "InputDatePicker";
7920
8021
  var InputDatePicker_default = InputDatePicker;
7921
8022
 
7922
8023
  // src/components/DatePicker/PopupPicker/index.tsx
7923
- var import_react16 = __toESM(require("react"), 1);
8024
+ var import_react17 = __toESM(require("react"), 1);
7924
8025
 
7925
8026
  // src/components/DatePicker/RangePicker/index.tsx
7926
- var import_react15 = __toESM(require("react"), 1);
8027
+ var import_react16 = __toESM(require("react"), 1);
7927
8028
 
7928
8029
  // src/components/Tab/Tab.tsx
7929
- var import_react14 = __toESM(require("react"), 1);
8030
+ var import_react15 = __toESM(require("react"), 1);
7930
8031
 
7931
8032
  // src/components/Tab/TabItem.tsx
7932
- var import_react13 = __toESM(require("react"), 1);
8033
+ var import_react14 = __toESM(require("react"), 1);
7933
8034
  var import_jsx_runtime316 = require("react/jsx-runtime");
7934
- var TabItem = import_react13.default.forwardRef((props, ref) => {
8035
+ var TabItem = import_react14.default.forwardRef((props, ref) => {
7935
8036
  const { isActive: isActive2, title, onClick } = props;
7936
8037
  return /* @__PURE__ */ (0, import_jsx_runtime316.jsx)(
7937
- "div",
8038
+ "button",
7938
8039
  {
7939
8040
  ref,
8041
+ type: "button",
8042
+ role: "tab",
8043
+ "aria-selected": isActive2,
8044
+ tabIndex: isActive2 ? 0 : -1,
7940
8045
  className: clsx_default("tab-item", isActive2 ? "active" : null),
7941
8046
  onClick,
7942
8047
  children: title
@@ -7951,44 +8056,64 @@ var import_jsx_runtime317 = require("react/jsx-runtime");
7951
8056
  var Tab = (props) => {
7952
8057
  const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
7953
8058
  const shape = variant ?? type ?? "default";
7954
- const [underlineStyle, setUnderlineStyle] = import_react14.default.useState({
8059
+ const [underlineStyle, setUnderlineStyle] = import_react15.default.useState({
7955
8060
  left: 0,
7956
8061
  width: 0
7957
8062
  });
7958
- const itemRefs = import_react14.default.useRef([]);
8063
+ const itemRefs = import_react15.default.useRef([]);
8064
+ const handleKeyDown = (e) => {
8065
+ const last = tabs.length - 1;
8066
+ let next = null;
8067
+ if (e.key === "ArrowRight") next = activeIndex >= last ? 0 : activeIndex + 1;
8068
+ else if (e.key === "ArrowLeft") next = activeIndex <= 0 ? last : activeIndex - 1;
8069
+ else if (e.key === "Home") next = 0;
8070
+ else if (e.key === "End") next = last;
8071
+ if (next === null) return;
8072
+ e.preventDefault();
8073
+ onChange(tabs[next], next);
8074
+ itemRefs.current[next]?.focus();
8075
+ };
7959
8076
  const handleChangeActiveTab = (tabItem, tabIdx) => {
7960
8077
  onChange(tabItem, tabIdx);
7961
8078
  };
7962
- import_react14.default.useEffect(() => {
8079
+ import_react15.default.useEffect(() => {
7963
8080
  const el = itemRefs.current[activeIndex];
7964
8081
  if (el) {
7965
8082
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
7966
8083
  }
7967
8084
  }, [activeIndex, tabs.length]);
7968
- return /* @__PURE__ */ (0, import_jsx_runtime317.jsxs)("div", { className: clsx_default("lib-xplat-tab", `type-${shape}`, size), children: [
7969
- tabs.map((tab, idx) => /* @__PURE__ */ (0, import_jsx_runtime317.jsx)(
7970
- TabItem_default,
7971
- {
7972
- onClick: () => handleChangeActiveTab(tab, idx),
7973
- isActive: activeIndex === idx,
7974
- ref: (el) => {
7975
- itemRefs.current[idx] = el;
7976
- },
7977
- title: tab.title
7978
- },
7979
- `${tab.value}_${idx}`
7980
- )),
7981
- shape === "toggle" && /* @__PURE__ */ (0, import_jsx_runtime317.jsx)(
7982
- "div",
7983
- {
7984
- className: "tab-toggle-underline",
7985
- style: {
7986
- left: underlineStyle.left,
7987
- width: underlineStyle.width
7988
- }
7989
- }
7990
- )
7991
- ] });
8085
+ return /* @__PURE__ */ (0, import_jsx_runtime317.jsxs)(
8086
+ "div",
8087
+ {
8088
+ className: clsx_default("lib-xplat-tab", `type-${shape}`, size),
8089
+ role: "tablist",
8090
+ onKeyDown: handleKeyDown,
8091
+ children: [
8092
+ tabs.map((tab, idx) => /* @__PURE__ */ (0, import_jsx_runtime317.jsx)(
8093
+ TabItem_default,
8094
+ {
8095
+ onClick: () => handleChangeActiveTab(tab, idx),
8096
+ isActive: activeIndex === idx,
8097
+ ref: (el) => {
8098
+ itemRefs.current[idx] = el;
8099
+ },
8100
+ title: tab.title
8101
+ },
8102
+ `${tab.value}_${idx}`
8103
+ )),
8104
+ shape === "toggle" && /* @__PURE__ */ (0, import_jsx_runtime317.jsx)(
8105
+ "div",
8106
+ {
8107
+ className: "tab-toggle-underline",
8108
+ style: {
8109
+ left: underlineStyle.left,
8110
+ width: underlineStyle.width
8111
+ }
8112
+ }
8113
+ )
8114
+ ]
8115
+ }
8116
+ );
7992
8117
  };
7993
8118
  Tab.displayName = "Tab";
7994
8119
  var Tab_default = Tab;
@@ -8004,7 +8129,7 @@ var RangePicker = (props) => {
8004
8129
  maxDate,
8005
8130
  locale = "ko"
8006
8131
  } = props;
8007
- const [activeTab, setActiveTab] = import_react15.default.useState("start");
8132
+ const [activeTab, setActiveTab] = import_react16.default.useState("start");
8008
8133
  const handleStartChange = (date) => {
8009
8134
  if (!date) return;
8010
8135
  const newStart = date > endDate ? endDate : date;
@@ -8089,7 +8214,7 @@ var RangePicker_default = RangePicker;
8089
8214
  var import_jsx_runtime319 = require("react/jsx-runtime");
8090
8215
  var PopupPicker = (props) => {
8091
8216
  const { component, type, locale } = props;
8092
- const [isOpen, setIsOpen] = import_react16.default.useState(false);
8217
+ const [isOpen, setIsOpen] = import_react17.default.useState(false);
8093
8218
  const handleClick = () => setIsOpen(true);
8094
8219
  const handleClose = () => setIsOpen(false);
8095
8220
  const handleSingleChange = (date) => {
@@ -8098,7 +8223,7 @@ var PopupPicker = (props) => {
8098
8223
  handleClose();
8099
8224
  };
8100
8225
  return /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: "lib-xplat-popup-datepicker", children: [
8101
- import_react16.default.cloneElement(component, { onClick: handleClick }),
8226
+ import_react17.default.cloneElement(component, { onClick: handleClick }),
8102
8227
  /* @__PURE__ */ (0, import_jsx_runtime319.jsx)(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
8103
8228
  /* @__PURE__ */ (0, import_jsx_runtime319.jsxs)("div", { className: "popup-datepicker-content", children: [
8104
8229
  type === "single" && /* @__PURE__ */ (0, import_jsx_runtime319.jsx)(
@@ -8157,15 +8282,18 @@ Divider.displayName = "Divider";
8157
8282
  var Divider_default = Divider;
8158
8283
 
8159
8284
  // src/components/Drawer/Drawer.tsx
8160
- var import_react17 = __toESM(require("react"), 1);
8285
+ var import_react18 = __toESM(require("react"), 1);
8161
8286
  var import_react_dom2 = require("react-dom");
8162
8287
  var import_jsx_runtime321 = require("react/jsx-runtime");
8163
8288
  var ANIMATION_DURATION_MS2 = 250;
8164
8289
  var Drawer = (props) => {
8165
8290
  const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
8166
- const [mounted, setMounted] = import_react17.default.useState(false);
8167
- const [visible, setVisible] = import_react17.default.useState(false);
8168
- import_react17.default.useEffect(() => {
8291
+ const [mounted, setMounted] = import_react18.default.useState(false);
8292
+ const [visible, setVisible] = import_react18.default.useState(false);
8293
+ const panelRef = import_react18.default.useRef(null);
8294
+ useEscapeKey(isOpen, onClose);
8295
+ useFocusTrap(panelRef, isOpen && mounted, { trap: true });
8296
+ import_react18.default.useEffect(() => {
8169
8297
  if (isOpen) {
8170
8298
  setMounted(true);
8171
8299
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -8187,6 +8315,7 @@ var Drawer = (props) => {
8187
8315
  children: /* @__PURE__ */ (0, import_jsx_runtime321.jsxs)(
8188
8316
  "div",
8189
8317
  {
8318
+ ref: panelRef,
8190
8319
  className: clsx_default("lib-xplat-drawer", placement, size, stateClass),
8191
8320
  role: "dialog",
8192
8321
  "aria-modal": "true",
@@ -8209,7 +8338,7 @@ Drawer.displayName = "Drawer";
8209
8338
  var Drawer_default = Drawer;
8210
8339
 
8211
8340
  // src/components/Dropdown/Dropdown.tsx
8212
- var import_react20 = __toESM(require("react"), 1);
8341
+ var import_react21 = __toESM(require("react"), 1);
8213
8342
 
8214
8343
  // src/tokens/hooks/Portal.tsx
8215
8344
  var import_react_dom3 = __toESM(require("react-dom"), 1);
@@ -8221,13 +8350,13 @@ Portal.displayName = "Portal";
8221
8350
  var Portal_default = Portal;
8222
8351
 
8223
8352
  // src/tokens/hooks/useAutoPosition.ts
8224
- var import_react18 = __toESM(require("react"), 1);
8353
+ var import_react19 = __toESM(require("react"), 1);
8225
8354
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8226
- const [position, setPosition] = import_react18.default.useState({
8355
+ const [position, setPosition] = import_react19.default.useState({
8227
8356
  position: {},
8228
8357
  direction: "bottom"
8229
8358
  });
8230
- const calculatePosition = import_react18.default.useCallback(() => {
8359
+ const calculatePosition = import_react19.default.useCallback(() => {
8231
8360
  if (!triggerRef.current || !popRef.current) return;
8232
8361
  const triggerRect = triggerRef.current.getBoundingClientRect();
8233
8362
  const popW = popRef.current.offsetWidth;
@@ -8254,13 +8383,13 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8254
8383
  direction
8255
8384
  });
8256
8385
  }, [triggerRef, popRef]);
8257
- import_react18.default.useLayoutEffect(() => {
8386
+ import_react19.default.useLayoutEffect(() => {
8258
8387
  if (!enabled) return;
8259
8388
  calculatePosition();
8260
8389
  const raf = requestAnimationFrame(calculatePosition);
8261
8390
  return () => cancelAnimationFrame(raf);
8262
8391
  }, [calculatePosition, enabled]);
8263
- import_react18.default.useEffect(() => {
8392
+ import_react19.default.useEffect(() => {
8264
8393
  if (!enabled || !popRef.current) return;
8265
8394
  const observer = new ResizeObserver(() => {
8266
8395
  calculatePosition();
@@ -8268,7 +8397,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8268
8397
  observer.observe(popRef.current);
8269
8398
  return () => observer.disconnect();
8270
8399
  }, [calculatePosition, enabled, popRef]);
8271
- import_react18.default.useEffect(() => {
8400
+ import_react19.default.useEffect(() => {
8272
8401
  if (!enabled) return;
8273
8402
  window.addEventListener("resize", calculatePosition);
8274
8403
  window.addEventListener("scroll", calculatePosition, true);
@@ -8282,9 +8411,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8282
8411
  var useAutoPosition_default = useAutoPosition;
8283
8412
 
8284
8413
  // src/tokens/hooks/useClickOutside.ts
8285
- var import_react19 = __toESM(require("react"), 1);
8414
+ var import_react20 = __toESM(require("react"), 1);
8286
8415
  var useClickOutside = (refs, handler, enabled = true) => {
8287
- import_react19.default.useEffect(() => {
8416
+ import_react20.default.useEffect(() => {
8288
8417
  if (!enabled) return;
8289
8418
  const refArray = Array.isArray(refs) ? refs : [refs];
8290
8419
  const listener = (event) => {
@@ -8310,14 +8439,18 @@ var useClickOutside_default = useClickOutside;
8310
8439
  var import_jsx_runtime322 = require("react/jsx-runtime");
8311
8440
  var Dropdown = (props) => {
8312
8441
  const { items, children } = props;
8313
- const [isOpen, setIsOpen] = import_react20.default.useState(false);
8314
- const [mounted, setMounted] = import_react20.default.useState(false);
8315
- const [visible, setVisible] = import_react20.default.useState(false);
8316
- const triggerRef = import_react20.default.useRef(null);
8317
- const menuRef = import_react20.default.useRef(null);
8442
+ const [isOpen, setIsOpen] = import_react21.default.useState(false);
8443
+ const [mounted, setMounted] = import_react21.default.useState(false);
8444
+ const [visible, setVisible] = import_react21.default.useState(false);
8445
+ const triggerRef = import_react21.default.useRef(null);
8446
+ const menuRef = import_react21.default.useRef(null);
8318
8447
  const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
8319
8448
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
8320
- import_react20.default.useEffect(() => {
8449
+ useEscapeKey(isOpen, () => {
8450
+ setIsOpen(false);
8451
+ triggerRef.current?.focus({ preventScroll: true });
8452
+ });
8453
+ import_react21.default.useEffect(() => {
8321
8454
  if (isOpen) {
8322
8455
  setMounted(true);
8323
8456
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -8371,7 +8504,7 @@ Dropdown.displayName = "Dropdown";
8371
8504
  var Dropdown_default = Dropdown;
8372
8505
 
8373
8506
  // src/components/Editor/Editor.tsx
8374
- var import_react21 = __toESM(require("react"), 1);
8507
+ var import_react22 = __toESM(require("react"), 1);
8375
8508
  var import_jsx_runtime323 = require("react/jsx-runtime");
8376
8509
  var DEFAULT_TOOLBAR = [
8377
8510
  "bold",
@@ -8421,6 +8554,15 @@ var ALLOWED_ATTRS = {
8421
8554
  a: ["href", "target", "rel"],
8422
8555
  img: ["src", "alt"]
8423
8556
  };
8557
+ var DROP_WITH_CONTENT = /* @__PURE__ */ new Set([
8558
+ "script",
8559
+ "style",
8560
+ "noscript",
8561
+ "iframe",
8562
+ "object",
8563
+ "embed",
8564
+ "template"
8565
+ ]);
8424
8566
  var sanitizeHtml = (input) => {
8425
8567
  const doc = new DOMParser().parseFromString(`<div>${input}</div>`, "text/html");
8426
8568
  const root = doc.body.firstElementChild;
@@ -8429,6 +8571,10 @@ var sanitizeHtml = (input) => {
8429
8571
  const children = Array.from(node.children);
8430
8572
  for (const child of children) {
8431
8573
  const tag = child.tagName.toLowerCase();
8574
+ if (DROP_WITH_CONTENT.has(tag)) {
8575
+ node.removeChild(child);
8576
+ continue;
8577
+ }
8432
8578
  if (!ALLOWED_TAGS.has(tag)) {
8433
8579
  while (child.firstChild) node.insertBefore(child.firstChild, child);
8434
8580
  node.removeChild(child);
@@ -8479,26 +8625,30 @@ var Editor = (props) => {
8479
8625
  onImageUpload,
8480
8626
  minHeight = 200
8481
8627
  } = props;
8482
- const editorRef = import_react21.default.useRef(null);
8483
- const lastRangeRef = import_react21.default.useRef(null);
8484
- const composingRef = import_react21.default.useRef(false);
8485
- const [isFocused, setIsFocused] = import_react21.default.useState(false);
8486
- const [isEmpty, setIsEmpty] = import_react21.default.useState(!value);
8487
- const [activeFormats, setActiveFormats] = import_react21.default.useState(/* @__PURE__ */ new Set());
8488
- const [slashOpen, setSlashOpen] = import_react21.default.useState(false);
8489
- const [slashFilter, setSlashFilter] = import_react21.default.useState("");
8490
- const [slashIdx, setSlashIdx] = import_react21.default.useState(0);
8491
- const [slashPos, setSlashPos] = import_react21.default.useState({ top: 0, left: 0 });
8492
- const slashStartRangeRef = import_react21.default.useRef(null);
8493
- const [linkOpen, setLinkOpen] = import_react21.default.useState(false);
8494
- const [linkValue, setLinkValue] = import_react21.default.useState("");
8495
- const [linkPos, setLinkPos] = import_react21.default.useState({ top: 0, left: 0 });
8496
- import_react21.default.useEffect(() => {
8497
- if (!editorRef.current) return;
8498
- if (editorRef.current.innerHTML !== value) {
8499
- editorRef.current.innerHTML = sanitizeHtml(value || "");
8500
- updateEmpty();
8501
- }
8628
+ const editorRef = import_react22.default.useRef(null);
8629
+ const lastRangeRef = import_react22.default.useRef(null);
8630
+ const composingRef = import_react22.default.useRef(false);
8631
+ const [isFocused, setIsFocused] = import_react22.default.useState(false);
8632
+ const [isEmpty, setIsEmpty] = import_react22.default.useState(!value);
8633
+ const [activeFormats, setActiveFormats] = import_react22.default.useState(/* @__PURE__ */ new Set());
8634
+ const [slashOpen, setSlashOpen] = import_react22.default.useState(false);
8635
+ const [slashFilter, setSlashFilter] = import_react22.default.useState("");
8636
+ const [slashIdx, setSlashIdx] = import_react22.default.useState(0);
8637
+ const [slashPos, setSlashPos] = import_react22.default.useState({ top: 0, left: 0 });
8638
+ const slashStartRangeRef = import_react22.default.useRef(null);
8639
+ const [linkOpen, setLinkOpen] = import_react22.default.useState(false);
8640
+ const [linkValue, setLinkValue] = import_react22.default.useState("");
8641
+ const [linkPos, setLinkPos] = import_react22.default.useState({ top: 0, left: 0 });
8642
+ const lastEmittedRef = import_react22.default.useRef(null);
8643
+ import_react22.default.useEffect(() => {
8644
+ const el = editorRef.current;
8645
+ if (!el) return;
8646
+ if (value === lastEmittedRef.current) return;
8647
+ if (el.innerHTML === value) return;
8648
+ el.innerHTML = sanitizeHtml(value || "");
8649
+ if (!el.firstChild) el.innerHTML = "<p><br></p>";
8650
+ lastEmittedRef.current = null;
8651
+ updateEmpty();
8502
8652
  }, [value]);
8503
8653
  const updateEmpty = () => {
8504
8654
  const el = editorRef.current;
@@ -8514,10 +8664,19 @@ var Editor = (props) => {
8514
8664
  }
8515
8665
  };
8516
8666
  const restoreSelection = () => {
8517
- if (!lastRangeRef.current) return;
8667
+ const range = lastRangeRef.current;
8668
+ if (!range) return;
8669
+ if (!editorRef.current?.contains(range.startContainer)) {
8670
+ lastRangeRef.current = null;
8671
+ return;
8672
+ }
8518
8673
  const sel = window.getSelection();
8519
- sel?.removeAllRanges();
8520
- sel?.addRange(lastRangeRef.current);
8674
+ try {
8675
+ sel?.removeAllRanges();
8676
+ sel?.addRange(range);
8677
+ } catch {
8678
+ lastRangeRef.current = null;
8679
+ }
8521
8680
  };
8522
8681
  const updateActiveFormats = () => {
8523
8682
  if (!editorRef.current) return;
@@ -8546,6 +8705,96 @@ var Editor = (props) => {
8546
8705
  const setBlock = (tag) => {
8547
8706
  exec("formatBlock", tag);
8548
8707
  };
8708
+ const closestPre = () => {
8709
+ const sel = window.getSelection();
8710
+ const node = sel?.anchorNode;
8711
+ if (!node || !editorRef.current?.contains(node)) return null;
8712
+ const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
8713
+ return el?.closest("pre") ?? null;
8714
+ };
8715
+ const insertCodeBlock = () => {
8716
+ const el = editorRef.current;
8717
+ const sel = window.getSelection();
8718
+ if (!el || !sel || sel.rangeCount === 0) return;
8719
+ const existing = closestPre();
8720
+ if (existing) {
8721
+ const p = document.createElement("p");
8722
+ p.textContent = existing.textContent || "";
8723
+ if (!p.textContent) p.innerHTML = "<br>";
8724
+ existing.replaceWith(p);
8725
+ placeCaretAtEnd(p);
8726
+ handleInput();
8727
+ return;
8728
+ }
8729
+ const range = sel.getRangeAt(0);
8730
+ const frag = range.cloneContents();
8731
+ const holder = document.createElement("div");
8732
+ holder.appendChild(frag);
8733
+ const BLOCK = /^(p|div|h[1-6]|li|blockquote|pre|tr)$/i;
8734
+ const linesOf = (node) => {
8735
+ const out = [];
8736
+ let cur = "";
8737
+ for (const child of Array.from(node.childNodes)) {
8738
+ if (child.nodeType === Node.TEXT_NODE) {
8739
+ cur += child.textContent || "";
8740
+ } else if (child.nodeName === "BR") {
8741
+ out.push(cur);
8742
+ cur = "";
8743
+ } else if (BLOCK.test(child.nodeName)) {
8744
+ if (cur) {
8745
+ out.push(cur);
8746
+ cur = "";
8747
+ }
8748
+ const sub = linesOf(child);
8749
+ out.push(...sub.length > 0 ? sub : [""]);
8750
+ } else {
8751
+ cur += linesOf(child).join("\n");
8752
+ }
8753
+ }
8754
+ if (cur) out.push(cur);
8755
+ return out;
8756
+ };
8757
+ const text = linesOf(holder).join("\n").replace(/\n+$/, "");
8758
+ const pre = document.createElement("pre");
8759
+ const code = document.createElement("code");
8760
+ code.textContent = text || "";
8761
+ pre.appendChild(code);
8762
+ range.deleteContents();
8763
+ range.insertNode(pre);
8764
+ ensureParagraphAfter(pre);
8765
+ placeCaretAtEnd(code);
8766
+ handleInput();
8767
+ };
8768
+ const insertTextAtCaret = (text) => {
8769
+ const sel = window.getSelection();
8770
+ if (!sel || sel.rangeCount === 0) return;
8771
+ const range = sel.getRangeAt(0);
8772
+ range.deleteContents();
8773
+ const node = document.createTextNode(text);
8774
+ range.insertNode(node);
8775
+ range.setStartAfter(node);
8776
+ range.collapse(true);
8777
+ sel.removeAllRanges();
8778
+ sel.addRange(range);
8779
+ handleInput();
8780
+ };
8781
+ const ensureParagraphAfter = (node) => {
8782
+ const next = node.nextElementSibling;
8783
+ if (next && next.tagName === "P") return;
8784
+ const p = document.createElement("p");
8785
+ p.innerHTML = "<br>";
8786
+ node.after(p);
8787
+ };
8788
+ const placeCaretAtEnd = (node) => {
8789
+ const sel = window.getSelection();
8790
+ if (!sel) return;
8791
+ const r2 = document.createRange();
8792
+ r2.selectNodeContents(node);
8793
+ r2.collapse(false);
8794
+ sel.removeAllRanges();
8795
+ sel.addRange(r2);
8796
+ editorRef.current?.focus();
8797
+ };
8549
8798
  const insertDivider = () => {
8550
8799
  exec("insertHorizontalRule");
8551
8800
  const el = editorRef.current;
@@ -8592,7 +8841,9 @@ var Editor = (props) => {
8592
8841
  const range = sel.getRangeAt(0);
8593
8842
  slashStartRangeRef.current = range.cloneRange();
8594
8843
  const rect = range.getBoundingClientRect();
8595
- const editorRect = editorRef.current.getBoundingClientRect();
8844
+ const editorEl = editorRef.current;
8845
+ if (!editorEl) return;
8846
+ const editorRect = editorEl.getBoundingClientRect();
8596
8847
  setSlashPos({
8597
8848
  top: rect.bottom - editorRect.top + 4,
8598
8849
  left: rect.left - editorRect.left
@@ -8607,7 +8858,7 @@ var Editor = (props) => {
8607
8858
  setSlashIdx(0);
8608
8859
  slashStartRangeRef.current = null;
8609
8860
  };
8610
- const filteredSlashItems = import_react21.default.useMemo(() => {
8861
+ const filteredSlashItems = import_react22.default.useMemo(() => {
8611
8862
  if (!slashFilter) return SLASH_ITEMS;
8612
8863
  const f = slashFilter.toLowerCase();
8613
8864
  return SLASH_ITEMS.filter((it) => it.label.toLowerCase().includes(f) || it.key.includes(f));
@@ -8650,7 +8901,7 @@ var Editor = (props) => {
8650
8901
  setBlock("blockquote");
8651
8902
  break;
8652
8903
  case "code-block":
8653
- setBlock("pre");
8904
+ insertCodeBlock();
8654
8905
  break;
8655
8906
  case "divider":
8656
8907
  insertDivider();
@@ -8668,7 +8919,9 @@ var Editor = (props) => {
8668
8919
  if (!sel || sel.rangeCount === 0) return;
8669
8920
  const range = sel.getRangeAt(0);
8670
8921
  const rect = range.getBoundingClientRect();
8671
- const editorRect = editorRef.current.getBoundingClientRect();
8922
+ const editorEl2 = editorRef.current;
8923
+ if (!editorEl2) return;
8924
+ const editorRect = editorEl2.getBoundingClientRect();
8672
8925
  setLinkPos({
8673
8926
  top: rect.bottom - editorRect.top + 4,
8674
8927
  left: rect.left - editorRect.left
@@ -8701,13 +8954,13 @@ var Editor = (props) => {
8701
8954
  if (node.nodeType !== Node.TEXT_NODE) return false;
8702
8955
  const text = (node.textContent || "").slice(0, range.startOffset);
8703
8956
  const patterns = [
8704
- [/^###\s$/, () => setBlock("h3")],
8705
- [/^##\s$/, () => setBlock("h2")],
8706
- [/^#\s$/, () => setBlock("h1")],
8707
- [/^-\s$/, () => exec("insertUnorderedList")],
8708
- [/^\*\s$/, () => exec("insertUnorderedList")],
8709
- [/^1\.\s$/, () => exec("insertOrderedList")],
8710
- [/^>\s$/, () => setBlock("blockquote")]
8957
+ [/^###$/, () => setBlock("h3")],
8958
+ [/^##$/, () => setBlock("h2")],
8959
+ [/^#$/, () => setBlock("h1")],
8960
+ [/^-$/, () => exec("insertUnorderedList")],
8961
+ [/^\*$/, () => exec("insertUnorderedList")],
8962
+ [/^1\.$/, () => exec("insertOrderedList")],
8963
+ [/^>$/, () => setBlock("blockquote")]
8711
8964
  ];
8712
8965
  for (const [re, fn] of patterns) {
8713
8966
  if (re.test(text)) {
@@ -8727,7 +8980,9 @@ var Editor = (props) => {
8727
8980
  if (composingRef.current) return;
8728
8981
  const el = editorRef.current;
8729
8982
  if (!el) return;
8730
- onChange?.(el.innerHTML);
8983
+ const html = el.innerHTML;
8984
+ lastEmittedRef.current = html;
8985
+ onChange?.(html);
8731
8986
  updateEmpty();
8732
8987
  updateActiveFormats();
8733
8988
  if (slashOpen) {
@@ -8755,6 +9010,31 @@ var Editor = (props) => {
8755
9010
  };
8756
9011
  const handleKeyDown = (e) => {
8757
9012
  if (readOnly) return;
9013
+ if (composingRef.current || e.nativeEvent.isComposing || e.keyCode === 229) return;
9014
+ const pre = closestPre();
9015
+ if (pre && !slashOpen) {
9016
+ if (e.key === "Enter" && !e.shiftKey) {
9017
+ const text = pre.textContent || "";
9018
+ if (text.endsWith("\n\n")) {
9019
+ e.preventDefault();
9020
+ const code = pre.querySelector("code") ?? pre;
9021
+ code.textContent = text.replace(/\n\n$/, "");
9022
+ ensureParagraphAfter(pre);
9023
+ const next = pre.nextElementSibling;
9024
+ if (next) placeCaretAtEnd(next);
9025
+ handleInput();
9026
+ return;
9027
+ }
9028
+ e.preventDefault();
9029
+ insertTextAtCaret("\n");
9030
+ return;
9031
+ }
9032
+ if (e.key === "Tab") {
9033
+ e.preventDefault();
9034
+ insertTextAtCaret(" ");
9035
+ return;
9036
+ }
9037
+ }
8758
9038
  if (slashOpen) {
8759
9039
  if (e.key === "ArrowDown") {
8760
9040
  e.preventDefault();
@@ -8801,6 +9081,7 @@ var Editor = (props) => {
8801
9081
  return;
8802
9082
  }
8803
9083
  }
9084
+ if (pre) return;
8804
9085
  if (enableSlashCommand && e.key === "/") {
8805
9086
  setTimeout(openSlashMenu, 0);
8806
9087
  }
@@ -8813,8 +9094,12 @@ var Editor = (props) => {
8813
9094
  const handlePaste = (e) => {
8814
9095
  if (readOnly) return;
8815
9096
  e.preventDefault();
8816
- const html = e.clipboardData.getData("text/html");
8817
9097
  const text = e.clipboardData.getData("text/plain");
9098
+ if (closestPre()) {
9099
+ insertTextAtCaret(text);
9100
+ return;
9101
+ }
9102
+ const html = e.clipboardData.getData("text/html");
8818
9103
  const clean = html ? sanitizeHtml(html) : escapeHtml(text);
8819
9104
  document.execCommand("insertHTML", false, clean);
8820
9105
  handleInput();
@@ -8838,6 +9123,7 @@ var Editor = (props) => {
8838
9123
  updateActiveFormats();
8839
9124
  };
8840
9125
  const onToolbarAction = (item) => {
9126
+ if (closestPre() && item !== "code-block") return;
8841
9127
  switch (item) {
8842
9128
  case "bold":
8843
9129
  exec("bold");
@@ -8879,7 +9165,7 @@ var Editor = (props) => {
8879
9165
  setBlock("blockquote");
8880
9166
  break;
8881
9167
  case "code-block":
8882
- setBlock("pre");
9168
+ insertCodeBlock();
8883
9169
  break;
8884
9170
  case "link":
8885
9171
  openLinkEditor();
@@ -8909,6 +9195,10 @@ var Editor = (props) => {
8909
9195
  ref: editorRef,
8910
9196
  contentEditable: !readOnly,
8911
9197
  suppressContentEditableWarning: true,
9198
+ role: "textbox",
9199
+ "aria-multiline": "true",
9200
+ "aria-readonly": readOnly || void 0,
9201
+ "aria-label": placeholder,
8912
9202
  className: "lib-xplat-editor__editable",
8913
9203
  onInput: handleInput,
8914
9204
  onKeyDown: handleKeyDown,
@@ -9000,7 +9290,7 @@ var EditorToolbar = ({ items, active, onAction }) => {
9000
9290
  )) });
9001
9291
  };
9002
9292
  var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
9003
- import_react21.default.useEffect(() => {
9293
+ import_react22.default.useEffect(() => {
9004
9294
  const handleClickOutside = (e) => {
9005
9295
  const target = e.target;
9006
9296
  const menu = document.querySelector(".lib-xplat-editor__slash-menu");
@@ -9034,8 +9324,8 @@ var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
9034
9324
  );
9035
9325
  };
9036
9326
  var LinkPopover = ({ position, value, onChange, onConfirm, onClose }) => {
9037
- const inputRef = import_react21.default.useRef(null);
9038
- import_react21.default.useEffect(() => {
9327
+ const inputRef = import_react22.default.useRef(null);
9328
+ import_react22.default.useEffect(() => {
9039
9329
  inputRef.current?.focus();
9040
9330
  }, []);
9041
9331
  return /* @__PURE__ */ (0, import_jsx_runtime323.jsxs)(
@@ -9093,7 +9383,7 @@ EmptyState.displayName = "EmptyState";
9093
9383
  var EmptyState_default = EmptyState;
9094
9384
 
9095
9385
  // src/components/FileUpload/FileUpload.tsx
9096
- var import_react22 = __toESM(require("react"), 1);
9386
+ var import_react23 = __toESM(require("react"), 1);
9097
9387
  var import_jsx_runtime325 = require("react/jsx-runtime");
9098
9388
  var FileUpload = (props) => {
9099
9389
  const {
@@ -9105,8 +9395,8 @@ var FileUpload = (props) => {
9105
9395
  description,
9106
9396
  validations
9107
9397
  } = props;
9108
- const [isDragOver, setIsDragOver] = import_react22.default.useState(false);
9109
- const inputRef = import_react22.default.useRef(null);
9398
+ const [isDragOver, setIsDragOver] = import_react23.default.useState(false);
9399
+ const inputRef = import_react23.default.useRef(null);
9110
9400
  const handleFiles = (fileList) => {
9111
9401
  let files = Array.from(fileList);
9112
9402
  if (maxSize) {
@@ -9168,10 +9458,10 @@ FileUpload.displayName = "FileUpload";
9168
9458
  var FileUpload_default = FileUpload;
9169
9459
 
9170
9460
  // src/components/HtmlTypeWriter/HtmlTypeWriter.tsx
9171
- var import_react24 = __toESM(require("react"), 1);
9461
+ var import_react25 = __toESM(require("react"), 1);
9172
9462
 
9173
9463
  // src/components/HtmlTypeWriter/utils.ts
9174
- var import_react23 = __toESM(require("react"), 1);
9464
+ var import_react24 = __toESM(require("react"), 1);
9175
9465
  var voidTags = /* @__PURE__ */ new Set([
9176
9466
  "br",
9177
9467
  "img",
@@ -9239,15 +9529,15 @@ var convertNodeToReactWithRange = (node, typedLen, rangeMap) => {
9239
9529
  props[attr.name] = attr.value;
9240
9530
  });
9241
9531
  if (voidTags.has(tag)) {
9242
- return import_react23.default.createElement(tag, props);
9532
+ return import_react24.default.createElement(tag, props);
9243
9533
  }
9244
9534
  const children = Array.from(element.childNodes).map((child) => convertNodeToReactWithRange(child, typedLen, rangeMap)).filter((n) => n != null);
9245
- return import_react23.default.createElement(tag, props, ...children);
9535
+ return import_react24.default.createElement(tag, props, ...children);
9246
9536
  };
9247
9537
  var htmlToReactProgressive = (root, typedLen, rangeMap) => {
9248
9538
  const nodes = Array.from(root.childNodes).map((child, idx) => {
9249
9539
  const node = convertNodeToReactWithRange(child, typedLen, rangeMap);
9250
- return node == null ? null : import_react23.default.createElement(import_react23.default.Fragment, { key: idx }, node);
9540
+ return node == null ? null : import_react24.default.createElement(import_react24.default.Fragment, { key: idx }, node);
9251
9541
  }).filter(Boolean);
9252
9542
  return nodes.length === 0 ? null : nodes;
9253
9543
  };
@@ -9260,20 +9550,20 @@ var HtmlTypeWriter = ({
9260
9550
  onDone,
9261
9551
  onChange
9262
9552
  }) => {
9263
- const [typedLen, setTypedLen] = import_react24.default.useState(0);
9264
- const doneCalledRef = import_react24.default.useRef(false);
9265
- const { doc, rangeMap, totalLength } = import_react24.default.useMemo(() => {
9553
+ const [typedLen, setTypedLen] = import_react25.default.useState(0);
9554
+ const doneCalledRef = import_react25.default.useRef(false);
9555
+ const { doc, rangeMap, totalLength } = import_react25.default.useMemo(() => {
9266
9556
  if (typeof window === "undefined") return { doc: null, rangeMap: /* @__PURE__ */ new Map(), totalLength: 0 };
9267
9557
  const decoded = decodeHtmlEntities(html);
9268
9558
  const doc2 = new DOMParser().parseFromString(decoded, "text/html");
9269
9559
  const { rangeMap: rangeMap2, totalLength: totalLength2 } = buildRangeMap(doc2.body);
9270
9560
  return { doc: doc2, rangeMap: rangeMap2, totalLength: totalLength2 };
9271
9561
  }, [html]);
9272
- import_react24.default.useEffect(() => {
9562
+ import_react25.default.useEffect(() => {
9273
9563
  setTypedLen(0);
9274
9564
  doneCalledRef.current = false;
9275
9565
  }, [html]);
9276
- import_react24.default.useEffect(() => {
9566
+ import_react25.default.useEffect(() => {
9277
9567
  if (!totalLength) return;
9278
9568
  if (typedLen >= totalLength) return;
9279
9569
  const timer = window.setInterval(() => {
@@ -9281,18 +9571,18 @@ var HtmlTypeWriter = ({
9281
9571
  }, duration);
9282
9572
  return () => window.clearInterval(timer);
9283
9573
  }, [typedLen, totalLength, duration]);
9284
- import_react24.default.useEffect(() => {
9574
+ import_react25.default.useEffect(() => {
9285
9575
  if (typedLen > 0 && typedLen < totalLength) {
9286
9576
  onChange?.();
9287
9577
  }
9288
9578
  }, [typedLen, totalLength, onChange]);
9289
- import_react24.default.useEffect(() => {
9579
+ import_react25.default.useEffect(() => {
9290
9580
  if (typedLen === totalLength && totalLength > 0 && !doneCalledRef.current) {
9291
9581
  doneCalledRef.current = true;
9292
9582
  onDone?.();
9293
9583
  }
9294
9584
  }, [typedLen, totalLength, onDone]);
9295
- const parsed = import_react24.default.useMemo(
9585
+ const parsed = import_react25.default.useMemo(
9296
9586
  () => doc ? htmlToReactProgressive(doc.body, typedLen, rangeMap) : null,
9297
9587
  [doc, typedLen, rangeMap]
9298
9588
  );
@@ -9302,12 +9592,12 @@ HtmlTypeWriter.displayName = "HtmlTypeWriter";
9302
9592
  var HtmlTypeWriter_default = HtmlTypeWriter;
9303
9593
 
9304
9594
  // src/components/ImageSelector/ImageSelector.tsx
9305
- var import_react25 = __toESM(require("react"), 1);
9595
+ var import_react26 = __toESM(require("react"), 1);
9306
9596
  var import_jsx_runtime327 = require("react/jsx-runtime");
9307
9597
  var ImageSelector = (props) => {
9308
9598
  const { value, label, onChange, validations } = props;
9309
- const [previewUrl, setPreviewUrl] = import_react25.default.useState();
9310
- import_react25.default.useEffect(() => {
9599
+ const [previewUrl, setPreviewUrl] = import_react26.default.useState();
9600
+ import_react26.default.useEffect(() => {
9311
9601
  if (!value) {
9312
9602
  setPreviewUrl(void 0);
9313
9603
  return;
@@ -9316,7 +9606,7 @@ var ImageSelector = (props) => {
9316
9606
  setPreviewUrl(url);
9317
9607
  return () => URL.revokeObjectURL(url);
9318
9608
  }, [value]);
9319
- const inputRef = import_react25.default.useRef(null);
9609
+ const inputRef = import_react26.default.useRef(null);
9320
9610
  const handleFileChange = (e) => {
9321
9611
  const selectedFile = e.target.files?.[0];
9322
9612
  if (selectedFile) {
@@ -9499,17 +9789,21 @@ Pagination.displayName = "Pagination";
9499
9789
  var Pagination_default = Pagination;
9500
9790
 
9501
9791
  // src/components/PopOver/PopOver.tsx
9502
- var import_react26 = __toESM(require("react"), 1);
9792
+ var import_react27 = __toESM(require("react"), 1);
9503
9793
  var import_jsx_runtime332 = require("react/jsx-runtime");
9504
9794
  var PopOver = (props) => {
9505
9795
  const { children, isOpen, onClose, PopOverEl } = props;
9506
- const popRef = import_react26.default.useRef(null);
9507
- const triggerRef = import_react26.default.useRef(null);
9508
- const [localOpen, setLocalOpen] = import_react26.default.useState(false);
9509
- const [eventTrigger, setEventTrigger] = import_react26.default.useState(false);
9796
+ const popRef = import_react27.default.useRef(null);
9797
+ const triggerRef = import_react27.default.useRef(null);
9798
+ const [localOpen, setLocalOpen] = import_react27.default.useState(false);
9799
+ const [eventTrigger, setEventTrigger] = import_react27.default.useState(false);
9510
9800
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
9801
+ useEscapeKey(isOpen, () => {
9802
+ onClose();
9803
+ triggerRef.current?.focus({ preventScroll: true });
9804
+ });
9511
9805
  const position = useAutoPosition_default(triggerRef, popRef, localOpen);
9512
- import_react26.default.useEffect(() => {
9806
+ import_react27.default.useEffect(() => {
9513
9807
  if (isOpen) {
9514
9808
  setLocalOpen(isOpen);
9515
9809
  setTimeout(() => {
@@ -9594,12 +9888,12 @@ Progress.displayName = "Progress";
9594
9888
  var Progress_default = Progress;
9595
9889
 
9596
9890
  // src/components/Radio/RadioGroupContext.tsx
9597
- var import_react27 = __toESM(require("react"), 1);
9598
- var RadioGroupContext = import_react27.default.createContext(
9891
+ var import_react28 = __toESM(require("react"), 1);
9892
+ var RadioGroupContext = import_react28.default.createContext(
9599
9893
  null
9600
9894
  );
9601
9895
  var useRadioGroupContext = () => {
9602
- return import_react27.default.useContext(RadioGroupContext);
9896
+ return import_react28.default.useContext(RadioGroupContext);
9603
9897
  };
9604
9898
  var RadioGroupContext_default = RadioGroupContext;
9605
9899
 
@@ -9675,19 +9969,19 @@ RadioGroup.displayName = "RadioGroup";
9675
9969
  var RadioGroup_default = RadioGroup;
9676
9970
 
9677
9971
  // src/components/Select/Select.tsx
9678
- var import_react30 = __toESM(require("react"), 1);
9972
+ var import_react31 = __toESM(require("react"), 1);
9679
9973
 
9680
9974
  // src/components/Select/context.ts
9681
- var import_react28 = __toESM(require("react"), 1);
9682
- var SelectContext = import_react28.default.createContext(null);
9975
+ var import_react29 = __toESM(require("react"), 1);
9976
+ var SelectContext = import_react29.default.createContext(null);
9683
9977
  var context_default = SelectContext;
9684
9978
 
9685
9979
  // src/components/Select/SelectItem.tsx
9686
- var import_react29 = __toESM(require("react"), 1);
9980
+ var import_react30 = __toESM(require("react"), 1);
9687
9981
  var import_jsx_runtime336 = require("react/jsx-runtime");
9688
9982
  var SelectItem = (props) => {
9689
9983
  const { children, value, onClick, disabled = false } = props;
9690
- const ctx = import_react29.default.useContext(context_default);
9984
+ const ctx = import_react30.default.useContext(context_default);
9691
9985
  const handleClick = (e) => {
9692
9986
  e.preventDefault();
9693
9987
  e.stopPropagation();
@@ -9727,32 +10021,37 @@ var SelectRoot = (props) => {
9727
10021
  onChange,
9728
10022
  children,
9729
10023
  disabled = false,
10024
+ searchable = false,
10025
+ searchPlaceholder = "\uAC80\uC0C9",
9730
10026
  error = false,
9731
10027
  validations,
10028
+ label,
10029
+ required,
9732
10030
  size = "md"
9733
10031
  } = props;
9734
- const itemChildren = import_react30.default.Children.toArray(children).filter(
9735
- (child) => import_react30.default.isValidElement(child) && child.type === SelectItem_default
10032
+ const fieldId = import_react31.default.useId();
10033
+ const itemChildren = import_react31.default.Children.toArray(children).filter(
10034
+ (child) => import_react31.default.isValidElement(child) && child.type === SelectItem_default
9736
10035
  );
9737
10036
  const isControlled = valueProp !== void 0;
9738
- const [isOpen, setOpen] = import_react30.default.useState(false);
9739
- const [uncontrolledLabel, setUncontrolledLabel] = import_react30.default.useState(null);
9740
- const [uncontrolledValue, setUncontrolledValue] = import_react30.default.useState(void 0);
9741
- const controlledLabel = import_react30.default.useMemo(() => {
10037
+ const [isOpen, setOpen] = import_react31.default.useState(false);
10038
+ const [uncontrolledLabel, setUncontrolledLabel] = import_react31.default.useState(null);
10039
+ const [uncontrolledValue, setUncontrolledValue] = import_react31.default.useState(void 0);
10040
+ const controlledLabel = import_react31.default.useMemo(() => {
9742
10041
  if (!isControlled) return null;
9743
10042
  const match = itemChildren.find((child) => child.props.value === valueProp);
9744
10043
  return match ? match.props.children : null;
9745
10044
  }, [isControlled, valueProp, itemChildren]);
9746
10045
  const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
9747
10046
  const selectedValue = isControlled ? valueProp : uncontrolledValue;
9748
- const triggerRef = import_react30.default.useRef(null);
9749
- const contentRef = import_react30.default.useRef(null);
9750
- const [mounted, setMounted] = import_react30.default.useState(false);
9751
- const [visible, setVisible] = import_react30.default.useState(false);
9752
- import_react30.default.useEffect(() => {
10047
+ const triggerRef = import_react31.default.useRef(null);
10048
+ const contentRef = import_react31.default.useRef(null);
10049
+ const [mounted, setMounted] = import_react31.default.useState(false);
10050
+ const [visible, setVisible] = import_react31.default.useState(false);
10051
+ import_react31.default.useEffect(() => {
9753
10052
  if (disabled && isOpen) setOpen(false);
9754
10053
  }, [disabled, isOpen]);
9755
- import_react30.default.useEffect(() => {
10054
+ import_react31.default.useEffect(() => {
9756
10055
  if (isOpen) {
9757
10056
  setMounted(true);
9758
10057
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -9762,22 +10061,42 @@ var SelectRoot = (props) => {
9762
10061
  const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS3);
9763
10062
  return () => clearTimeout(t);
9764
10063
  }, [isOpen]);
9765
- const open = import_react30.default.useCallback(() => setOpen(true), []);
9766
- const close = import_react30.default.useCallback(() => setOpen(false), []);
9767
- const toggle = import_react30.default.useCallback(() => setOpen((prev) => !prev), []);
10064
+ const [query, setQuery] = import_react31.default.useState("");
10065
+ const textOf = (node) => {
10066
+ if (node === null || node === void 0 || typeof node === "boolean") return "";
10067
+ if (typeof node === "string" || typeof node === "number") return String(node);
10068
+ if (Array.isArray(node)) return node.map(textOf).join("");
10069
+ if (import_react31.default.isValidElement(node)) return textOf(node.props.children);
10070
+ return "";
10071
+ };
10072
+ const visibleItems = import_react31.default.useMemo(() => {
10073
+ if (!searchable || !query.trim()) return itemChildren;
10074
+ const q = query.trim().toLowerCase();
10075
+ return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
10076
+ }, [searchable, query, itemChildren]);
10077
+ const open = import_react31.default.useCallback(() => setOpen(true), []);
10078
+ const close = import_react31.default.useCallback(() => {
10079
+ setOpen(false);
10080
+ setQuery("");
10081
+ }, []);
10082
+ const toggle = import_react31.default.useCallback(() => setOpen((prev) => !prev), []);
9768
10083
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
10084
+ useEscapeKey(isOpen, () => {
10085
+ close();
10086
+ triggerRef.current?.focus({ preventScroll: true });
10087
+ });
9769
10088
  const position = useAutoPosition_default(triggerRef, contentRef, mounted);
9770
- const setSelected = import_react30.default.useCallback(
9771
- (label, itemValue) => {
10089
+ const setSelected = import_react31.default.useCallback(
10090
+ (label2, itemValue) => {
9772
10091
  if (!isControlled) {
9773
- setUncontrolledLabel(label);
10092
+ setUncontrolledLabel(label2);
9774
10093
  setUncontrolledValue(itemValue);
9775
10094
  }
9776
- onChange?.(itemValue, label);
10095
+ onChange?.(itemValue, label2);
9777
10096
  },
9778
10097
  [isControlled, onChange]
9779
10098
  );
9780
- const ctxValue = import_react30.default.useMemo(
10099
+ const ctxValue = import_react31.default.useMemo(
9781
10100
  () => ({
9782
10101
  isOpen,
9783
10102
  mounted,
@@ -9813,6 +10132,7 @@ var SelectRoot = (props) => {
9813
10132
  /* @__PURE__ */ (0, import_jsx_runtime337.jsxs)(
9814
10133
  "div",
9815
10134
  {
10135
+ id: fieldId,
9816
10136
  ref: triggerRef,
9817
10137
  className: clsx_default(
9818
10138
  "select-trigger",
@@ -9855,20 +10175,33 @@ var SelectRoot = (props) => {
9855
10175
  ]
9856
10176
  }
9857
10177
  ),
9858
- mounted && /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(
10178
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime337.jsxs)(
9859
10179
  "div",
9860
10180
  {
9861
10181
  className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
9862
10182
  ref: contentRef,
9863
10183
  style: { ...position.position, width: triggerRef.current?.offsetWidth },
9864
10184
  role: "listbox",
9865
- children: /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(context_default.Provider, { value: ctxValue, children: itemChildren })
10185
+ children: [
10186
+ searchable && /* @__PURE__ */ (0, import_jsx_runtime337.jsx)("div", { className: "select-search", children: /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(
10187
+ "input",
10188
+ {
10189
+ type: "text",
10190
+ value: query,
10191
+ placeholder: searchPlaceholder,
10192
+ onChange: (e) => setQuery(e.target.value),
10193
+ autoFocus: true,
10194
+ "aria-label": searchPlaceholder
10195
+ }
10196
+ ) }),
10197
+ /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(context_default.Provider, { value: ctxValue, children: visibleItems.length > 0 ? visibleItems : /* @__PURE__ */ (0, import_jsx_runtime337.jsx)("div", { className: "select-empty", children: "\uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" }) })
10198
+ ]
9866
10199
  }
9867
10200
  ) })
9868
10201
  ]
9869
10202
  }
9870
10203
  ) });
9871
- return /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(Field, { validations, children: control });
10204
+ return /* @__PURE__ */ (0, import_jsx_runtime337.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
9872
10205
  };
9873
10206
  SelectRoot.displayName = "Select";
9874
10207
  var Select = Object.assign(SelectRoot, {
@@ -9948,8 +10281,44 @@ var Spinner = (props) => {
9948
10281
  Spinner.displayName = "Spinner";
9949
10282
  var Spinner_default = Spinner;
9950
10283
 
9951
- // src/components/Steps/Steps.tsx
10284
+ // src/components/Stat/Stat.tsx
9952
10285
  var import_jsx_runtime340 = require("react/jsx-runtime");
10286
+ var ARROW = {
10287
+ up: "\u25B2",
10288
+ down: "\u25BC",
10289
+ flat: "\u2014"
10290
+ };
10291
+ var Stat = (props) => {
10292
+ const {
10293
+ label,
10294
+ value,
10295
+ unit,
10296
+ description,
10297
+ trend,
10298
+ icon,
10299
+ size = "md",
10300
+ type = "primary"
10301
+ } = props;
10302
+ const statusType = normalizeStatus(type);
10303
+ return /* @__PURE__ */ (0, import_jsx_runtime340.jsxs)("div", { className: clsx_default("lib-xplat-stat", size, statusType), children: [
10304
+ /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("div", { className: "stat-label", children: label }),
10305
+ /* @__PURE__ */ (0, import_jsx_runtime340.jsxs)("div", { className: "stat-value-row", children: [
10306
+ icon && /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { className: "stat-icon", children: icon }),
10307
+ /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { className: "stat-value", children: value }),
10308
+ unit && /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { className: "stat-unit", children: unit }),
10309
+ trend && /* @__PURE__ */ (0, import_jsx_runtime340.jsxs)("span", { className: clsx_default("stat-trend", trend.direction), children: [
10310
+ /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { "aria-hidden": "true", children: ARROW[trend.direction] }),
10311
+ trend.value
10312
+ ] })
10313
+ ] }),
10314
+ description && /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("div", { className: "stat-description", children: description })
10315
+ ] });
10316
+ };
10317
+ Stat.displayName = "Stat";
10318
+ var Stat_default = Stat;
10319
+
10320
+ // src/components/Steps/Steps.tsx
10321
+ var import_jsx_runtime341 = require("react/jsx-runtime");
9953
10322
  var Steps = (props) => {
9954
10323
  const {
9955
10324
  items,
@@ -9957,13 +10326,13 @@ var Steps = (props) => {
9957
10326
  type = "primary"
9958
10327
  } = props;
9959
10328
  const statusType = normalizeStatus(type);
9960
- return /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
10329
+ return /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
9961
10330
  const status = index < current ? "completed" : index === current ? "active" : "pending";
9962
- return /* @__PURE__ */ (0, import_jsx_runtime340.jsxs)("div", { className: clsx_default("step-item", status), children: [
9963
- /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ (0, import_jsx_runtime340.jsx)(CheckIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { children: index + 1 }) }),
9964
- /* @__PURE__ */ (0, import_jsx_runtime340.jsxs)("div", { className: "step-content", children: [
9965
- /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { className: "step-title", children: item.title }),
9966
- item.description && /* @__PURE__ */ (0, import_jsx_runtime340.jsx)("span", { className: "step-description", children: item.description })
10331
+ return /* @__PURE__ */ (0, import_jsx_runtime341.jsxs)("div", { className: clsx_default("step-item", status), children: [
10332
+ /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(CheckIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("span", { children: index + 1 }) }),
10333
+ /* @__PURE__ */ (0, import_jsx_runtime341.jsxs)("div", { className: "step-content", children: [
10334
+ /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("span", { className: "step-title", children: item.title }),
10335
+ item.description && /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("span", { className: "step-description", children: item.description })
9967
10336
  ] })
9968
10337
  ] }, index);
9969
10338
  }) });
@@ -9972,8 +10341,8 @@ Steps.displayName = "Steps";
9972
10341
  var Steps_default = Steps;
9973
10342
 
9974
10343
  // src/components/Swiper/Swiper.tsx
9975
- var import_react31 = __toESM(require("react"), 1);
9976
- var import_jsx_runtime341 = require("react/jsx-runtime");
10344
+ var import_react32 = __toESM(require("react"), 1);
10345
+ var import_jsx_runtime342 = require("react/jsx-runtime");
9977
10346
  var Swiper = (props) => {
9978
10347
  const {
9979
10348
  auto = false,
@@ -9997,26 +10366,26 @@ var Swiper = (props) => {
9997
10366
  const maxIndex = Math.max(0, totalSlides - viewItemCount);
9998
10367
  const useLoop = loop && canSlide;
9999
10368
  const cloneCount = useLoop ? totalSlides : 0;
10000
- const extendedItems = import_react31.default.useMemo(() => {
10369
+ const extendedItems = import_react32.default.useMemo(() => {
10001
10370
  if (!useLoop) return items;
10002
10371
  return [...items, ...items, ...items];
10003
10372
  }, [items, useLoop]);
10004
10373
  const initialIdx = Math.max(0, Math.min(indexProp ?? 0, maxIndex));
10005
- const [innerIndex, setInnerIndex] = import_react31.default.useState(
10374
+ const [innerIndex, setInnerIndex] = import_react32.default.useState(
10006
10375
  useLoop ? cloneCount + initialIdx : initialIdx
10007
10376
  );
10008
- const [isDragging, setIsDragging] = import_react31.default.useState(false);
10009
- const [dragOffset, setDragOffset] = import_react31.default.useState(0);
10010
- const [animated, setAnimated] = import_react31.default.useState(false);
10011
- const [containerWidth, setContainerWidth] = import_react31.default.useState(0);
10012
- const containerRef = import_react31.default.useRef(null);
10013
- const startXRef = import_react31.default.useRef(0);
10014
- const startTimeRef = import_react31.default.useRef(0);
10015
- const autoplayTimerRef = import_react31.default.useRef(null);
10016
- const resumeTimeoutRef = import_react31.default.useRef(null);
10017
- const [paused, setPaused] = import_react31.default.useState(false);
10018
- const initializedRef = import_react31.default.useRef(false);
10019
- import_react31.default.useEffect(() => {
10377
+ const [isDragging, setIsDragging] = import_react32.default.useState(false);
10378
+ const [dragOffset, setDragOffset] = import_react32.default.useState(0);
10379
+ const [animated, setAnimated] = import_react32.default.useState(false);
10380
+ const [containerWidth, setContainerWidth] = import_react32.default.useState(0);
10381
+ const containerRef = import_react32.default.useRef(null);
10382
+ const startXRef = import_react32.default.useRef(0);
10383
+ const startTimeRef = import_react32.default.useRef(0);
10384
+ const autoplayTimerRef = import_react32.default.useRef(null);
10385
+ const resumeTimeoutRef = import_react32.default.useRef(null);
10386
+ const [paused, setPaused] = import_react32.default.useState(false);
10387
+ const initializedRef = import_react32.default.useRef(false);
10388
+ import_react32.default.useEffect(() => {
10020
10389
  const el = containerRef.current;
10021
10390
  if (!el) return;
10022
10391
  const ro = new ResizeObserver((entries) => {
@@ -10039,7 +10408,7 @@ var Swiper = (props) => {
10039
10408
  return ((inner - cloneCount) % totalSlides + totalSlides) % totalSlides;
10040
10409
  };
10041
10410
  const realIndex = getRealIndex(innerIndex);
10042
- const moveToInner = import_react31.default.useCallback(
10411
+ const moveToInner = import_react32.default.useCallback(
10043
10412
  (idx, withAnim = true) => {
10044
10413
  if (!useLoop) {
10045
10414
  setAnimated(withAnim);
@@ -10067,7 +10436,7 @@ var Swiper = (props) => {
10067
10436
  },
10068
10437
  [useLoop, cloneCount, totalSlides]
10069
10438
  );
10070
- const handleTransitionEnd = import_react31.default.useCallback(() => {
10439
+ const handleTransitionEnd = import_react32.default.useCallback(() => {
10071
10440
  if (!useLoop) return;
10072
10441
  const real = getRealIndex(innerIndex);
10073
10442
  const canonical = cloneCount + real;
@@ -10077,7 +10446,7 @@ var Swiper = (props) => {
10077
10446
  }
10078
10447
  onChange?.(Math.min(real, maxIndex));
10079
10448
  }, [useLoop, innerIndex, cloneCount, totalSlides, maxIndex, onChange]);
10080
- const slideTo = import_react31.default.useCallback(
10449
+ const slideTo = import_react32.default.useCallback(
10081
10450
  (logicalIndex) => {
10082
10451
  if (!canSlide) return;
10083
10452
  const clamped = useLoop ? logicalIndex : Math.max(0, Math.min(logicalIndex, maxIndex));
@@ -10087,7 +10456,7 @@ var Swiper = (props) => {
10087
10456
  },
10088
10457
  [canSlide, useLoop, cloneCount, maxIndex, onChange, moveToInner]
10089
10458
  );
10090
- const slideNext = import_react31.default.useCallback(() => {
10459
+ const slideNext = import_react32.default.useCallback(() => {
10091
10460
  if (!canSlide) return;
10092
10461
  const nextInner = innerIndex + slideBy;
10093
10462
  if (useLoop) {
@@ -10096,7 +10465,7 @@ var Swiper = (props) => {
10096
10465
  moveToInner(Math.min(nextInner, maxIndex), true);
10097
10466
  }
10098
10467
  }, [canSlide, useLoop, innerIndex, slideBy, maxIndex, moveToInner]);
10099
- const slidePrev = import_react31.default.useCallback(() => {
10468
+ const slidePrev = import_react32.default.useCallback(() => {
10100
10469
  if (!canSlide) return;
10101
10470
  const prevInner = innerIndex - slideBy;
10102
10471
  if (useLoop) {
@@ -10105,7 +10474,7 @@ var Swiper = (props) => {
10105
10474
  moveToInner(Math.max(prevInner, 0), true);
10106
10475
  }
10107
10476
  }, [canSlide, useLoop, innerIndex, slideBy, moveToInner]);
10108
- import_react31.default.useEffect(() => {
10477
+ import_react32.default.useEffect(() => {
10109
10478
  if (indexProp === void 0) return;
10110
10479
  const clamped = Math.max(0, Math.min(indexProp, maxIndex));
10111
10480
  const target = useLoop ? cloneCount + clamped : clamped;
@@ -10113,12 +10482,12 @@ var Swiper = (props) => {
10113
10482
  moveToInner(target, true);
10114
10483
  }
10115
10484
  }, [indexProp]);
10116
- import_react31.default.useImperativeHandle(swiperRef, () => ({
10485
+ import_react32.default.useImperativeHandle(swiperRef, () => ({
10117
10486
  slidePrev,
10118
10487
  slideNext,
10119
10488
  slideTo
10120
10489
  }));
10121
- import_react31.default.useEffect(() => {
10490
+ import_react32.default.useEffect(() => {
10122
10491
  if (!auto || !canSlide || paused) return;
10123
10492
  autoplayTimerRef.current = setInterval(slideNext, autoplayDelay);
10124
10493
  return () => {
@@ -10144,7 +10513,7 @@ var Swiper = (props) => {
10144
10513
  resumeTimeoutRef.current = null;
10145
10514
  }, pauseOnInteraction);
10146
10515
  };
10147
- import_react31.default.useEffect(() => {
10516
+ import_react32.default.useEffect(() => {
10148
10517
  return () => {
10149
10518
  if (resumeTimeoutRef.current) clearTimeout(resumeTimeoutRef.current);
10150
10519
  };
@@ -10162,7 +10531,7 @@ var Swiper = (props) => {
10162
10531
  startXRef.current = getClientX(e);
10163
10532
  startTimeRef.current = Date.now();
10164
10533
  };
10165
- import_react31.default.useEffect(() => {
10534
+ import_react32.default.useEffect(() => {
10166
10535
  if (!isDragging) return;
10167
10536
  const handleMove = (e) => {
10168
10537
  setDragOffset(getClientX(e) - startXRef.current);
@@ -10201,8 +10570,8 @@ var Swiper = (props) => {
10201
10570
  }, [isDragging, dragOffset, innerIndex, useLoop, maxIndex, slideStep, moveToInner]);
10202
10571
  const slideWidthPercent = 100 / viewItemCount;
10203
10572
  const gapAdjust = spaceBetween * (viewItemCount - 1) / viewItemCount;
10204
- const slideElements = import_react31.default.useMemo(
10205
- () => extendedItems.map((item, idx) => /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(
10573
+ const slideElements = import_react32.default.useMemo(
10574
+ () => extendedItems.map((item, idx) => /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
10206
10575
  "div",
10207
10576
  {
10208
10577
  className: "lib-xplat-swiper__slide",
@@ -10221,15 +10590,15 @@ var Swiper = (props) => {
10221
10590
  Math.floor(realIndex / slideBy),
10222
10591
  totalSteps - 1
10223
10592
  );
10224
- return /* @__PURE__ */ (0, import_jsx_runtime341.jsxs)("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
10225
- /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(
10593
+ return /* @__PURE__ */ (0, import_jsx_runtime342.jsxs)("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
10594
+ /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
10226
10595
  "div",
10227
10596
  {
10228
10597
  className: "lib-xplat-swiper__viewport",
10229
10598
  onMouseDown: handleDragStart,
10230
10599
  onTouchStart: handleDragStart,
10231
10600
  onDragStart: (e) => e.preventDefault(),
10232
- children: /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(
10601
+ children: /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
10233
10602
  "div",
10234
10603
  {
10235
10604
  className: clsx_default(
@@ -10247,7 +10616,7 @@ var Swiper = (props) => {
10247
10616
  )
10248
10617
  }
10249
10618
  ),
10250
- showProgress && canSlide && /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(
10619
+ showProgress && canSlide && /* @__PURE__ */ (0, import_jsx_runtime342.jsx)("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ (0, import_jsx_runtime342.jsx)("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
10251
10620
  "span",
10252
10621
  {
10253
10622
  className: "lib-xplat-swiper__progress-fill",
@@ -10257,7 +10626,7 @@ var Swiper = (props) => {
10257
10626
  }
10258
10627
  }
10259
10628
  ) }) }),
10260
- canSlide && /* @__PURE__ */ (0, import_jsx_runtime341.jsx)("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime341.jsx)(
10629
+ canSlide && /* @__PURE__ */ (0, import_jsx_runtime342.jsx)("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
10261
10630
  "button",
10262
10631
  {
10263
10632
  className: clsx_default(
@@ -10275,8 +10644,8 @@ Swiper.displayName = "Swiper";
10275
10644
  var Swiper_default = Swiper;
10276
10645
 
10277
10646
  // src/components/Switch/Switch.tsx
10278
- var import_react32 = __toESM(require("react"), 1);
10279
- var import_jsx_runtime342 = require("react/jsx-runtime");
10647
+ var import_react33 = __toESM(require("react"), 1);
10648
+ var import_jsx_runtime343 = require("react/jsx-runtime");
10280
10649
  var KNOB_TRANSITION_MS = 250;
10281
10650
  var Switch = (props) => {
10282
10651
  const {
@@ -10285,12 +10654,15 @@ var Switch = (props) => {
10285
10654
  type = "primary",
10286
10655
  disabled,
10287
10656
  onChange,
10288
- validations
10657
+ validations,
10658
+ label,
10659
+ required
10289
10660
  } = props;
10661
+ const fieldId = import_react33.default.useId();
10290
10662
  const statusType = normalizeStatus(type);
10291
- const [isAnimating, setIsAnimating] = import_react32.default.useState(false);
10292
- const timeoutRef = import_react32.default.useRef(null);
10293
- import_react32.default.useEffect(() => {
10663
+ const [isAnimating, setIsAnimating] = import_react33.default.useState(false);
10664
+ const timeoutRef = import_react33.default.useRef(null);
10665
+ import_react33.default.useEffect(() => {
10294
10666
  return () => {
10295
10667
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
10296
10668
  };
@@ -10305,9 +10677,10 @@ var Switch = (props) => {
10305
10677
  timeoutRef.current = null;
10306
10678
  }, KNOB_TRANSITION_MS);
10307
10679
  };
10308
- const control = /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(
10680
+ const control = /* @__PURE__ */ (0, import_jsx_runtime343.jsx)(
10309
10681
  "div",
10310
10682
  {
10683
+ id: fieldId,
10311
10684
  className: clsx_default(
10312
10685
  "lib-xplat-switch",
10313
10686
  size,
@@ -10319,26 +10692,26 @@ var Switch = (props) => {
10319
10692
  onClick: handleClick,
10320
10693
  "aria-invalid": hasError(validations) || void 0,
10321
10694
  "aria-disabled": disabled || isAnimating,
10322
- children: /* @__PURE__ */ (0, import_jsx_runtime342.jsx)("div", { className: clsx_default("knob", value ? "checked" : void 0) })
10695
+ children: /* @__PURE__ */ (0, import_jsx_runtime343.jsx)("div", { className: clsx_default("knob", value ? "checked" : void 0) })
10323
10696
  }
10324
10697
  );
10325
- return /* @__PURE__ */ (0, import_jsx_runtime342.jsx)(Field, { validations, children: control });
10698
+ return /* @__PURE__ */ (0, import_jsx_runtime343.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
10326
10699
  };
10327
10700
  Switch.displayName = "Switch";
10328
10701
  var Switch_default = Switch;
10329
10702
 
10330
10703
  // src/components/Table/TableContext.tsx
10331
- var import_react33 = __toESM(require("react"), 1);
10332
- var TableContext = import_react33.default.createContext(null);
10704
+ var import_react34 = __toESM(require("react"), 1);
10705
+ var TableContext = import_react34.default.createContext(null);
10333
10706
  var useTableContext = () => {
10334
- const ctx = import_react33.default.useContext(TableContext);
10707
+ const ctx = import_react34.default.useContext(TableContext);
10335
10708
  if (!ctx) throw new Error("Table components must be used inside <Table>");
10336
10709
  return ctx;
10337
10710
  };
10338
10711
  var TableContext_default = TableContext;
10339
10712
 
10340
10713
  // src/components/Table/Table.tsx
10341
- var import_jsx_runtime343 = require("react/jsx-runtime");
10714
+ var import_jsx_runtime344 = require("react/jsx-runtime");
10342
10715
  var Table = (props) => {
10343
10716
  const {
10344
10717
  children,
@@ -10348,7 +10721,7 @@ var Table = (props) => {
10348
10721
  headerSticky = false,
10349
10722
  stickyShadow = true
10350
10723
  } = props;
10351
- return /* @__PURE__ */ (0, import_jsx_runtime343.jsx)("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ (0, import_jsx_runtime343.jsx)(
10724
+ return /* @__PURE__ */ (0, import_jsx_runtime344.jsx)("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ (0, import_jsx_runtime344.jsx)(
10352
10725
  TableContext_default.Provider,
10353
10726
  {
10354
10727
  value: {
@@ -10357,7 +10730,7 @@ var Table = (props) => {
10357
10730
  headerSticky,
10358
10731
  stickyShadow
10359
10732
  },
10360
- children: /* @__PURE__ */ (0, import_jsx_runtime343.jsx)("table", { className: "lib-xplat-table", children })
10733
+ children: /* @__PURE__ */ (0, import_jsx_runtime344.jsx)("table", { className: "lib-xplat-table", children })
10361
10734
  }
10362
10735
  ) });
10363
10736
  };
@@ -10365,41 +10738,41 @@ Table.displayName = "Table";
10365
10738
  var Table_default = Table;
10366
10739
 
10367
10740
  // src/components/Table/TableBody.tsx
10368
- var import_jsx_runtime344 = require("react/jsx-runtime");
10741
+ var import_jsx_runtime345 = require("react/jsx-runtime");
10369
10742
  var TableBody = (props) => {
10370
10743
  const { children } = props;
10371
- return /* @__PURE__ */ (0, import_jsx_runtime344.jsx)("tbody", { children });
10744
+ return /* @__PURE__ */ (0, import_jsx_runtime345.jsx)("tbody", { children });
10372
10745
  };
10373
10746
  TableBody.displayName = "TableBody";
10374
10747
  var TableBody_default = TableBody;
10375
10748
 
10376
10749
  // src/components/Table/TableCell.tsx
10377
- var import_react36 = __toESM(require("react"), 1);
10750
+ var import_react37 = __toESM(require("react"), 1);
10378
10751
 
10379
10752
  // src/components/Table/TableHeadContext.tsx
10380
- var import_react34 = __toESM(require("react"), 1);
10381
- var TableHeadContext = import_react34.default.createContext(
10753
+ var import_react35 = __toESM(require("react"), 1);
10754
+ var TableHeadContext = import_react35.default.createContext(
10382
10755
  null
10383
10756
  );
10384
10757
  var useTableHeadContext = () => {
10385
- const ctx = import_react34.default.useContext(TableHeadContext);
10758
+ const ctx = import_react35.default.useContext(TableHeadContext);
10386
10759
  return ctx;
10387
10760
  };
10388
10761
  var TableHeadContext_default = TableHeadContext;
10389
10762
 
10390
10763
  // src/components/Table/TableRowContext.tsx
10391
- var import_react35 = __toESM(require("react"), 1);
10392
- var TableRowContext = import_react35.default.createContext(null);
10764
+ var import_react36 = __toESM(require("react"), 1);
10765
+ var TableRowContext = import_react36.default.createContext(null);
10393
10766
  var useTableRowContext = () => {
10394
- const ctx = import_react35.default.useContext(TableRowContext);
10767
+ const ctx = import_react36.default.useContext(TableRowContext);
10395
10768
  if (!ctx) throw new Error("Table components must be used inside <Table>");
10396
10769
  return ctx;
10397
10770
  };
10398
10771
  var TableRowContext_default = TableRowContext;
10399
10772
 
10400
10773
  // src/components/Table/TableCell.tsx
10401
- var import_jsx_runtime345 = require("react/jsx-runtime");
10402
- var TableCell = import_react36.default.memo((props) => {
10774
+ var import_jsx_runtime346 = require("react/jsx-runtime");
10775
+ var TableCell = import_react37.default.memo((props) => {
10403
10776
  const {
10404
10777
  children,
10405
10778
  align = "center",
@@ -10413,9 +10786,9 @@ var TableCell = import_react36.default.memo((props) => {
10413
10786
  const { registerStickyCell, stickyCells } = useTableRowContext();
10414
10787
  const { stickyShadow } = useTableContext();
10415
10788
  const headContext = useTableHeadContext();
10416
- const [left, setLeft] = import_react36.default.useState(0);
10417
- const cellRef = import_react36.default.useRef(null);
10418
- const calculateLeft = import_react36.default.useCallback(() => {
10789
+ const [left, setLeft] = import_react37.default.useState(0);
10790
+ const cellRef = import_react37.default.useRef(null);
10791
+ const calculateLeft = import_react37.default.useCallback(() => {
10419
10792
  if (!cellRef.current) return 0;
10420
10793
  let totalLeft = 0;
10421
10794
  for (const ref of stickyCells) {
@@ -10424,7 +10797,7 @@ var TableCell = import_react36.default.memo((props) => {
10424
10797
  }
10425
10798
  return totalLeft;
10426
10799
  }, [stickyCells]);
10427
- import_react36.default.useEffect(() => {
10800
+ import_react37.default.useEffect(() => {
10428
10801
  if (!isSticky || !cellRef.current) return;
10429
10802
  registerStickyCell(cellRef);
10430
10803
  setLeft(calculateLeft());
@@ -10443,7 +10816,7 @@ var TableCell = import_react36.default.memo((props) => {
10443
10816
  const CellTag = isHeaderCell ? "th" : "td";
10444
10817
  const isLastSticky = isSticky && stickyCells[stickyCells.length - 1] === cellRef;
10445
10818
  const enableHover = headContext && headContext.cellHover;
10446
- return /* @__PURE__ */ (0, import_jsx_runtime345.jsx)(
10819
+ return /* @__PURE__ */ (0, import_jsx_runtime346.jsx)(
10447
10820
  CellTag,
10448
10821
  {
10449
10822
  ref: cellRef,
@@ -10470,21 +10843,21 @@ TableCell.displayName = "TableCell";
10470
10843
  var TableCell_default = TableCell;
10471
10844
 
10472
10845
  // src/components/Table/TableHead.tsx
10473
- var import_jsx_runtime346 = require("react/jsx-runtime");
10846
+ var import_jsx_runtime347 = require("react/jsx-runtime");
10474
10847
  var TableHead = ({
10475
10848
  children,
10476
10849
  cellHover = false
10477
10850
  }) => {
10478
10851
  const { headerSticky } = useTableContext();
10479
- return /* @__PURE__ */ (0, import_jsx_runtime346.jsx)(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ (0, import_jsx_runtime346.jsx)("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
10852
+ return /* @__PURE__ */ (0, import_jsx_runtime347.jsx)(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ (0, import_jsx_runtime347.jsx)("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
10480
10853
  };
10481
10854
  TableHead.displayName = "TableHead";
10482
10855
  var TableHead_default = TableHead;
10483
10856
 
10484
10857
  // src/components/Table/TableRow.tsx
10485
- var import_react37 = __toESM(require("react"), 1);
10486
- var import_jsx_runtime347 = require("react/jsx-runtime");
10487
- var TableRow = import_react37.default.memo((props) => {
10858
+ var import_react38 = __toESM(require("react"), 1);
10859
+ var import_jsx_runtime348 = require("react/jsx-runtime");
10860
+ var TableRow = import_react38.default.memo((props) => {
10488
10861
  const {
10489
10862
  children,
10490
10863
  type = "secondary",
@@ -10493,14 +10866,14 @@ var TableRow = import_react37.default.memo((props) => {
10493
10866
  onClick
10494
10867
  } = props;
10495
10868
  const { rowBorderUse } = useTableContext();
10496
- const [stickyCells, setStickyCells] = import_react37.default.useState([]);
10869
+ const [stickyCells, setStickyCells] = import_react38.default.useState([]);
10497
10870
  const registerStickyCell = (ref) => {
10498
10871
  setStickyCells((prev) => {
10499
10872
  if (prev.includes(ref)) return prev;
10500
10873
  return [...prev, ref];
10501
10874
  });
10502
10875
  };
10503
- return /* @__PURE__ */ (0, import_jsx_runtime347.jsx)(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ (0, import_jsx_runtime347.jsx)(
10876
+ return /* @__PURE__ */ (0, import_jsx_runtime348.jsx)(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ (0, import_jsx_runtime348.jsx)(
10504
10877
  "tr",
10505
10878
  {
10506
10879
  className: clsx_default(
@@ -10524,7 +10897,7 @@ TableRow.displayName = "TableRow";
10524
10897
  var TableRow_default = TableRow;
10525
10898
 
10526
10899
  // src/components/Tag/Tag.tsx
10527
- var import_jsx_runtime348 = require("react/jsx-runtime");
10900
+ var import_jsx_runtime349 = require("react/jsx-runtime");
10528
10901
  var Tag = (props) => {
10529
10902
  const {
10530
10903
  children,
@@ -10536,7 +10909,7 @@ var Tag = (props) => {
10536
10909
  colorIndex
10537
10910
  } = props;
10538
10911
  const shape = variant ?? type ?? "neutral";
10539
- return /* @__PURE__ */ (0, import_jsx_runtime348.jsxs)(
10912
+ return /* @__PURE__ */ (0, import_jsx_runtime349.jsxs)(
10540
10913
  "span",
10541
10914
  {
10542
10915
  className: clsx_default(
@@ -10547,8 +10920,8 @@ var Tag = (props) => {
10547
10920
  disabled && "disabled"
10548
10921
  ),
10549
10922
  children: [
10550
- /* @__PURE__ */ (0, import_jsx_runtime348.jsx)("span", { className: "tag-label", children }),
10551
- onClose && /* @__PURE__ */ (0, import_jsx_runtime348.jsx)("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ (0, import_jsx_runtime348.jsx)(XIcon_default, {}) })
10923
+ /* @__PURE__ */ (0, import_jsx_runtime349.jsx)("span", { className: "tag-label", children }),
10924
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime349.jsx)("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ (0, import_jsx_runtime349.jsx)(XIcon_default, {}) })
10552
10925
  ]
10553
10926
  }
10554
10927
  );
@@ -10557,24 +10930,29 @@ Tag.displayName = "Tag";
10557
10930
  var Tag_default = Tag;
10558
10931
 
10559
10932
  // src/components/TextArea/TextArea.tsx
10560
- var import_react38 = __toESM(require("react"), 1);
10561
- var import_jsx_runtime349 = require("react/jsx-runtime");
10562
- var TextArea = import_react38.default.forwardRef(
10933
+ var import_react39 = __toESM(require("react"), 1);
10934
+ var import_jsx_runtime350 = require("react/jsx-runtime");
10935
+ var TextArea = import_react39.default.forwardRef(
10563
10936
  (props, ref) => {
10564
10937
  const {
10565
10938
  className,
10566
10939
  size = "md",
10567
10940
  validations,
10941
+ label,
10942
+ required,
10568
10943
  resize = "vertical",
10569
10944
  rows = 3,
10570
10945
  disabled,
10571
10946
  ...textareaProps
10572
10947
  } = props;
10573
- const control = /* @__PURE__ */ (0, import_jsx_runtime349.jsx)("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ (0, import_jsx_runtime349.jsx)(
10948
+ const autoId = import_react39.default.useId();
10949
+ const fieldId = props.id ?? autoId;
10950
+ const control = /* @__PURE__ */ (0, import_jsx_runtime350.jsx)("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ (0, import_jsx_runtime350.jsx)(
10574
10951
  "textarea",
10575
10952
  {
10576
10953
  ...textareaProps,
10577
10954
  ref,
10955
+ id: fieldId,
10578
10956
  rows,
10579
10957
  disabled,
10580
10958
  "aria-invalid": hasError(validations) || void 0,
@@ -10582,32 +10960,166 @@ var TextArea = import_react38.default.forwardRef(
10582
10960
  style: { resize }
10583
10961
  }
10584
10962
  ) });
10585
- return /* @__PURE__ */ (0, import_jsx_runtime349.jsx)(Field, { validations, children: control });
10963
+ return /* @__PURE__ */ (0, import_jsx_runtime350.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
10586
10964
  }
10587
10965
  );
10588
10966
  TextArea.displayName = "TextArea";
10589
10967
  var TextArea_default = TextArea;
10590
10968
 
10969
+ // src/components/TimePicker/TimePicker.tsx
10970
+ var import_react40 = __toESM(require("react"), 1);
10971
+ var import_jsx_runtime351 = require("react/jsx-runtime");
10972
+ var ANIMATION_DURATION_MS4 = 200;
10973
+ var toMinutes = (hhmm) => {
10974
+ if (!hhmm) return null;
10975
+ const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
10976
+ if (!m) return null;
10977
+ const h = Number(m[1]);
10978
+ const min = Number(m[2]);
10979
+ if (h > 23 || min > 59) return null;
10980
+ return h * 60 + min;
10981
+ };
10982
+ var toHHmm = (minutes) => `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
10983
+ var display = (hhmm, use12Hours) => {
10984
+ if (!use12Hours) return hhmm;
10985
+ const total = toMinutes(hhmm);
10986
+ if (total === null) return hhmm;
10987
+ const h24 = Math.floor(total / 60);
10988
+ const mm = String(total % 60).padStart(2, "0");
10989
+ const period = h24 < 12 ? "\uC624\uC804" : "\uC624\uD6C4";
10990
+ const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
10991
+ return `${period} ${h12}:${mm}`;
10992
+ };
10993
+ var TimePicker = (props) => {
10994
+ const {
10995
+ value,
10996
+ onChange,
10997
+ step = 30,
10998
+ min,
10999
+ max,
11000
+ use12Hours = false,
11001
+ placeholder = "\uC2DC\uAC01 \uC120\uD0DD",
11002
+ disabled = false,
11003
+ size = "md",
11004
+ label,
11005
+ required,
11006
+ validations
11007
+ } = props;
11008
+ const fieldId = import_react40.default.useId();
11009
+ const triggerRef = import_react40.default.useRef(null);
11010
+ const contentRef = import_react40.default.useRef(null);
11011
+ const [isOpen, setOpen] = import_react40.default.useState(false);
11012
+ const [mounted, setMounted] = import_react40.default.useState(false);
11013
+ const [visible, setVisible] = import_react40.default.useState(false);
11014
+ const options = import_react40.default.useMemo(() => {
11015
+ const safeStep = step > 0 && step <= 720 ? step : 30;
11016
+ const lo = toMinutes(min) ?? 0;
11017
+ const hi = toMinutes(max) ?? 24 * 60 - 1;
11018
+ const out = [];
11019
+ for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
11020
+ return out;
11021
+ }, [step, min, max]);
11022
+ const close = import_react40.default.useCallback(() => setOpen(false), []);
11023
+ useClickOutside_default([triggerRef, contentRef], close, isOpen);
11024
+ useEscapeKey(isOpen, () => {
11025
+ close();
11026
+ triggerRef.current?.focus({ preventScroll: true });
11027
+ });
11028
+ const position = useAutoPosition_default(triggerRef, contentRef, mounted);
11029
+ import_react40.default.useEffect(() => {
11030
+ if (disabled && isOpen) setOpen(false);
11031
+ }, [disabled, isOpen]);
11032
+ import_react40.default.useEffect(() => {
11033
+ if (isOpen) {
11034
+ setMounted(true);
11035
+ const t2 = setTimeout(() => setVisible(true), 1);
11036
+ return () => clearTimeout(t2);
11037
+ }
11038
+ setVisible(false);
11039
+ const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS4);
11040
+ return () => clearTimeout(t);
11041
+ }, [isOpen]);
11042
+ const pick = (hhmm) => {
11043
+ onChange?.(hhmm);
11044
+ close();
11045
+ triggerRef.current?.focus({ preventScroll: true });
11046
+ };
11047
+ const control = /* @__PURE__ */ (0, import_jsx_runtime351.jsxs)("div", { className: clsx_default("lib-xplat-time-picker", size, disabled && "disabled"), children: [
11048
+ /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(
11049
+ "div",
11050
+ {
11051
+ id: fieldId,
11052
+ ref: triggerRef,
11053
+ className: clsx_default("time-picker-trigger", hasError(validations) && "error"),
11054
+ role: "combobox",
11055
+ "aria-expanded": isOpen,
11056
+ "aria-haspopup": "listbox",
11057
+ "aria-invalid": hasError(validations) || void 0,
11058
+ tabIndex: disabled ? void 0 : 0,
11059
+ onClick: () => !disabled && setOpen((p) => !p),
11060
+ onKeyDown: (e) => {
11061
+ if (disabled) return;
11062
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
11063
+ e.preventDefault();
11064
+ setOpen(true);
11065
+ }
11066
+ },
11067
+ children: /* @__PURE__ */ (0, import_jsx_runtime351.jsx)("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
11068
+ }
11069
+ ),
11070
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(
11071
+ "div",
11072
+ {
11073
+ ref: contentRef,
11074
+ className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit"),
11075
+ style: { ...position.position, width: triggerRef.current?.offsetWidth },
11076
+ role: "listbox",
11077
+ children: options.map((t) => /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(
11078
+ "div",
11079
+ {
11080
+ className: clsx_default("time-picker-item", t === value && "is-selected"),
11081
+ role: "option",
11082
+ "aria-selected": t === value,
11083
+ tabIndex: 0,
11084
+ onClick: () => pick(t),
11085
+ onKeyDown: (e) => {
11086
+ if (e.key === "Enter" || e.key === " ") {
11087
+ e.preventDefault();
11088
+ pick(t);
11089
+ }
11090
+ },
11091
+ children: display(t, use12Hours)
11092
+ },
11093
+ t
11094
+ ))
11095
+ }
11096
+ ) })
11097
+ ] });
11098
+ return /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
11099
+ };
11100
+ TimePicker.displayName = "TimePicker";
11101
+ var TimePicker_default = TimePicker;
11102
+
10591
11103
  // src/components/Toast/Toast.tsx
10592
- var import_react39 = __toESM(require("react"), 1);
11104
+ var import_react41 = __toESM(require("react"), 1);
10593
11105
  var import_react_dom4 = require("react-dom");
10594
- var import_jsx_runtime350 = require("react/jsx-runtime");
10595
- var ToastContext = import_react39.default.createContext(null);
11106
+ var import_jsx_runtime352 = require("react/jsx-runtime");
11107
+ var ToastContext = import_react41.default.createContext(null);
10596
11108
  var useToast = () => {
10597
- const ctx = import_react39.default.useContext(ToastContext);
11109
+ const ctx = import_react41.default.useContext(ToastContext);
10598
11110
  if (!ctx) throw new Error("useToast must be used within ToastProvider");
10599
11111
  return ctx;
10600
11112
  };
10601
11113
  var EXIT_DURATION = 300;
10602
11114
  var ToastItemComponent = ({ item, isExiting, onClose }) => {
10603
- const ref = import_react39.default.useRef(null);
10604
- const [height, setHeight] = import_react39.default.useState(void 0);
10605
- import_react39.default.useEffect(() => {
11115
+ const ref = import_react41.default.useRef(null);
11116
+ const [height, setHeight] = import_react41.default.useState(void 0);
11117
+ import_react41.default.useEffect(() => {
10606
11118
  if (ref.current && !isExiting) {
10607
11119
  setHeight(ref.current.offsetHeight);
10608
11120
  }
10609
11121
  }, [isExiting]);
10610
- return /* @__PURE__ */ (0, import_jsx_runtime350.jsx)(
11122
+ return /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
10611
11123
  "div",
10612
11124
  {
10613
11125
  className: clsx_default("lib-xplat-toast-wrapper", { exit: isExiting }),
@@ -10615,15 +11127,15 @@ var ToastItemComponent = ({ item, isExiting, onClose }) => {
10615
11127
  maxHeight: isExiting ? 0 : height ?? "none",
10616
11128
  marginBottom: isExiting ? 0 : void 0
10617
11129
  },
10618
- children: /* @__PURE__ */ (0, import_jsx_runtime350.jsxs)(
11130
+ children: /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)(
10619
11131
  "div",
10620
11132
  {
10621
11133
  ref,
10622
11134
  className: clsx_default("lib-xplat-toast", item.type, { exit: isExiting }),
10623
11135
  role: "alert",
10624
11136
  children: [
10625
- /* @__PURE__ */ (0, import_jsx_runtime350.jsx)("span", { className: "message", children: item.message }),
10626
- /* @__PURE__ */ (0, import_jsx_runtime350.jsx)("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
11137
+ /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("span", { className: "message", children: item.message }),
11138
+ /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
10627
11139
  ]
10628
11140
  }
10629
11141
  )
@@ -10634,13 +11146,13 @@ var ToastProvider = ({
10634
11146
  children,
10635
11147
  position = "top-right"
10636
11148
  }) => {
10637
- const [toasts, setToasts] = import_react39.default.useState([]);
10638
- const [removing, setRemoving] = import_react39.default.useState(/* @__PURE__ */ new Set());
10639
- const [mounted, setMounted] = import_react39.default.useState(false);
10640
- import_react39.default.useEffect(() => {
11149
+ const [toasts, setToasts] = import_react41.default.useState([]);
11150
+ const [removing, setRemoving] = import_react41.default.useState(/* @__PURE__ */ new Set());
11151
+ const [mounted, setMounted] = import_react41.default.useState(false);
11152
+ import_react41.default.useEffect(() => {
10641
11153
  setMounted(true);
10642
11154
  }, []);
10643
- const remove = import_react39.default.useCallback((id) => {
11155
+ const remove = import_react41.default.useCallback((id) => {
10644
11156
  setRemoving((prev) => new Set(prev).add(id));
10645
11157
  setTimeout(() => {
10646
11158
  setToasts((prev) => prev.filter((t) => t.id !== id));
@@ -10651,7 +11163,7 @@ var ToastProvider = ({
10651
11163
  });
10652
11164
  }, EXIT_DURATION);
10653
11165
  }, []);
10654
- const toast = import_react39.default.useCallback(
11166
+ const toast = import_react41.default.useCallback(
10655
11167
  (type, message, duration = 3e3) => {
10656
11168
  const id = `${Date.now()}-${Math.random()}`;
10657
11169
  setToasts((prev) => [...prev, { id, type, message }]);
@@ -10661,10 +11173,10 @@ var ToastProvider = ({
10661
11173
  },
10662
11174
  [remove]
10663
11175
  );
10664
- return /* @__PURE__ */ (0, import_jsx_runtime350.jsxs)(ToastContext.Provider, { value: { toast }, children: [
11176
+ return /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)(ToastContext.Provider, { value: { toast }, children: [
10665
11177
  children,
10666
11178
  mounted && (0, import_react_dom4.createPortal)(
10667
- /* @__PURE__ */ (0, import_jsx_runtime350.jsx)("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime350.jsx)(
11179
+ /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
10668
11180
  ToastItemComponent,
10669
11181
  {
10670
11182
  item: t,
@@ -10680,8 +11192,8 @@ var ToastProvider = ({
10680
11192
  ToastProvider.displayName = "ToastProvider";
10681
11193
 
10682
11194
  // src/components/Tooltip/Tooltip.tsx
10683
- var import_react40 = __toESM(require("react"), 1);
10684
- var import_jsx_runtime351 = require("react/jsx-runtime");
11195
+ var import_react42 = __toESM(require("react"), 1);
11196
+ var import_jsx_runtime353 = require("react/jsx-runtime");
10685
11197
  var OFFSET = 12;
10686
11198
  var GAP = 8;
10687
11199
  var SHOW_DELAY = 300;
@@ -10696,14 +11208,14 @@ var Tooltip = (props) => {
10696
11208
  disabled = false
10697
11209
  } = props;
10698
11210
  const shape = variant ?? type ?? "dark";
10699
- const triggerRef = import_react40.default.useRef(null);
10700
- const tooltipRef = import_react40.default.useRef(null);
10701
- const [visible, setVisible] = import_react40.default.useState(false);
10702
- const [pos, setPos] = import_react40.default.useState({ left: 0, top: 0 });
10703
- const delayTimer = import_react40.default.useRef(0);
10704
- const rafRef = import_react40.default.useRef(0);
10705
- const cursor = import_react40.default.useRef(null);
10706
- const clamp = import_react40.default.useCallback((left, top, w, h) => {
11211
+ const triggerRef = import_react42.default.useRef(null);
11212
+ const tooltipRef = import_react42.default.useRef(null);
11213
+ const [visible, setVisible] = import_react42.default.useState(false);
11214
+ const [pos, setPos] = import_react42.default.useState({ left: 0, top: 0 });
11215
+ const delayTimer = import_react42.default.useRef(0);
11216
+ const rafRef = import_react42.default.useRef(0);
11217
+ const cursor = import_react42.default.useRef(null);
11218
+ const clamp = import_react42.default.useCallback((left, top, w, h) => {
10707
11219
  const vw = window.innerWidth;
10708
11220
  const vh = window.innerHeight;
10709
11221
  return {
@@ -10711,7 +11223,7 @@ var Tooltip = (props) => {
10711
11223
  top: Math.min(Math.max(GAP, top), Math.max(GAP, vh - h - GAP))
10712
11224
  };
10713
11225
  }, []);
10714
- const placeAtCursor = import_react40.default.useCallback((x, y) => {
11226
+ const placeAtCursor = import_react42.default.useCallback((x, y) => {
10715
11227
  const el = tooltipRef.current;
10716
11228
  if (!el) return;
10717
11229
  const w = el.offsetWidth;
@@ -10722,7 +11234,7 @@ var Tooltip = (props) => {
10722
11234
  if (top < GAP) top = y + OFFSET;
10723
11235
  setPos(clamp(left, top, w, h));
10724
11236
  }, [clamp]);
10725
- const placeAtTrigger = import_react40.default.useCallback(() => {
11237
+ const placeAtTrigger = import_react42.default.useCallback(() => {
10726
11238
  const el = tooltipRef.current;
10727
11239
  const trigger = triggerRef.current;
10728
11240
  if (!el || !trigger) return;
@@ -10734,19 +11246,19 @@ var Tooltip = (props) => {
10734
11246
  const left = rect.left + rect.width / 2 - w / 2;
10735
11247
  setPos(clamp(left, top, w, h));
10736
11248
  }, [clamp]);
10737
- const reposition = import_react40.default.useCallback(() => {
11249
+ const reposition = import_react42.default.useCallback(() => {
10738
11250
  if (follow && cursor.current) {
10739
11251
  placeAtCursor(cursor.current.x, cursor.current.y);
10740
11252
  } else {
10741
11253
  placeAtTrigger();
10742
11254
  }
10743
11255
  }, [follow, placeAtCursor, placeAtTrigger]);
10744
- const handleMouseEnter = import_react40.default.useCallback((e) => {
11256
+ const handleMouseEnter = import_react42.default.useCallback((e) => {
10745
11257
  if (disabled) return;
10746
11258
  cursor.current = { x: e.clientX, y: e.clientY };
10747
11259
  delayTimer.current = window.setTimeout(() => setVisible(true), SHOW_DELAY);
10748
11260
  }, [disabled]);
10749
- const handleMouseMove = import_react40.default.useCallback((e) => {
11261
+ const handleMouseMove = import_react42.default.useCallback((e) => {
10750
11262
  cursor.current = { x: e.clientX, y: e.clientY };
10751
11263
  if (!visible || !follow) return;
10752
11264
  cancelAnimationFrame(rafRef.current);
@@ -10754,25 +11266,25 @@ var Tooltip = (props) => {
10754
11266
  if (cursor.current) placeAtCursor(cursor.current.x, cursor.current.y);
10755
11267
  });
10756
11268
  }, [visible, follow, placeAtCursor]);
10757
- const close = import_react40.default.useCallback(() => {
11269
+ const close = import_react42.default.useCallback(() => {
10758
11270
  window.clearTimeout(delayTimer.current);
10759
11271
  cancelAnimationFrame(rafRef.current);
10760
11272
  setVisible(false);
10761
11273
  }, []);
10762
- const handleMouseLeave = import_react40.default.useCallback(() => {
11274
+ const handleMouseLeave = import_react42.default.useCallback(() => {
10763
11275
  cursor.current = null;
10764
11276
  close();
10765
11277
  }, [close]);
10766
- const handleFocus = import_react40.default.useCallback(() => {
11278
+ const handleFocus = import_react42.default.useCallback(() => {
10767
11279
  if (disabled) return;
10768
11280
  cursor.current = null;
10769
11281
  setVisible(true);
10770
11282
  }, [disabled]);
10771
- import_react40.default.useLayoutEffect(() => {
11283
+ import_react42.default.useLayoutEffect(() => {
10772
11284
  if (!visible) return;
10773
11285
  reposition();
10774
11286
  }, [visible, reposition]);
10775
- import_react40.default.useEffect(() => {
11287
+ import_react42.default.useEffect(() => {
10776
11288
  if (!visible || follow) return;
10777
11289
  const onChange = () => placeAtTrigger();
10778
11290
  window.addEventListener("scroll", onChange, true);
@@ -10782,12 +11294,12 @@ var Tooltip = (props) => {
10782
11294
  window.removeEventListener("resize", onChange);
10783
11295
  };
10784
11296
  }, [visible, follow, placeAtTrigger]);
10785
- import_react40.default.useEffect(() => () => {
11297
+ import_react42.default.useEffect(() => () => {
10786
11298
  window.clearTimeout(delayTimer.current);
10787
11299
  cancelAnimationFrame(rafRef.current);
10788
11300
  }, []);
10789
- if (!title && !description) return /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(import_jsx_runtime351.Fragment, { children });
10790
- return /* @__PURE__ */ (0, import_jsx_runtime351.jsxs)(
11301
+ if (!title && !description) return /* @__PURE__ */ (0, import_jsx_runtime353.jsx)(import_jsx_runtime353.Fragment, { children });
11302
+ return /* @__PURE__ */ (0, import_jsx_runtime353.jsxs)(
10791
11303
  "div",
10792
11304
  {
10793
11305
  ref: triggerRef,
@@ -10800,7 +11312,7 @@ var Tooltip = (props) => {
10800
11312
  onBlur: close,
10801
11313
  children: [
10802
11314
  children,
10803
- visible && /* @__PURE__ */ (0, import_jsx_runtime351.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime351.jsxs)(
11315
+ visible && /* @__PURE__ */ (0, import_jsx_runtime353.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime353.jsxs)(
10804
11316
  "div",
10805
11317
  {
10806
11318
  ref: tooltipRef,
@@ -10808,8 +11320,8 @@ var Tooltip = (props) => {
10808
11320
  className: clsx_default("lib-xplat-tooltip", shape),
10809
11321
  style: { position: "fixed", left: pos.left, top: pos.top },
10810
11322
  children: [
10811
- title && /* @__PURE__ */ (0, import_jsx_runtime351.jsx)("div", { className: "tooltip-title", children: title }),
10812
- description && /* @__PURE__ */ (0, import_jsx_runtime351.jsx)("div", { className: "tooltip-desc", children: description })
11323
+ title && /* @__PURE__ */ (0, import_jsx_runtime353.jsx)("div", { className: "tooltip-title", children: title }),
11324
+ description && /* @__PURE__ */ (0, import_jsx_runtime353.jsx)("div", { className: "tooltip-desc", children: description })
10813
11325
  ]
10814
11326
  }
10815
11327
  ) })
@@ -10821,11 +11333,11 @@ Tooltip.displayName = "Tooltip";
10821
11333
  var Tooltip_default = Tooltip;
10822
11334
 
10823
11335
  // src/components/Video/Video.tsx
10824
- var import_react41 = __toESM(require("react"), 1);
10825
- var import_jsx_runtime352 = require("react/jsx-runtime");
10826
- var PipIcon = () => /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
10827
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
10828
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
11336
+ var import_react43 = __toESM(require("react"), 1);
11337
+ var import_jsx_runtime354 = require("react/jsx-runtime");
11338
+ var PipIcon = () => /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
11339
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
11340
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
10829
11341
  ] });
10830
11342
  var formatTime = (sec) => {
10831
11343
  if (!Number.isFinite(sec) || sec < 0) return "0:00";
@@ -10833,7 +11345,7 @@ var formatTime = (sec) => {
10833
11345
  const s = Math.floor(sec % 60);
10834
11346
  return `${m}:${s.toString().padStart(2, "0")}`;
10835
11347
  };
10836
- var Video = import_react41.default.forwardRef((props, ref) => {
11348
+ var Video = import_react43.default.forwardRef((props, ref) => {
10837
11349
  const {
10838
11350
  src,
10839
11351
  poster,
@@ -10857,21 +11369,21 @@ var Video = import_react41.default.forwardRef((props, ref) => {
10857
11369
  children,
10858
11370
  ...rest
10859
11371
  } = props;
10860
- const containerRef = import_react41.default.useRef(null);
10861
- const videoRef = import_react41.default.useRef(null);
10862
- const [isPlaying, setIsPlaying] = import_react41.default.useState(Boolean(autoPlay));
10863
- const [isLoaded, setIsLoaded] = import_react41.default.useState(false);
10864
- const [currentTime, setCurrentTime] = import_react41.default.useState(0);
10865
- const [duration, setDuration] = import_react41.default.useState(0);
10866
- const [buffered, setBuffered] = import_react41.default.useState(0);
10867
- const [volume, setVolume] = import_react41.default.useState(1);
10868
- const [isMuted, setIsMuted] = import_react41.default.useState(Boolean(muted));
10869
- const [isFullscreen, setIsFullscreen] = import_react41.default.useState(false);
10870
- const [playbackRate, setPlaybackRate] = import_react41.default.useState(1);
10871
- const [rateMenuOpen, setRateMenuOpen] = import_react41.default.useState(false);
10872
- const [captionsOn, setCaptionsOn] = import_react41.default.useState(false);
10873
- const [isPip, setIsPip] = import_react41.default.useState(false);
10874
- const setRefs = import_react41.default.useCallback(
11372
+ const containerRef = import_react43.default.useRef(null);
11373
+ const videoRef = import_react43.default.useRef(null);
11374
+ const [isPlaying, setIsPlaying] = import_react43.default.useState(Boolean(autoPlay));
11375
+ const [isLoaded, setIsLoaded] = import_react43.default.useState(false);
11376
+ const [currentTime, setCurrentTime] = import_react43.default.useState(0);
11377
+ const [duration, setDuration] = import_react43.default.useState(0);
11378
+ const [buffered, setBuffered] = import_react43.default.useState(0);
11379
+ const [volume, setVolume] = import_react43.default.useState(1);
11380
+ const [isMuted, setIsMuted] = import_react43.default.useState(Boolean(muted));
11381
+ const [isFullscreen, setIsFullscreen] = import_react43.default.useState(false);
11382
+ const [playbackRate, setPlaybackRate] = import_react43.default.useState(1);
11383
+ const [rateMenuOpen, setRateMenuOpen] = import_react43.default.useState(false);
11384
+ const [captionsOn, setCaptionsOn] = import_react43.default.useState(false);
11385
+ const [isPip, setIsPip] = import_react43.default.useState(false);
11386
+ const setRefs = import_react43.default.useCallback(
10875
11387
  (el) => {
10876
11388
  videoRef.current = el;
10877
11389
  if (typeof ref === "function") ref(el);
@@ -10879,14 +11391,14 @@ var Video = import_react41.default.forwardRef((props, ref) => {
10879
11391
  },
10880
11392
  [ref]
10881
11393
  );
10882
- import_react41.default.useEffect(() => {
11394
+ import_react43.default.useEffect(() => {
10883
11395
  const onFsChange = () => {
10884
11396
  setIsFullscreen(document.fullscreenElement === containerRef.current);
10885
11397
  };
10886
11398
  document.addEventListener("fullscreenchange", onFsChange);
10887
11399
  return () => document.removeEventListener("fullscreenchange", onFsChange);
10888
11400
  }, []);
10889
- import_react41.default.useEffect(() => {
11401
+ import_react43.default.useEffect(() => {
10890
11402
  const v = videoRef.current;
10891
11403
  if (!v) return;
10892
11404
  const onEnter = () => setIsPip(true);
@@ -11000,13 +11512,13 @@ var Video = import_react41.default.forwardRef((props, ref) => {
11000
11512
  const volumePct = (isMuted ? 0 : volume) * 100;
11001
11513
  const VolumeGlyph = isMuted || volume === 0 ? VolumeXIcon_default : volume < 0.5 ? VolumeIcon_default : Volume2Icon_default;
11002
11514
  const pipSupported = typeof document !== "undefined" && "pictureInPictureEnabled" in document && document.pictureInPictureEnabled;
11003
- return /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)(
11515
+ return /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)(
11004
11516
  "div",
11005
11517
  {
11006
11518
  ref: containerRef,
11007
11519
  className: clsx_default("lib-xplat-video", showControls && "has-controls"),
11008
11520
  children: [
11009
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
11521
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
11010
11522
  "video",
11011
11523
  {
11012
11524
  ref: setRefs,
@@ -11027,7 +11539,7 @@ var Video = import_react41.default.forwardRef((props, ref) => {
11027
11539
  children
11028
11540
  }
11029
11541
  ),
11030
- showCenterPlay && /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
11542
+ showCenterPlay && /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
11031
11543
  "button",
11032
11544
  {
11033
11545
  type: "button",
@@ -11039,11 +11551,11 @@ var Video = import_react41.default.forwardRef((props, ref) => {
11039
11551
  onClick: togglePlay,
11040
11552
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
11041
11553
  tabIndex: -1,
11042
- children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("span", { className: "center-play-icon", children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(PlayCircleIcon_default, {}) })
11554
+ children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("span", { className: "center-play-icon", children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(PlayCircleIcon_default, {}) })
11043
11555
  }
11044
11556
  ),
11045
- showControls && /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
11046
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
11557
+ showControls && /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
11558
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
11047
11559
  "input",
11048
11560
  {
11049
11561
  type: "range",
@@ -11060,29 +11572,29 @@ var Video = import_react41.default.forwardRef((props, ref) => {
11060
11572
  }
11061
11573
  }
11062
11574
  ),
11063
- /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("div", { className: "controls-row", children: [
11064
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
11575
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("div", { className: "controls-row", children: [
11576
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
11065
11577
  "button",
11066
11578
  {
11067
11579
  type: "button",
11068
11580
  className: "control-btn",
11069
11581
  onClick: togglePlay,
11070
11582
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
11071
- children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(PauseIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(PlayIcon_default, {})
11583
+ children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(PauseIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(PlayIcon_default, {})
11072
11584
  }
11073
11585
  ),
11074
- /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("div", { className: "volume-group", children: [
11075
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
11586
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("div", { className: "volume-group", children: [
11587
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
11076
11588
  "button",
11077
11589
  {
11078
11590
  type: "button",
11079
11591
  className: "control-btn",
11080
11592
  onClick: toggleMute,
11081
11593
  "aria-label": isMuted ? "\uC74C\uC18C\uAC70 \uD574\uC81C" : "\uC74C\uC18C\uAC70",
11082
- children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(VolumeGlyph, {})
11594
+ children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(VolumeGlyph, {})
11083
11595
  }
11084
11596
  ),
11085
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
11597
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
11086
11598
  "input",
11087
11599
  {
11088
11600
  type: "range",
@@ -11097,14 +11609,14 @@ var Video = import_react41.default.forwardRef((props, ref) => {
11097
11609
  }
11098
11610
  )
11099
11611
  ] }),
11100
- /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("span", { className: "time", children: [
11612
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("span", { className: "time", children: [
11101
11613
  formatTime(currentTime),
11102
11614
  " / ",
11103
11615
  formatTime(duration)
11104
11616
  ] }),
11105
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("div", { className: "controls-spacer" }),
11106
- playbackRates && playbackRates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
11107
- /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)(
11617
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("div", { className: "controls-spacer" }),
11618
+ playbackRates && playbackRates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
11619
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)(
11108
11620
  "button",
11109
11621
  {
11110
11622
  type: "button",
@@ -11118,7 +11630,7 @@ var Video = import_react41.default.forwardRef((props, ref) => {
11118
11630
  ]
11119
11631
  }
11120
11632
  ),
11121
- rateMenuOpen && /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ (0, import_jsx_runtime352.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime352.jsxs)(
11633
+ rateMenuOpen && /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime354.jsxs)(
11122
11634
  "button",
11123
11635
  {
11124
11636
  type: "button",
@@ -11132,7 +11644,7 @@ var Video = import_react41.default.forwardRef((props, ref) => {
11132
11644
  }
11133
11645
  ) }, r2)) })
11134
11646
  ] }),
11135
- showCaptions && /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
11647
+ showCaptions && /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
11136
11648
  "button",
11137
11649
  {
11138
11650
  type: "button",
@@ -11140,37 +11652,37 @@ var Video = import_react41.default.forwardRef((props, ref) => {
11140
11652
  onClick: toggleCaptions,
11141
11653
  "aria-label": captionsOn ? "\uC790\uB9C9 \uB044\uAE30" : "\uC790\uB9C9 \uCF1C\uAE30",
11142
11654
  "aria-pressed": captionsOn,
11143
- children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(TypeIcon_default, {})
11655
+ children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(TypeIcon_default, {})
11144
11656
  }
11145
11657
  ),
11146
- showPip && pipSupported && /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
11658
+ showPip && pipSupported && /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
11147
11659
  "button",
11148
11660
  {
11149
11661
  type: "button",
11150
11662
  className: clsx_default("control-btn", isPip && "is-active"),
11151
11663
  onClick: togglePip,
11152
11664
  "aria-label": isPip ? "PIP \uC885\uB8CC" : "PIP",
11153
- children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(PipIcon, {})
11665
+ children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(PipIcon, {})
11154
11666
  }
11155
11667
  ),
11156
- showDownload && /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
11668
+ showDownload && /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
11157
11669
  "a",
11158
11670
  {
11159
11671
  className: "control-btn",
11160
11672
  href: src,
11161
11673
  download: downloadFileName ?? true,
11162
11674
  "aria-label": "\uB2E4\uC6B4\uB85C\uB4DC",
11163
- children: /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(DownloadIcon_default, {})
11675
+ children: /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(DownloadIcon_default, {})
11164
11676
  }
11165
11677
  ),
11166
- /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(
11678
+ /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(
11167
11679
  "button",
11168
11680
  {
11169
11681
  type: "button",
11170
11682
  className: "control-btn",
11171
11683
  onClick: toggleFullscreen,
11172
11684
  "aria-label": isFullscreen ? "\uC804\uCCB4\uD654\uBA74 \uC885\uB8CC" : "\uC804\uCCB4\uD654\uBA74",
11173
- children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(MinimizeIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime352.jsx)(MaximizeIcon_default, {})
11685
+ children: isFullscreen ? /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(MinimizeIcon_default, {}) : /* @__PURE__ */ (0, import_jsx_runtime354.jsx)(MaximizeIcon_default, {})
11174
11686
  }
11175
11687
  )
11176
11688
  ] })
@@ -11183,7 +11695,7 @@ Video.displayName = "Video";
11183
11695
  var Video_default = Video;
11184
11696
 
11185
11697
  // src/layout/Grid/FullGrid/FullGrid.tsx
11186
- var import_jsx_runtime353 = require("react/jsx-runtime");
11698
+ var import_jsx_runtime355 = require("react/jsx-runtime");
11187
11699
  var GAP_MAP = {
11188
11700
  none: "var(--spacing-space-none)",
11189
11701
  xs: "var(--spacing-space-1)",
@@ -11196,13 +11708,13 @@ var GAP_MAP = {
11196
11708
  var FullGrid = (props) => {
11197
11709
  const { children, gap } = props;
11198
11710
  const style = gap != null ? { gap: GAP_MAP[gap] } : void 0;
11199
- return /* @__PURE__ */ (0, import_jsx_runtime353.jsx)("div", { className: "lib-xplat-full-grid", style, children });
11711
+ return /* @__PURE__ */ (0, import_jsx_runtime355.jsx)("div", { className: "lib-xplat-full-grid", style, children });
11200
11712
  };
11201
11713
  FullGrid.displayName = "FullGrid";
11202
11714
  var FullGrid_default = FullGrid;
11203
11715
 
11204
11716
  // src/layout/Grid/FullScreen/FullScreen.tsx
11205
- var import_jsx_runtime354 = require("react/jsx-runtime");
11717
+ var import_jsx_runtime356 = require("react/jsx-runtime");
11206
11718
  var GAP_MAP2 = {
11207
11719
  none: "var(--spacing-space-none)",
11208
11720
  xs: "var(--spacing-space-1)",
@@ -11215,13 +11727,13 @@ var GAP_MAP2 = {
11215
11727
  var FullScreen = (props) => {
11216
11728
  const { children, gap } = props;
11217
11729
  const style = gap != null ? { gap: GAP_MAP2[gap] } : void 0;
11218
- return /* @__PURE__ */ (0, import_jsx_runtime354.jsx)("div", { className: "lib-xplat-full-screen", style, children });
11730
+ return /* @__PURE__ */ (0, import_jsx_runtime356.jsx)("div", { className: "lib-xplat-full-screen", style, children });
11219
11731
  };
11220
11732
  FullScreen.displayName = "FullScreen";
11221
11733
  var FullScreen_default = FullScreen;
11222
11734
 
11223
11735
  // src/layout/Grid/Item/Item.tsx
11224
- var import_jsx_runtime355 = require("react/jsx-runtime");
11736
+ var import_jsx_runtime357 = require("react/jsx-runtime");
11225
11737
  var calculateSpans = (column) => {
11226
11738
  const spans = {};
11227
11739
  let inherited = column.default;
@@ -11238,35 +11750,35 @@ var GridItem = ({ column, children, className }) => {
11238
11750
  Object.entries(spans).forEach(([key, value]) => {
11239
11751
  style[`--column-${key}`] = value;
11240
11752
  });
11241
- return /* @__PURE__ */ (0, import_jsx_runtime355.jsx)("div", { className: clsx_default("lib-xplat-grid-item", className), style, children });
11753
+ return /* @__PURE__ */ (0, import_jsx_runtime357.jsx)("div", { className: clsx_default("lib-xplat-grid-item", className), style, children });
11242
11754
  };
11243
11755
  GridItem.displayName = "GridItem";
11244
11756
  var Item_default = GridItem;
11245
11757
 
11246
11758
  // src/layout/Header/Header.tsx
11247
- var import_jsx_runtime356 = require("react/jsx-runtime");
11759
+ var import_jsx_runtime358 = require("react/jsx-runtime");
11248
11760
  var Header = ({
11249
11761
  logo,
11250
11762
  centerContent,
11251
11763
  rightContent
11252
11764
  }) => {
11253
- return /* @__PURE__ */ (0, import_jsx_runtime356.jsxs)("div", { className: "lib-xplat-layout-header", children: [
11254
- /* @__PURE__ */ (0, import_jsx_runtime356.jsx)("div", { children: logo }),
11255
- /* @__PURE__ */ (0, import_jsx_runtime356.jsx)("div", { children: centerContent }),
11256
- /* @__PURE__ */ (0, import_jsx_runtime356.jsx)("div", { children: rightContent })
11765
+ return /* @__PURE__ */ (0, import_jsx_runtime358.jsxs)("div", { className: "lib-xplat-layout-header", children: [
11766
+ /* @__PURE__ */ (0, import_jsx_runtime358.jsx)("div", { children: logo }),
11767
+ /* @__PURE__ */ (0, import_jsx_runtime358.jsx)("div", { children: centerContent }),
11768
+ /* @__PURE__ */ (0, import_jsx_runtime358.jsx)("div", { children: rightContent })
11257
11769
  ] });
11258
11770
  };
11259
11771
  Header.displayName = "Header";
11260
11772
  var Header_default = Header;
11261
11773
 
11262
11774
  // src/layout/Layout/Layout.tsx
11263
- var import_jsx_runtime357 = require("react/jsx-runtime");
11775
+ var import_jsx_runtime359 = require("react/jsx-runtime");
11264
11776
  var Layout = (props) => {
11265
11777
  const { header, sideBar, children } = props;
11266
- return /* @__PURE__ */ (0, import_jsx_runtime357.jsx)("div", { className: "lib-xplat-layout", children: /* @__PURE__ */ (0, import_jsx_runtime357.jsxs)("div", { className: "lib-xplat-layout-content-wrapper", children: [
11267
- sideBar && /* @__PURE__ */ (0, import_jsx_runtime357.jsx)(import_jsx_runtime357.Fragment, { children: sideBar }),
11268
- /* @__PURE__ */ (0, import_jsx_runtime357.jsxs)("div", { className: "lib-xplat-layout-content", children: [
11269
- header && /* @__PURE__ */ (0, import_jsx_runtime357.jsx)("div", { className: "lib-xplat-layout-conent-header", children: header }),
11778
+ return /* @__PURE__ */ (0, import_jsx_runtime359.jsx)("div", { className: "lib-xplat-layout", children: /* @__PURE__ */ (0, import_jsx_runtime359.jsxs)("div", { className: "lib-xplat-layout-content-wrapper", children: [
11779
+ sideBar && /* @__PURE__ */ (0, import_jsx_runtime359.jsx)(import_jsx_runtime359.Fragment, { children: sideBar }),
11780
+ /* @__PURE__ */ (0, import_jsx_runtime359.jsxs)("div", { className: "lib-xplat-layout-content", children: [
11781
+ header && /* @__PURE__ */ (0, import_jsx_runtime359.jsx)("div", { className: "lib-xplat-layout-conent-header", children: header }),
11270
11782
  children
11271
11783
  ] })
11272
11784
  ] }) });
@@ -11275,31 +11787,31 @@ Layout.displayName = "Layout";
11275
11787
  var Layout_default = Layout;
11276
11788
 
11277
11789
  // src/layout/SideBar/SideBar.tsx
11278
- var import_react43 = __toESM(require("react"), 1);
11790
+ var import_react45 = __toESM(require("react"), 1);
11279
11791
 
11280
11792
  // src/layout/SideBar/SideBarContext.tsx
11281
- var import_react42 = __toESM(require("react"), 1);
11282
- var SideBarContext = import_react42.default.createContext(null);
11793
+ var import_react44 = __toESM(require("react"), 1);
11794
+ var SideBarContext = import_react44.default.createContext(null);
11283
11795
  var useSideBarContext = () => {
11284
- const ctx = import_react42.default.useContext(SideBarContext);
11796
+ const ctx = import_react44.default.useContext(SideBarContext);
11285
11797
  if (!ctx) throw new Error("Error");
11286
11798
  return ctx;
11287
11799
  };
11288
11800
  var SideBarContext_default = SideBarContext;
11289
11801
 
11290
11802
  // src/layout/SideBar/SideBar.tsx
11291
- var import_jsx_runtime358 = require("react/jsx-runtime");
11803
+ var import_jsx_runtime360 = require("react/jsx-runtime");
11292
11804
  var SideBar = (props) => {
11293
11805
  const { children, className } = props;
11294
- const [isOpen, setIsOpen] = import_react43.default.useState(true);
11806
+ const [isOpen, setIsOpen] = import_react45.default.useState(true);
11295
11807
  const handleSwitchSideBar = () => {
11296
11808
  setIsOpen((prev) => !prev);
11297
11809
  };
11298
- return /* @__PURE__ */ (0, import_jsx_runtime358.jsx)(
11810
+ return /* @__PURE__ */ (0, import_jsx_runtime360.jsx)(
11299
11811
  SideBarContext_default.Provider,
11300
11812
  {
11301
11813
  value: { isSidebarOpen: isOpen, handleSwitchSideBar },
11302
- children: /* @__PURE__ */ (0, import_jsx_runtime358.jsx)(
11814
+ children: /* @__PURE__ */ (0, import_jsx_runtime360.jsx)(
11303
11815
  "div",
11304
11816
  {
11305
11817
  className: clsx_default(
@@ -11607,6 +12119,7 @@ var SideBar_default = SideBar;
11607
12119
  Spinner,
11608
12120
  SquareIcon,
11609
12121
  StarIcon,
12122
+ Stat,
11610
12123
  Steps,
11611
12124
  StopCircleIcon,
11612
12125
  SuccessIcon,
@@ -11631,6 +12144,7 @@ var SideBar_default = SideBar;
11631
12144
  ThermometerIcon,
11632
12145
  ThumbsDownIcon,
11633
12146
  ThumbsUpIcon,
12147
+ TimePicker,
11634
12148
  ToastProvider,
11635
12149
  ToggleLeftIcon,
11636
12150
  ToggleRightIcon,