@x-plat/design-system 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/dist/components/AutoResizeTextArea/index.cjs +14 -5
  2. package/dist/components/AutoResizeTextArea/index.css +15 -0
  3. package/dist/components/AutoResizeTextArea/index.d.cts +5 -0
  4. package/dist/components/AutoResizeTextArea/index.d.ts +5 -0
  5. package/dist/components/AutoResizeTextArea/index.js +14 -5
  6. package/dist/components/Badge/index.cjs +5 -1
  7. package/dist/components/Badge/index.css +1 -0
  8. package/dist/components/Badge/index.d.cts +1 -0
  9. package/dist/components/Badge/index.d.ts +1 -0
  10. package/dist/components/Badge/index.js +5 -1
  11. package/dist/components/Box/index.d.cts +3 -0
  12. package/dist/components/Box/index.d.ts +3 -0
  13. package/dist/components/Chart/index.cjs +7 -6
  14. package/dist/components/Chart/index.d.cts +12 -1
  15. package/dist/components/Chart/index.d.ts +12 -1
  16. package/dist/components/Chart/index.js +7 -6
  17. package/dist/components/ChatInput/index.cjs +20 -7
  18. package/dist/components/ChatInput/index.css +15 -0
  19. package/dist/components/ChatInput/index.d.cts +10 -0
  20. package/dist/components/ChatInput/index.d.ts +10 -0
  21. package/dist/components/ChatInput/index.js +20 -7
  22. package/dist/components/CheckBox/index.cjs +14 -5
  23. package/dist/components/CheckBox/index.css +17 -0
  24. package/dist/components/CheckBox/index.d.cts +10 -2
  25. package/dist/components/CheckBox/index.d.ts +10 -2
  26. package/dist/components/CheckBox/index.js +14 -5
  27. package/dist/components/Chip/index.d.cts +2 -0
  28. package/dist/components/Chip/index.d.ts +2 -0
  29. package/dist/components/DatePicker/index.cjs +181 -65
  30. package/dist/components/DatePicker/index.css +19 -0
  31. package/dist/components/DatePicker/index.js +181 -65
  32. package/dist/components/Drawer/index.cjs +83 -4
  33. package/dist/components/Drawer/index.d.cts +1 -0
  34. package/dist/components/Drawer/index.d.ts +1 -0
  35. package/dist/components/Drawer/index.js +83 -4
  36. package/dist/components/Dropdown/index.cjs +35 -7
  37. package/dist/components/Dropdown/index.js +35 -7
  38. package/dist/components/Editor/index.cjs +178 -21
  39. package/dist/components/Editor/index.js +178 -21
  40. package/dist/components/FieldMessage/index.cjs +8 -3
  41. package/dist/components/FieldMessage/index.css +15 -0
  42. package/dist/components/FieldMessage/index.d.cts +11 -4
  43. package/dist/components/FieldMessage/index.d.ts +11 -4
  44. package/dist/components/FieldMessage/index.js +8 -3
  45. package/dist/components/FileUpload/index.cjs +8 -3
  46. package/dist/components/FileUpload/index.css +15 -0
  47. package/dist/components/FileUpload/index.d.cts +6 -0
  48. package/dist/components/FileUpload/index.d.ts +6 -0
  49. package/dist/components/FileUpload/index.js +8 -3
  50. package/dist/components/ImageSelector/index.cjs +8 -3
  51. package/dist/components/ImageSelector/index.css +15 -0
  52. package/dist/components/ImageSelector/index.d.cts +3 -0
  53. package/dist/components/ImageSelector/index.d.ts +3 -0
  54. package/dist/components/ImageSelector/index.js +8 -3
  55. package/dist/components/Input/index.cjs +15 -5
  56. package/dist/components/Input/index.css +15 -0
  57. package/dist/components/Input/index.d.cts +8 -0
  58. package/dist/components/Input/index.d.ts +8 -0
  59. package/dist/components/Input/index.js +15 -5
  60. package/dist/components/Modal/index.cjs +84 -5
  61. package/dist/components/Modal/index.js +84 -5
  62. package/dist/components/NotificationBadge/index.cjs +5 -1
  63. package/dist/components/NotificationBadge/index.css +1 -0
  64. package/dist/components/NotificationBadge/index.d.cts +6 -2
  65. package/dist/components/NotificationBadge/index.d.ts +6 -2
  66. package/dist/components/NotificationBadge/index.js +5 -1
  67. package/dist/components/Pagination/index.cjs +6 -2
  68. package/dist/components/Pagination/index.css +1 -0
  69. package/dist/components/Pagination/index.d.cts +13 -2
  70. package/dist/components/Pagination/index.d.ts +13 -2
  71. package/dist/components/Pagination/index.js +6 -2
  72. package/dist/components/PopOver/index.cjs +34 -6
  73. package/dist/components/PopOver/index.js +34 -6
  74. package/dist/components/Progress/index.cjs +6 -2
  75. package/dist/components/Progress/index.css +1 -0
  76. package/dist/components/Progress/index.d.cts +11 -2
  77. package/dist/components/Progress/index.d.ts +11 -2
  78. package/dist/components/Progress/index.js +6 -2
  79. package/dist/components/Radio/index.cjs +14 -5
  80. package/dist/components/Radio/index.css +17 -0
  81. package/dist/components/Radio/index.d.cts +11 -2
  82. package/dist/components/Radio/index.d.ts +11 -2
  83. package/dist/components/Radio/index.js +14 -5
  84. package/dist/components/Select/index.cjs +99 -31
  85. package/dist/components/Select/index.css +54 -0
  86. package/dist/components/Select/index.d.cts +16 -1
  87. package/dist/components/Select/index.d.ts +16 -1
  88. package/dist/components/Select/index.js +99 -31
  89. package/dist/components/Skeleton/index.d.cts +3 -0
  90. package/dist/components/Skeleton/index.d.ts +3 -0
  91. package/dist/components/Spinner/index.cjs +6 -2
  92. package/dist/components/Spinner/index.css +1 -0
  93. package/dist/components/Spinner/index.d.cts +8 -2
  94. package/dist/components/Spinner/index.d.ts +8 -2
  95. package/dist/components/Spinner/index.js +6 -2
  96. package/dist/components/Stat/index.cjs +84 -0
  97. package/dist/components/Stat/index.css +96 -0
  98. package/dist/components/Stat/index.d.cts +37 -0
  99. package/dist/components/Stat/index.d.ts +37 -0
  100. package/dist/components/Stat/index.js +57 -0
  101. package/dist/components/Steps/index.cjs +6 -2
  102. package/dist/components/Steps/index.css +11 -0
  103. package/dist/components/Steps/index.d.cts +9 -2
  104. package/dist/components/Steps/index.d.ts +9 -2
  105. package/dist/components/Steps/index.js +6 -2
  106. package/dist/components/Switch/index.cjs +20 -7
  107. package/dist/components/Switch/index.css +17 -0
  108. package/dist/components/Switch/index.d.cts +15 -2
  109. package/dist/components/Switch/index.d.ts +15 -2
  110. package/dist/components/Switch/index.js +20 -7
  111. package/dist/components/Tab/index.cjs +51 -26
  112. package/dist/components/Tab/index.css +4 -0
  113. package/dist/components/Tab/index.d.cts +12 -1
  114. package/dist/components/Tab/index.d.ts +12 -1
  115. package/dist/components/Tab/index.js +51 -26
  116. package/dist/components/Tag/index.cjs +5 -3
  117. package/dist/components/Tag/index.d.cts +12 -2
  118. package/dist/components/Tag/index.d.ts +12 -2
  119. package/dist/components/Tag/index.js +5 -3
  120. package/dist/components/TextArea/index.cjs +14 -4
  121. package/dist/components/TextArea/index.css +15 -0
  122. package/dist/components/TextArea/index.d.cts +7 -0
  123. package/dist/components/TextArea/index.d.ts +7 -0
  124. package/dist/components/TextArea/index.js +14 -4
  125. package/dist/components/TimePicker/index.cjs +448 -0
  126. package/dist/components/TimePicker/index.css +172 -0
  127. package/dist/components/TimePicker/index.d.cts +42 -0
  128. package/dist/components/TimePicker/index.d.ts +42 -0
  129. package/dist/components/TimePicker/index.js +411 -0
  130. package/dist/components/Tooltip/index.cjs +4 -2
  131. package/dist/components/Tooltip/index.d.cts +11 -1
  132. package/dist/components/Tooltip/index.d.ts +11 -1
  133. package/dist/components/Tooltip/index.js +4 -2
  134. package/dist/components/index.cjs +916 -385
  135. package/dist/components/index.css +296 -0
  136. package/dist/components/index.d.cts +3 -0
  137. package/dist/components/index.d.ts +3 -0
  138. package/dist/components/index.js +914 -385
  139. package/dist/index.cjs +940 -409
  140. package/dist/index.css +296 -0
  141. package/dist/index.d.cts +3 -0
  142. package/dist/index.d.ts +3 -0
  143. package/dist/index.js +938 -409
  144. package/dist/status-njWqQWFV.d.cts +20 -0
  145. package/dist/status-njWqQWFV.d.ts +20 -0
  146. package/guidelines/AGENT_PROMPT.md +18 -3
  147. package/guidelines/Guidelines.md +3 -0
  148. package/guidelines/components/card.md +3 -3
  149. package/guidelines/components/editor.md +86 -0
  150. package/guidelines/components/feedback.md +1 -1
  151. package/guidelines/components/form.md +19 -0
  152. package/guidelines/components/navigation.md +16 -15
  153. package/guidelines/components/overlay.md +43 -4
  154. package/guidelines/components/stat.md +31 -0
  155. package/guidelines/components/time-picker.md +49 -0
  156. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -5622,11 +5622,16 @@ var FieldMessage = (props) => {
5622
5622
  FieldMessage.displayName = "FieldMessage";
5623
5623
  var FieldMessage_default = FieldMessage;
5624
5624
  var Field = (props) => {
5625
- const { validations, children } = props;
5626
- if (!validations || validations.length === 0) return /* @__PURE__ */ jsx297(Fragment, { children });
5625
+ const { label, required = false, htmlFor, validations, children } = props;
5626
+ const hasMessages = !!validations && validations.length > 0;
5627
+ if (!label && !hasMessages) return /* @__PURE__ */ jsx297(Fragment, { children });
5627
5628
  return /* @__PURE__ */ jsxs191("div", { className: "lib-xplat-field", children: [
5629
+ label && /* @__PURE__ */ jsxs191("label", { className: "lib-xplat-field-label", htmlFor, children: [
5630
+ label,
5631
+ required && /* @__PURE__ */ jsx297("span", { className: "required", "aria-hidden": "true", children: "*" })
5632
+ ] }),
5628
5633
  children,
5629
- /* @__PURE__ */ jsx297(FieldMessage, { validations })
5634
+ hasMessages && /* @__PURE__ */ jsx297(FieldMessage, { validations })
5630
5635
  ] });
5631
5636
  };
5632
5637
  Field.displayName = "Field";
@@ -5637,7 +5642,9 @@ import { jsx as jsx298 } from "react/jsx-runtime";
5637
5642
  var MAX_HEIGHT = 400;
5638
5643
  var AutoResizeTextArea = React2.forwardRef(
5639
5644
  (props, ref) => {
5640
- const { value, className, onChange, disabled, bare = false, validations, ...textareaProps } = props;
5645
+ const { value, className, onChange, disabled, bare = false, validations, label, required, ...textareaProps } = props;
5646
+ const autoId = React2.useId();
5647
+ const fieldId = props.id ?? autoId;
5641
5648
  const localRef = React2.useRef(null);
5642
5649
  const setRefs = (el) => {
5643
5650
  localRef.current = el;
@@ -5671,6 +5678,7 @@ var AutoResizeTextArea = React2.forwardRef(
5671
5678
  "aria-invalid": hasError(validations) || void 0,
5672
5679
  ...textareaProps,
5673
5680
  ref: setRefs,
5681
+ id: fieldId,
5674
5682
  className,
5675
5683
  disabled,
5676
5684
  value,
@@ -5684,12 +5692,13 @@ var AutoResizeTextArea = React2.forwardRef(
5684
5692
  "aria-invalid": hasError(validations) || void 0,
5685
5693
  ...textareaProps,
5686
5694
  ref: setRefs,
5695
+ id: fieldId,
5687
5696
  disabled,
5688
5697
  value,
5689
5698
  onChange: handleChange
5690
5699
  }
5691
5700
  ) }) });
5692
- return /* @__PURE__ */ jsx298(Field, { validations, children: control });
5701
+ return /* @__PURE__ */ jsx298(Field, { validations, label, required, htmlFor: fieldId, children: control });
5693
5702
  }
5694
5703
  );
5695
5704
  AutoResizeTextArea.displayName = "AutoResizeTextArea";
@@ -6848,7 +6857,8 @@ var ChartLegend = ({ data, labels, type }) => {
6848
6857
  }) });
6849
6858
  };
6850
6859
  var Chart = React6.memo((props) => {
6851
- const { type, data, labels, tooltip: showTooltip = true, tooltipType = "light" } = props;
6860
+ const { variant, type, data, labels, tooltip: showTooltip = true, tooltipType = "light" } = props;
6861
+ const shape = variant ?? type ?? "line";
6852
6862
  const { tooltip, show, hide, move, containerRef } = useChartTooltip(showTooltip);
6853
6863
  const { width, height } = useChartSize(containerRef);
6854
6864
  const stableData = React6.useMemo(() => data, [JSON.stringify(data)]);
@@ -6857,11 +6867,11 @@ var Chart = React6.memo((props) => {
6857
6867
  const animate = useChartAnimation(containerRef, dataKey);
6858
6868
  const ready = width > 0 && height > 0;
6859
6869
  return /* @__PURE__ */ jsxs196("div", { className: "lib-xplat-chart", ref: containerRef, children: [
6860
- ready && type === "line" && /* @__PURE__ */ jsx306(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6861
- ready && type === "curve" && /* @__PURE__ */ jsx306(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6862
- ready && type === "bar" && /* @__PURE__ */ jsx306(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6863
- ready && type === "pie" && /* @__PURE__ */ jsx306(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6864
- ready && type === "doughnut" && /* @__PURE__ */ jsx306(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
6870
+ ready && shape === "line" && /* @__PURE__ */ jsx306(LineChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6871
+ ready && shape === "curve" && /* @__PURE__ */ jsx306(CurveChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6872
+ ready && shape === "bar" && /* @__PURE__ */ jsx306(BarChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6873
+ ready && shape === "pie" && /* @__PURE__ */ jsx306(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, onHover: show, onMove: move, onLeave: hide }),
6874
+ ready && shape === "doughnut" && /* @__PURE__ */ jsx306(PieDonutChart, { data: stableData, labels: stableLabels, width, height, animate, isDoughnut: true, onHover: show, onMove: move, onLeave: hide }),
6865
6875
  ready && (type === "pie" || type === "doughnut") && /* @__PURE__ */ jsx306(ChartLegend, { data: stableData, labels: stableLabels, type }),
6866
6876
  tooltip.visible && tooltip.content && /* @__PURE__ */ jsx306(ChartTooltip, { x: tooltip.x, y: tooltip.y, containerWidth: width, containerHeight: height, tooltipType, children: tooltip.content })
6867
6877
  ] });
@@ -6906,8 +6916,11 @@ var ChatInput = React7.forwardRef(
6906
6916
  buttonType = "primary",
6907
6917
  onSubmit,
6908
6918
  onChange,
6909
- validations
6919
+ validations,
6920
+ label,
6921
+ required
6910
6922
  } = props;
6923
+ const fieldId = React7.useId();
6911
6924
  const isControlled = valueProp !== void 0;
6912
6925
  const [internalValue, setInternalValue] = React7.useState("");
6913
6926
  const value = isControlled ? valueProp : internalValue;
@@ -6932,6 +6945,7 @@ var ChatInput = React7.forwardRef(
6932
6945
  /* @__PURE__ */ jsx308(
6933
6946
  AutoResizeTextArea_default,
6934
6947
  {
6948
+ id: fieldId,
6935
6949
  ref,
6936
6950
  bare: true,
6937
6951
  className: "chat-input-textarea",
@@ -6956,7 +6970,7 @@ var ChatInput = React7.forwardRef(
6956
6970
  }
6957
6971
  )
6958
6972
  ] });
6959
- return /* @__PURE__ */ jsx308(Field, { validations, children: control });
6973
+ return /* @__PURE__ */ jsx308(Field, { validations, label, required, htmlFor: fieldId, children: control });
6960
6974
  }
6961
6975
  );
6962
6976
  ChatInput.displayName = "ChatInput";
@@ -6981,6 +6995,9 @@ import { semantic } from "@x-plat/tokens-core";
6981
6995
  // src/tokens/index.ts
6982
6996
  import { cssVar } from "@x-plat/tokens-core";
6983
6997
 
6998
+ // src/tokens/interface/status.ts
6999
+ var normalizeStatus = (value) => value === "brand" ? "primary" : value;
7000
+
6984
7001
  // src/components/CheckBox/CheckBox.tsx
6985
7002
  import { jsx as jsx309, jsxs as jsxs198 } from "react/jsx-runtime";
6986
7003
  var CheckBox = (props) => {
@@ -6991,10 +7008,11 @@ var CheckBox = (props) => {
6991
7008
  onChange,
6992
7009
  disabled,
6993
7010
  size = "md",
6994
- type = "brand",
7011
+ type = "primary",
6995
7012
  validations,
6996
7013
  ...rest
6997
7014
  } = props;
7015
+ const statusType = normalizeStatus(type);
6998
7016
  const handleChange = (e) => {
6999
7017
  if (onChange) onChange(e);
7000
7018
  };
@@ -7002,7 +7020,7 @@ var CheckBox = (props) => {
7002
7020
  const checkedClasses = `checked`;
7003
7021
  const disabledClasses = "disabled";
7004
7022
  const boxClasses = disabled ? disabledClasses : checked ? checkedClasses : uncheckedClasses;
7005
- const control = /* @__PURE__ */ jsxs198("label", { className: clsx_default("lib-xplat-checkbox", size, type, className), children: [
7023
+ const control = /* @__PURE__ */ jsxs198("label", { className: clsx_default("lib-xplat-checkbox", size, statusType, className), children: [
7006
7024
  /* @__PURE__ */ jsx309(
7007
7025
  "input",
7008
7026
  {
@@ -7036,7 +7054,7 @@ Chip.displayName = "Chip";
7036
7054
  var Chip_default = Chip;
7037
7055
 
7038
7056
  // src/components/DatePicker/InputDatePicker/index.tsx
7039
- import React12 from "react";
7057
+ import React13 from "react";
7040
7058
 
7041
7059
  // src/components/Input/Input.tsx
7042
7060
  import React8 from "react";
@@ -7134,8 +7152,12 @@ var Input = React8.forwardRef((props, ref) => {
7134
7152
  suffix,
7135
7153
  disabled,
7136
7154
  validations,
7155
+ label,
7156
+ required,
7137
7157
  ...inputProps
7138
7158
  } = props;
7159
+ const autoId = React8.useId();
7160
+ const fieldId = inputProps.id ?? autoId;
7139
7161
  const localValue = formatValue(type, value);
7140
7162
  const handleChange = (e) => {
7141
7163
  let val = e.target.value;
@@ -7151,7 +7173,7 @@ var Input = React8.forwardRef((props, ref) => {
7151
7173
  onChange(event);
7152
7174
  }
7153
7175
  };
7154
- return /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
7176
+ return /* @__PURE__ */ jsx311(Field, { label, required, htmlFor: fieldId, children: /* @__PURE__ */ jsxs199("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
7155
7177
  /* @__PURE__ */ jsxs199(
7156
7178
  "div",
7157
7179
  {
@@ -7162,6 +7184,7 @@ var Input = React8.forwardRef((props, ref) => {
7162
7184
  {
7163
7185
  ...inputProps,
7164
7186
  ref,
7187
+ id: fieldId,
7165
7188
  disabled,
7166
7189
  type: type === "number" ? "text" : type,
7167
7190
  value: localValue,
@@ -7174,7 +7197,7 @@ var Input = React8.forwardRef((props, ref) => {
7174
7197
  }
7175
7198
  ),
7176
7199
  /* @__PURE__ */ jsx311(FieldMessage_default, { validations })
7177
- ] });
7200
+ ] }) });
7178
7201
  });
7179
7202
  Input.displayName = "Input";
7180
7203
  var Input_default = Input;
@@ -7204,16 +7227,96 @@ PasswordInput.displayName = "PasswordInput";
7204
7227
  var PasswordInput_default = PasswordInput;
7205
7228
 
7206
7229
  // src/components/Modal/Modal.tsx
7207
- import React10 from "react";
7230
+ import React11 from "react";
7208
7231
  import { createPortal } from "react-dom";
7232
+
7233
+ // src/tokens/hooks/useOverlayKeyboard.ts
7234
+ import React10 from "react";
7235
+ var FOCUSABLE = [
7236
+ "a[href]",
7237
+ "button:not([disabled])",
7238
+ "input:not([disabled]):not([type='hidden'])",
7239
+ "select:not([disabled])",
7240
+ "textarea:not([disabled])",
7241
+ "[tabindex]:not([tabindex='-1'])"
7242
+ ].join(",");
7243
+ var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
7244
+ // 화면에 없는 것은 제외 (display:none 등)
7245
+ (n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
7246
+ );
7247
+ var useEscapeKey = (enabled, onEscape) => {
7248
+ React10.useEffect(() => {
7249
+ if (!enabled) return;
7250
+ const onKey = (e) => {
7251
+ if (e.key !== "Escape") return;
7252
+ if (e.defaultPrevented) return;
7253
+ e.preventDefault();
7254
+ onEscape();
7255
+ };
7256
+ document.addEventListener("keydown", onKey);
7257
+ return () => document.removeEventListener("keydown", onKey);
7258
+ }, [enabled, onEscape]);
7259
+ };
7260
+ var useFocusTrap = (containerRef, enabled, options = {}) => {
7261
+ const { trap = false, initialFocus } = options;
7262
+ const restoreRef = React10.useRef(null);
7263
+ React10.useEffect(() => {
7264
+ if (!enabled) return;
7265
+ restoreRef.current = document.activeElement;
7266
+ const raf = requestAnimationFrame(() => {
7267
+ const el = containerRef.current;
7268
+ if (!el) return;
7269
+ const target = initialFocus?.current ?? focusableIn(el)[0] ?? el;
7270
+ if (!target.hasAttribute("tabindex") && !focusableIn(el).includes(target)) {
7271
+ target.setAttribute("tabindex", "-1");
7272
+ }
7273
+ target.focus({ preventScroll: true });
7274
+ });
7275
+ return () => {
7276
+ cancelAnimationFrame(raf);
7277
+ const prev = restoreRef.current;
7278
+ if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
7279
+ };
7280
+ }, [enabled, containerRef, initialFocus]);
7281
+ React10.useEffect(() => {
7282
+ if (!enabled || !trap) return;
7283
+ const onKey = (e) => {
7284
+ if (e.key !== "Tab") return;
7285
+ const el = containerRef.current;
7286
+ if (!el) return;
7287
+ const items = focusableIn(el);
7288
+ if (items.length === 0) {
7289
+ e.preventDefault();
7290
+ return;
7291
+ }
7292
+ const first = items[0];
7293
+ const last = items[items.length - 1];
7294
+ const active = document.activeElement;
7295
+ if (e.shiftKey && (active === first || !el.contains(active))) {
7296
+ e.preventDefault();
7297
+ last.focus();
7298
+ } else if (!e.shiftKey && (active === last || !el.contains(active))) {
7299
+ e.preventDefault();
7300
+ first.focus();
7301
+ }
7302
+ };
7303
+ document.addEventListener("keydown", onKey);
7304
+ return () => document.removeEventListener("keydown", onKey);
7305
+ }, [enabled, trap, containerRef]);
7306
+ };
7307
+
7308
+ // src/components/Modal/Modal.tsx
7209
7309
  import { jsx as jsx313 } from "react/jsx-runtime";
7210
7310
  var ANIMATION_DURATION_MS = 200;
7211
7311
  var Modal = (props) => {
7212
7312
  const { isOpen, onClose, children } = props;
7213
- const [mounted, setMounted] = React10.useState(false);
7214
- const [visible, setVisible] = React10.useState(false);
7215
- const [settled, setSettled] = React10.useState(false);
7216
- React10.useEffect(() => {
7313
+ const [mounted, setMounted] = React11.useState(false);
7314
+ const [visible, setVisible] = React11.useState(false);
7315
+ const [settled, setSettled] = React11.useState(false);
7316
+ const boxRef = React11.useRef(null);
7317
+ useEscapeKey(isOpen, onClose);
7318
+ useFocusTrap(boxRef, isOpen && mounted, { trap: true });
7319
+ React11.useEffect(() => {
7217
7320
  if (isOpen) {
7218
7321
  setMounted(true);
7219
7322
  const show = setTimeout(() => setVisible(true), 1);
@@ -7240,6 +7343,7 @@ var Modal = (props) => {
7240
7343
  children: /* @__PURE__ */ jsx313(
7241
7344
  "div",
7242
7345
  {
7346
+ ref: boxRef,
7243
7347
  className: clsx_default("lib-xplat-modal", "modal-box", stateClass, settled && "settled"),
7244
7348
  role: "dialog",
7245
7349
  "aria-modal": "true",
@@ -7256,9 +7360,9 @@ Modal.displayName = "Modal";
7256
7360
  var Modal_default = Modal;
7257
7361
 
7258
7362
  // src/components/DatePicker/SingleDatePicker/index.tsx
7259
- import React11 from "react";
7363
+ import React12 from "react";
7260
7364
  import { Fragment as Fragment4, jsx as jsx314, jsxs as jsxs200 } from "react/jsx-runtime";
7261
- var DayCell2 = React11.memo(
7365
+ var DayCell2 = React12.memo(
7262
7366
  ({
7263
7367
  day,
7264
7368
  disabled,
@@ -7310,26 +7414,26 @@ var SingleDatePicker = (props) => {
7310
7414
  initialYear,
7311
7415
  initialMonth
7312
7416
  );
7313
- const [pickerMode, setPickerMode] = React11.useState("days");
7314
- const [yearRangeStart, setYearRangeStart] = React11.useState(
7417
+ const [pickerMode, setPickerMode] = React12.useState("days");
7418
+ const [yearRangeStart, setYearRangeStart] = React12.useState(
7315
7419
  Math.floor((initialYear ?? (/* @__PURE__ */ new Date()).getFullYear()) / 12) * 12
7316
7420
  );
7317
- const minTime = React11.useMemo(
7421
+ const minTime = React12.useMemo(
7318
7422
  () => minDate ? new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate()).getTime() : -Infinity,
7319
7423
  [minDate]
7320
7424
  );
7321
- const maxTime = React11.useMemo(
7425
+ const maxTime = React12.useMemo(
7322
7426
  () => maxDate ? new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate()).getTime() : Infinity,
7323
7427
  [maxDate]
7324
7428
  );
7325
- const highlightSet = React11.useMemo(() => {
7429
+ const highlightSet = React12.useMemo(() => {
7326
7430
  const set = /* @__PURE__ */ new Set();
7327
7431
  for (const h of highlightDates) {
7328
7432
  set.add(`${h.getFullYear()}-${h.getMonth()}-${h.getDate()}`);
7329
7433
  }
7330
7434
  return set;
7331
7435
  }, [highlightDates]);
7332
- const handleSelect = React11.useCallback(
7436
+ const handleSelect = React12.useCallback(
7333
7437
  (date) => {
7334
7438
  onChange?.(date);
7335
7439
  },
@@ -7458,8 +7562,8 @@ var formatDate = (date) => {
7458
7562
  };
7459
7563
  var InputDatePicker = (props) => {
7460
7564
  const { value, onChange, minDate, maxDate, disabled, locale = "ko", placeholder } = props;
7461
- const [isOpen, setIsOpen] = React12.useState(false);
7462
- const [tempDate, setTempDate] = React12.useState(value ?? /* @__PURE__ */ new Date());
7565
+ const [isOpen, setIsOpen] = React13.useState(false);
7566
+ const [tempDate, setTempDate] = React13.useState(value ?? /* @__PURE__ */ new Date());
7463
7567
  const handleOpen = () => {
7464
7568
  if (disabled) return;
7465
7569
  setTempDate(value ?? /* @__PURE__ */ new Date());
@@ -7508,23 +7612,27 @@ InputDatePicker.displayName = "InputDatePicker";
7508
7612
  var InputDatePicker_default = InputDatePicker;
7509
7613
 
7510
7614
  // src/components/DatePicker/PopupPicker/index.tsx
7511
- import React16 from "react";
7615
+ import React17 from "react";
7512
7616
 
7513
7617
  // src/components/DatePicker/RangePicker/index.tsx
7514
- import React15 from "react";
7618
+ import React16 from "react";
7515
7619
 
7516
7620
  // src/components/Tab/Tab.tsx
7517
- import React14 from "react";
7621
+ import React15 from "react";
7518
7622
 
7519
7623
  // src/components/Tab/TabItem.tsx
7520
- import React13 from "react";
7624
+ import React14 from "react";
7521
7625
  import { jsx as jsx316 } from "react/jsx-runtime";
7522
- var TabItem = React13.forwardRef((props, ref) => {
7626
+ var TabItem = React14.forwardRef((props, ref) => {
7523
7627
  const { isActive: isActive2, title, onClick } = props;
7524
7628
  return /* @__PURE__ */ jsx316(
7525
- "div",
7629
+ "button",
7526
7630
  {
7527
7631
  ref,
7632
+ type: "button",
7633
+ role: "tab",
7634
+ "aria-selected": isActive2,
7635
+ tabIndex: isActive2 ? 0 : -1,
7528
7636
  className: clsx_default("tab-item", isActive2 ? "active" : null),
7529
7637
  onClick,
7530
7638
  children: title
@@ -7537,45 +7645,66 @@ var TabItem_default = TabItem;
7537
7645
  // src/components/Tab/Tab.tsx
7538
7646
  import { jsx as jsx317, jsxs as jsxs202 } from "react/jsx-runtime";
7539
7647
  var Tab = (props) => {
7540
- const { activeIndex, onChange, tabs, type, size = "md" } = props;
7541
- const [underlineStyle, setUnderlineStyle] = React14.useState({
7648
+ const { activeIndex, onChange, tabs, variant, type, size = "md" } = props;
7649
+ const shape = variant ?? type ?? "default";
7650
+ const [underlineStyle, setUnderlineStyle] = React15.useState({
7542
7651
  left: 0,
7543
7652
  width: 0
7544
7653
  });
7545
- const itemRefs = React14.useRef([]);
7654
+ const itemRefs = React15.useRef([]);
7655
+ const handleKeyDown = (e) => {
7656
+ const last = tabs.length - 1;
7657
+ let next = null;
7658
+ if (e.key === "ArrowRight") next = activeIndex >= last ? 0 : activeIndex + 1;
7659
+ else if (e.key === "ArrowLeft") next = activeIndex <= 0 ? last : activeIndex - 1;
7660
+ else if (e.key === "Home") next = 0;
7661
+ else if (e.key === "End") next = last;
7662
+ if (next === null) return;
7663
+ e.preventDefault();
7664
+ onChange(tabs[next], next);
7665
+ itemRefs.current[next]?.focus();
7666
+ };
7546
7667
  const handleChangeActiveTab = (tabItem, tabIdx) => {
7547
7668
  onChange(tabItem, tabIdx);
7548
7669
  };
7549
- React14.useEffect(() => {
7670
+ React15.useEffect(() => {
7550
7671
  const el = itemRefs.current[activeIndex];
7551
7672
  if (el) {
7552
7673
  setUnderlineStyle({ left: el.offsetLeft, width: el.offsetWidth });
7553
7674
  }
7554
7675
  }, [activeIndex, tabs.length]);
7555
- return /* @__PURE__ */ jsxs202("div", { className: clsx_default("lib-xplat-tab", `type-${type}`, size), children: [
7556
- tabs.map((tab, idx) => /* @__PURE__ */ jsx317(
7557
- TabItem_default,
7558
- {
7559
- onClick: () => handleChangeActiveTab(tab, idx),
7560
- isActive: activeIndex === idx,
7561
- ref: (el) => {
7562
- itemRefs.current[idx] = el;
7563
- },
7564
- title: tab.title
7565
- },
7566
- `${tab.value}_${idx}`
7567
- )),
7568
- type === "toggle" && /* @__PURE__ */ jsx317(
7569
- "div",
7570
- {
7571
- className: "tab-toggle-underline",
7572
- style: {
7573
- left: underlineStyle.left,
7574
- width: underlineStyle.width
7575
- }
7576
- }
7577
- )
7578
- ] });
7676
+ return /* @__PURE__ */ jsxs202(
7677
+ "div",
7678
+ {
7679
+ className: clsx_default("lib-xplat-tab", `type-${shape}`, size),
7680
+ role: "tablist",
7681
+ onKeyDown: handleKeyDown,
7682
+ children: [
7683
+ tabs.map((tab, idx) => /* @__PURE__ */ jsx317(
7684
+ TabItem_default,
7685
+ {
7686
+ onClick: () => handleChangeActiveTab(tab, idx),
7687
+ isActive: activeIndex === idx,
7688
+ ref: (el) => {
7689
+ itemRefs.current[idx] = el;
7690
+ },
7691
+ title: tab.title
7692
+ },
7693
+ `${tab.value}_${idx}`
7694
+ )),
7695
+ shape === "toggle" && /* @__PURE__ */ jsx317(
7696
+ "div",
7697
+ {
7698
+ className: "tab-toggle-underline",
7699
+ style: {
7700
+ left: underlineStyle.left,
7701
+ width: underlineStyle.width
7702
+ }
7703
+ }
7704
+ )
7705
+ ]
7706
+ }
7707
+ );
7579
7708
  };
7580
7709
  Tab.displayName = "Tab";
7581
7710
  var Tab_default = Tab;
@@ -7591,7 +7720,7 @@ var RangePicker = (props) => {
7591
7720
  maxDate,
7592
7721
  locale = "ko"
7593
7722
  } = props;
7594
- const [activeTab, setActiveTab] = React15.useState("start");
7723
+ const [activeTab, setActiveTab] = React16.useState("start");
7595
7724
  const handleStartChange = (date) => {
7596
7725
  if (!date) return;
7597
7726
  const newStart = date > endDate ? endDate : date;
@@ -7676,7 +7805,7 @@ var RangePicker_default = RangePicker;
7676
7805
  import { jsx as jsx319, jsxs as jsxs204 } from "react/jsx-runtime";
7677
7806
  var PopupPicker = (props) => {
7678
7807
  const { component, type, locale } = props;
7679
- const [isOpen, setIsOpen] = React16.useState(false);
7808
+ const [isOpen, setIsOpen] = React17.useState(false);
7680
7809
  const handleClick = () => setIsOpen(true);
7681
7810
  const handleClose = () => setIsOpen(false);
7682
7811
  const handleSingleChange = (date) => {
@@ -7685,7 +7814,7 @@ var PopupPicker = (props) => {
7685
7814
  handleClose();
7686
7815
  };
7687
7816
  return /* @__PURE__ */ jsxs204("div", { className: "lib-xplat-popup-datepicker", children: [
7688
- React16.cloneElement(component, { onClick: handleClick }),
7817
+ React17.cloneElement(component, { onClick: handleClick }),
7689
7818
  /* @__PURE__ */ jsx319(Modal_default, { isOpen, onClose: handleClose, children: /* @__PURE__ */ jsxs204("div", { className: clsx_default("lib-xplat-popup-datepicker-card", type === "range" && "range-mode"), children: [
7690
7819
  /* @__PURE__ */ jsxs204("div", { className: "popup-datepicker-content", children: [
7691
7820
  type === "single" && /* @__PURE__ */ jsx319(
@@ -7744,15 +7873,18 @@ Divider.displayName = "Divider";
7744
7873
  var Divider_default = Divider;
7745
7874
 
7746
7875
  // src/components/Drawer/Drawer.tsx
7747
- import React17 from "react";
7876
+ import React18 from "react";
7748
7877
  import { createPortal as createPortal2 } from "react-dom";
7749
7878
  import { jsx as jsx321, jsxs as jsxs205 } from "react/jsx-runtime";
7750
7879
  var ANIMATION_DURATION_MS2 = 250;
7751
7880
  var Drawer = (props) => {
7752
7881
  const { isOpen, onClose, placement = "right", size = "md", title, children } = props;
7753
- const [mounted, setMounted] = React17.useState(false);
7754
- const [visible, setVisible] = React17.useState(false);
7755
- React17.useEffect(() => {
7882
+ const [mounted, setMounted] = React18.useState(false);
7883
+ const [visible, setVisible] = React18.useState(false);
7884
+ const panelRef = React18.useRef(null);
7885
+ useEscapeKey(isOpen, onClose);
7886
+ useFocusTrap(panelRef, isOpen && mounted, { trap: true });
7887
+ React18.useEffect(() => {
7756
7888
  if (isOpen) {
7757
7889
  setMounted(true);
7758
7890
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -7774,6 +7906,7 @@ var Drawer = (props) => {
7774
7906
  children: /* @__PURE__ */ jsxs205(
7775
7907
  "div",
7776
7908
  {
7909
+ ref: panelRef,
7777
7910
  className: clsx_default("lib-xplat-drawer", placement, size, stateClass),
7778
7911
  role: "dialog",
7779
7912
  "aria-modal": "true",
@@ -7796,7 +7929,7 @@ Drawer.displayName = "Drawer";
7796
7929
  var Drawer_default = Drawer;
7797
7930
 
7798
7931
  // src/components/Dropdown/Dropdown.tsx
7799
- import React20 from "react";
7932
+ import React21 from "react";
7800
7933
 
7801
7934
  // src/tokens/hooks/Portal.tsx
7802
7935
  import ReactDOM from "react-dom";
@@ -7808,13 +7941,13 @@ Portal.displayName = "Portal";
7808
7941
  var Portal_default = Portal;
7809
7942
 
7810
7943
  // src/tokens/hooks/useAutoPosition.ts
7811
- import React18 from "react";
7944
+ import React19 from "react";
7812
7945
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7813
- const [position, setPosition] = React18.useState({
7946
+ const [position, setPosition] = React19.useState({
7814
7947
  position: {},
7815
7948
  direction: "bottom"
7816
7949
  });
7817
- const calculatePosition = React18.useCallback(() => {
7950
+ const calculatePosition = React19.useCallback(() => {
7818
7951
  if (!triggerRef.current || !popRef.current) return;
7819
7952
  const triggerRect = triggerRef.current.getBoundingClientRect();
7820
7953
  const popW = popRef.current.offsetWidth;
@@ -7841,13 +7974,13 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7841
7974
  direction
7842
7975
  });
7843
7976
  }, [triggerRef, popRef]);
7844
- React18.useLayoutEffect(() => {
7977
+ React19.useLayoutEffect(() => {
7845
7978
  if (!enabled) return;
7846
7979
  calculatePosition();
7847
7980
  const raf = requestAnimationFrame(calculatePosition);
7848
7981
  return () => cancelAnimationFrame(raf);
7849
7982
  }, [calculatePosition, enabled]);
7850
- React18.useEffect(() => {
7983
+ React19.useEffect(() => {
7851
7984
  if (!enabled || !popRef.current) return;
7852
7985
  const observer = new ResizeObserver(() => {
7853
7986
  calculatePosition();
@@ -7855,7 +7988,7 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7855
7988
  observer.observe(popRef.current);
7856
7989
  return () => observer.disconnect();
7857
7990
  }, [calculatePosition, enabled, popRef]);
7858
- React18.useEffect(() => {
7991
+ React19.useEffect(() => {
7859
7992
  if (!enabled) return;
7860
7993
  window.addEventListener("resize", calculatePosition);
7861
7994
  window.addEventListener("scroll", calculatePosition, true);
@@ -7869,9 +8002,9 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7869
8002
  var useAutoPosition_default = useAutoPosition;
7870
8003
 
7871
8004
  // src/tokens/hooks/useClickOutside.ts
7872
- import React19 from "react";
8005
+ import React20 from "react";
7873
8006
  var useClickOutside = (refs, handler, enabled = true) => {
7874
- React19.useEffect(() => {
8007
+ React20.useEffect(() => {
7875
8008
  if (!enabled) return;
7876
8009
  const refArray = Array.isArray(refs) ? refs : [refs];
7877
8010
  const listener = (event) => {
@@ -7897,14 +8030,18 @@ var useClickOutside_default = useClickOutside;
7897
8030
  import { jsx as jsx322, jsxs as jsxs206 } from "react/jsx-runtime";
7898
8031
  var Dropdown = (props) => {
7899
8032
  const { items, children } = props;
7900
- const [isOpen, setIsOpen] = React20.useState(false);
7901
- const [mounted, setMounted] = React20.useState(false);
7902
- const [visible, setVisible] = React20.useState(false);
7903
- const triggerRef = React20.useRef(null);
7904
- const menuRef = React20.useRef(null);
8033
+ const [isOpen, setIsOpen] = React21.useState(false);
8034
+ const [mounted, setMounted] = React21.useState(false);
8035
+ const [visible, setVisible] = React21.useState(false);
8036
+ const triggerRef = React21.useRef(null);
8037
+ const menuRef = React21.useRef(null);
7905
8038
  const { position, direction } = useAutoPosition_default(triggerRef, menuRef, mounted);
7906
8039
  useClickOutside_default([triggerRef, menuRef], () => setIsOpen(false), isOpen);
7907
- React20.useEffect(() => {
8040
+ useEscapeKey(isOpen, () => {
8041
+ setIsOpen(false);
8042
+ triggerRef.current?.focus({ preventScroll: true });
8043
+ });
8044
+ React21.useEffect(() => {
7908
8045
  if (isOpen) {
7909
8046
  setMounted(true);
7910
8047
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -7958,7 +8095,7 @@ Dropdown.displayName = "Dropdown";
7958
8095
  var Dropdown_default = Dropdown;
7959
8096
 
7960
8097
  // src/components/Editor/Editor.tsx
7961
- import React21 from "react";
8098
+ import React22 from "react";
7962
8099
  import { jsx as jsx323, jsxs as jsxs207 } from "react/jsx-runtime";
7963
8100
  var DEFAULT_TOOLBAR = [
7964
8101
  "bold",
@@ -8008,6 +8145,15 @@ var ALLOWED_ATTRS = {
8008
8145
  a: ["href", "target", "rel"],
8009
8146
  img: ["src", "alt"]
8010
8147
  };
8148
+ var DROP_WITH_CONTENT = /* @__PURE__ */ new Set([
8149
+ "script",
8150
+ "style",
8151
+ "noscript",
8152
+ "iframe",
8153
+ "object",
8154
+ "embed",
8155
+ "template"
8156
+ ]);
8011
8157
  var sanitizeHtml = (input) => {
8012
8158
  const doc = new DOMParser().parseFromString(`<div>${input}</div>`, "text/html");
8013
8159
  const root = doc.body.firstElementChild;
@@ -8016,6 +8162,10 @@ var sanitizeHtml = (input) => {
8016
8162
  const children = Array.from(node.children);
8017
8163
  for (const child of children) {
8018
8164
  const tag = child.tagName.toLowerCase();
8165
+ if (DROP_WITH_CONTENT.has(tag)) {
8166
+ node.removeChild(child);
8167
+ continue;
8168
+ }
8019
8169
  if (!ALLOWED_TAGS.has(tag)) {
8020
8170
  while (child.firstChild) node.insertBefore(child.firstChild, child);
8021
8171
  node.removeChild(child);
@@ -8066,26 +8216,30 @@ var Editor = (props) => {
8066
8216
  onImageUpload,
8067
8217
  minHeight = 200
8068
8218
  } = props;
8069
- const editorRef = React21.useRef(null);
8070
- const lastRangeRef = React21.useRef(null);
8071
- const composingRef = React21.useRef(false);
8072
- const [isFocused, setIsFocused] = React21.useState(false);
8073
- const [isEmpty, setIsEmpty] = React21.useState(!value);
8074
- const [activeFormats, setActiveFormats] = React21.useState(/* @__PURE__ */ new Set());
8075
- const [slashOpen, setSlashOpen] = React21.useState(false);
8076
- const [slashFilter, setSlashFilter] = React21.useState("");
8077
- const [slashIdx, setSlashIdx] = React21.useState(0);
8078
- const [slashPos, setSlashPos] = React21.useState({ top: 0, left: 0 });
8079
- const slashStartRangeRef = React21.useRef(null);
8080
- const [linkOpen, setLinkOpen] = React21.useState(false);
8081
- const [linkValue, setLinkValue] = React21.useState("");
8082
- const [linkPos, setLinkPos] = React21.useState({ top: 0, left: 0 });
8083
- React21.useEffect(() => {
8084
- if (!editorRef.current) return;
8085
- if (editorRef.current.innerHTML !== value) {
8086
- editorRef.current.innerHTML = sanitizeHtml(value || "");
8087
- updateEmpty();
8088
- }
8219
+ const editorRef = React22.useRef(null);
8220
+ const lastRangeRef = React22.useRef(null);
8221
+ const composingRef = React22.useRef(false);
8222
+ const [isFocused, setIsFocused] = React22.useState(false);
8223
+ const [isEmpty, setIsEmpty] = React22.useState(!value);
8224
+ const [activeFormats, setActiveFormats] = React22.useState(/* @__PURE__ */ new Set());
8225
+ const [slashOpen, setSlashOpen] = React22.useState(false);
8226
+ const [slashFilter, setSlashFilter] = React22.useState("");
8227
+ const [slashIdx, setSlashIdx] = React22.useState(0);
8228
+ const [slashPos, setSlashPos] = React22.useState({ top: 0, left: 0 });
8229
+ const slashStartRangeRef = React22.useRef(null);
8230
+ const [linkOpen, setLinkOpen] = React22.useState(false);
8231
+ const [linkValue, setLinkValue] = React22.useState("");
8232
+ const [linkPos, setLinkPos] = React22.useState({ top: 0, left: 0 });
8233
+ const lastEmittedRef = React22.useRef(null);
8234
+ React22.useEffect(() => {
8235
+ const el = editorRef.current;
8236
+ if (!el) return;
8237
+ if (value === lastEmittedRef.current) return;
8238
+ if (el.innerHTML === value) return;
8239
+ el.innerHTML = sanitizeHtml(value || "");
8240
+ if (!el.firstChild) el.innerHTML = "<p><br></p>";
8241
+ lastEmittedRef.current = null;
8242
+ updateEmpty();
8089
8243
  }, [value]);
8090
8244
  const updateEmpty = () => {
8091
8245
  const el = editorRef.current;
@@ -8101,10 +8255,19 @@ var Editor = (props) => {
8101
8255
  }
8102
8256
  };
8103
8257
  const restoreSelection = () => {
8104
- if (!lastRangeRef.current) return;
8258
+ const range = lastRangeRef.current;
8259
+ if (!range) return;
8260
+ if (!editorRef.current?.contains(range.startContainer)) {
8261
+ lastRangeRef.current = null;
8262
+ return;
8263
+ }
8105
8264
  const sel = window.getSelection();
8106
- sel?.removeAllRanges();
8107
- sel?.addRange(lastRangeRef.current);
8265
+ try {
8266
+ sel?.removeAllRanges();
8267
+ sel?.addRange(range);
8268
+ } catch {
8269
+ lastRangeRef.current = null;
8270
+ }
8108
8271
  };
8109
8272
  const updateActiveFormats = () => {
8110
8273
  if (!editorRef.current) return;
@@ -8133,6 +8296,96 @@ var Editor = (props) => {
8133
8296
  const setBlock = (tag) => {
8134
8297
  exec("formatBlock", tag);
8135
8298
  };
8299
+ const closestPre = () => {
8300
+ const sel = window.getSelection();
8301
+ const node = sel?.anchorNode;
8302
+ if (!node || !editorRef.current?.contains(node)) return null;
8303
+ const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
8304
+ return el?.closest("pre") ?? null;
8305
+ };
8306
+ const insertCodeBlock = () => {
8307
+ const el = editorRef.current;
8308
+ const sel = window.getSelection();
8309
+ if (!el || !sel || sel.rangeCount === 0) return;
8310
+ const existing = closestPre();
8311
+ if (existing) {
8312
+ const p = document.createElement("p");
8313
+ p.textContent = existing.textContent || "";
8314
+ if (!p.textContent) p.innerHTML = "<br>";
8315
+ existing.replaceWith(p);
8316
+ placeCaretAtEnd(p);
8317
+ handleInput();
8318
+ return;
8319
+ }
8320
+ const range = sel.getRangeAt(0);
8321
+ const frag = range.cloneContents();
8322
+ const holder = document.createElement("div");
8323
+ holder.appendChild(frag);
8324
+ const BLOCK = /^(p|div|h[1-6]|li|blockquote|pre|tr)$/i;
8325
+ const linesOf = (node) => {
8326
+ const out = [];
8327
+ let cur = "";
8328
+ for (const child of Array.from(node.childNodes)) {
8329
+ if (child.nodeType === Node.TEXT_NODE) {
8330
+ cur += child.textContent || "";
8331
+ } else if (child.nodeName === "BR") {
8332
+ out.push(cur);
8333
+ cur = "";
8334
+ } else if (BLOCK.test(child.nodeName)) {
8335
+ if (cur) {
8336
+ out.push(cur);
8337
+ cur = "";
8338
+ }
8339
+ const sub = linesOf(child);
8340
+ out.push(...sub.length > 0 ? sub : [""]);
8341
+ } else {
8342
+ cur += linesOf(child).join("\n");
8343
+ }
8344
+ }
8345
+ if (cur) out.push(cur);
8346
+ return out;
8347
+ };
8348
+ const text = linesOf(holder).join("\n").replace(/\n+$/, "");
8349
+ const pre = document.createElement("pre");
8350
+ const code = document.createElement("code");
8351
+ code.textContent = text || "";
8352
+ pre.appendChild(code);
8353
+ range.deleteContents();
8354
+ range.insertNode(pre);
8355
+ ensureParagraphAfter(pre);
8356
+ placeCaretAtEnd(code);
8357
+ handleInput();
8358
+ };
8359
+ const insertTextAtCaret = (text) => {
8360
+ const sel = window.getSelection();
8361
+ if (!sel || sel.rangeCount === 0) return;
8362
+ const range = sel.getRangeAt(0);
8363
+ range.deleteContents();
8364
+ const node = document.createTextNode(text);
8365
+ range.insertNode(node);
8366
+ range.setStartAfter(node);
8367
+ range.collapse(true);
8368
+ sel.removeAllRanges();
8369
+ sel.addRange(range);
8370
+ handleInput();
8371
+ };
8372
+ const ensureParagraphAfter = (node) => {
8373
+ const next = node.nextElementSibling;
8374
+ if (next && next.tagName === "P") return;
8375
+ const p = document.createElement("p");
8376
+ p.innerHTML = "<br>";
8377
+ node.after(p);
8378
+ };
8379
+ const placeCaretAtEnd = (node) => {
8380
+ const sel = window.getSelection();
8381
+ if (!sel) return;
8382
+ const r2 = document.createRange();
8383
+ r2.selectNodeContents(node);
8384
+ r2.collapse(false);
8385
+ sel.removeAllRanges();
8386
+ sel.addRange(r2);
8387
+ editorRef.current?.focus();
8388
+ };
8136
8389
  const insertDivider = () => {
8137
8390
  exec("insertHorizontalRule");
8138
8391
  const el = editorRef.current;
@@ -8179,7 +8432,9 @@ var Editor = (props) => {
8179
8432
  const range = sel.getRangeAt(0);
8180
8433
  slashStartRangeRef.current = range.cloneRange();
8181
8434
  const rect = range.getBoundingClientRect();
8182
- const editorRect = editorRef.current.getBoundingClientRect();
8435
+ const editorEl = editorRef.current;
8436
+ if (!editorEl) return;
8437
+ const editorRect = editorEl.getBoundingClientRect();
8183
8438
  setSlashPos({
8184
8439
  top: rect.bottom - editorRect.top + 4,
8185
8440
  left: rect.left - editorRect.left
@@ -8194,7 +8449,7 @@ var Editor = (props) => {
8194
8449
  setSlashIdx(0);
8195
8450
  slashStartRangeRef.current = null;
8196
8451
  };
8197
- const filteredSlashItems = React21.useMemo(() => {
8452
+ const filteredSlashItems = React22.useMemo(() => {
8198
8453
  if (!slashFilter) return SLASH_ITEMS;
8199
8454
  const f = slashFilter.toLowerCase();
8200
8455
  return SLASH_ITEMS.filter((it) => it.label.toLowerCase().includes(f) || it.key.includes(f));
@@ -8237,7 +8492,7 @@ var Editor = (props) => {
8237
8492
  setBlock("blockquote");
8238
8493
  break;
8239
8494
  case "code-block":
8240
- setBlock("pre");
8495
+ insertCodeBlock();
8241
8496
  break;
8242
8497
  case "divider":
8243
8498
  insertDivider();
@@ -8255,7 +8510,9 @@ var Editor = (props) => {
8255
8510
  if (!sel || sel.rangeCount === 0) return;
8256
8511
  const range = sel.getRangeAt(0);
8257
8512
  const rect = range.getBoundingClientRect();
8258
- const editorRect = editorRef.current.getBoundingClientRect();
8513
+ const editorEl2 = editorRef.current;
8514
+ if (!editorEl2) return;
8515
+ const editorRect = editorEl2.getBoundingClientRect();
8259
8516
  setLinkPos({
8260
8517
  top: rect.bottom - editorRect.top + 4,
8261
8518
  left: rect.left - editorRect.left
@@ -8288,13 +8545,13 @@ var Editor = (props) => {
8288
8545
  if (node.nodeType !== Node.TEXT_NODE) return false;
8289
8546
  const text = (node.textContent || "").slice(0, range.startOffset);
8290
8547
  const patterns = [
8291
- [/^###\s$/, () => setBlock("h3")],
8292
- [/^##\s$/, () => setBlock("h2")],
8293
- [/^#\s$/, () => setBlock("h1")],
8294
- [/^-\s$/, () => exec("insertUnorderedList")],
8295
- [/^\*\s$/, () => exec("insertUnorderedList")],
8296
- [/^1\.\s$/, () => exec("insertOrderedList")],
8297
- [/^>\s$/, () => setBlock("blockquote")]
8548
+ [/^###$/, () => setBlock("h3")],
8549
+ [/^##$/, () => setBlock("h2")],
8550
+ [/^#$/, () => setBlock("h1")],
8551
+ [/^-$/, () => exec("insertUnorderedList")],
8552
+ [/^\*$/, () => exec("insertUnorderedList")],
8553
+ [/^1\.$/, () => exec("insertOrderedList")],
8554
+ [/^>$/, () => setBlock("blockquote")]
8298
8555
  ];
8299
8556
  for (const [re, fn] of patterns) {
8300
8557
  if (re.test(text)) {
@@ -8314,7 +8571,9 @@ var Editor = (props) => {
8314
8571
  if (composingRef.current) return;
8315
8572
  const el = editorRef.current;
8316
8573
  if (!el) return;
8317
- onChange?.(el.innerHTML);
8574
+ const html = el.innerHTML;
8575
+ lastEmittedRef.current = html;
8576
+ onChange?.(html);
8318
8577
  updateEmpty();
8319
8578
  updateActiveFormats();
8320
8579
  if (slashOpen) {
@@ -8342,6 +8601,31 @@ var Editor = (props) => {
8342
8601
  };
8343
8602
  const handleKeyDown = (e) => {
8344
8603
  if (readOnly) return;
8604
+ if (composingRef.current || e.nativeEvent.isComposing || e.keyCode === 229) return;
8605
+ const pre = closestPre();
8606
+ if (pre && !slashOpen) {
8607
+ if (e.key === "Enter" && !e.shiftKey) {
8608
+ const text = pre.textContent || "";
8609
+ if (text.endsWith("\n\n")) {
8610
+ e.preventDefault();
8611
+ const code = pre.querySelector("code") ?? pre;
8612
+ code.textContent = text.replace(/\n\n$/, "");
8613
+ ensureParagraphAfter(pre);
8614
+ const next = pre.nextElementSibling;
8615
+ if (next) placeCaretAtEnd(next);
8616
+ handleInput();
8617
+ return;
8618
+ }
8619
+ e.preventDefault();
8620
+ insertTextAtCaret("\n");
8621
+ return;
8622
+ }
8623
+ if (e.key === "Tab") {
8624
+ e.preventDefault();
8625
+ insertTextAtCaret(" ");
8626
+ return;
8627
+ }
8628
+ }
8345
8629
  if (slashOpen) {
8346
8630
  if (e.key === "ArrowDown") {
8347
8631
  e.preventDefault();
@@ -8388,6 +8672,7 @@ var Editor = (props) => {
8388
8672
  return;
8389
8673
  }
8390
8674
  }
8675
+ if (pre) return;
8391
8676
  if (enableSlashCommand && e.key === "/") {
8392
8677
  setTimeout(openSlashMenu, 0);
8393
8678
  }
@@ -8400,8 +8685,12 @@ var Editor = (props) => {
8400
8685
  const handlePaste = (e) => {
8401
8686
  if (readOnly) return;
8402
8687
  e.preventDefault();
8403
- const html = e.clipboardData.getData("text/html");
8404
8688
  const text = e.clipboardData.getData("text/plain");
8689
+ if (closestPre()) {
8690
+ insertTextAtCaret(text);
8691
+ return;
8692
+ }
8693
+ const html = e.clipboardData.getData("text/html");
8405
8694
  const clean = html ? sanitizeHtml(html) : escapeHtml(text);
8406
8695
  document.execCommand("insertHTML", false, clean);
8407
8696
  handleInput();
@@ -8425,6 +8714,7 @@ var Editor = (props) => {
8425
8714
  updateActiveFormats();
8426
8715
  };
8427
8716
  const onToolbarAction = (item) => {
8717
+ if (closestPre() && item !== "code-block") return;
8428
8718
  switch (item) {
8429
8719
  case "bold":
8430
8720
  exec("bold");
@@ -8466,7 +8756,7 @@ var Editor = (props) => {
8466
8756
  setBlock("blockquote");
8467
8757
  break;
8468
8758
  case "code-block":
8469
- setBlock("pre");
8759
+ insertCodeBlock();
8470
8760
  break;
8471
8761
  case "link":
8472
8762
  openLinkEditor();
@@ -8496,6 +8786,10 @@ var Editor = (props) => {
8496
8786
  ref: editorRef,
8497
8787
  contentEditable: !readOnly,
8498
8788
  suppressContentEditableWarning: true,
8789
+ role: "textbox",
8790
+ "aria-multiline": "true",
8791
+ "aria-readonly": readOnly || void 0,
8792
+ "aria-label": placeholder,
8499
8793
  className: "lib-xplat-editor__editable",
8500
8794
  onInput: handleInput,
8501
8795
  onKeyDown: handleKeyDown,
@@ -8587,7 +8881,7 @@ var EditorToolbar = ({ items, active, onAction }) => {
8587
8881
  )) });
8588
8882
  };
8589
8883
  var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
8590
- React21.useEffect(() => {
8884
+ React22.useEffect(() => {
8591
8885
  const handleClickOutside = (e) => {
8592
8886
  const target = e.target;
8593
8887
  const menu = document.querySelector(".lib-xplat-editor__slash-menu");
@@ -8621,8 +8915,8 @@ var SlashMenu = ({ position, items, activeIndex, onSelect, onClose }) => {
8621
8915
  );
8622
8916
  };
8623
8917
  var LinkPopover = ({ position, value, onChange, onConfirm, onClose }) => {
8624
- const inputRef = React21.useRef(null);
8625
- React21.useEffect(() => {
8918
+ const inputRef = React22.useRef(null);
8919
+ React22.useEffect(() => {
8626
8920
  inputRef.current?.focus();
8627
8921
  }, []);
8628
8922
  return /* @__PURE__ */ jsxs207(
@@ -8680,7 +8974,7 @@ EmptyState.displayName = "EmptyState";
8680
8974
  var EmptyState_default = EmptyState;
8681
8975
 
8682
8976
  // src/components/FileUpload/FileUpload.tsx
8683
- import React22 from "react";
8977
+ import React23 from "react";
8684
8978
  import { jsx as jsx325, jsxs as jsxs209 } from "react/jsx-runtime";
8685
8979
  var FileUpload = (props) => {
8686
8980
  const {
@@ -8692,8 +8986,8 @@ var FileUpload = (props) => {
8692
8986
  description,
8693
8987
  validations
8694
8988
  } = props;
8695
- const [isDragOver, setIsDragOver] = React22.useState(false);
8696
- const inputRef = React22.useRef(null);
8989
+ const [isDragOver, setIsDragOver] = React23.useState(false);
8990
+ const inputRef = React23.useRef(null);
8697
8991
  const handleFiles = (fileList) => {
8698
8992
  let files = Array.from(fileList);
8699
8993
  if (maxSize) {
@@ -8755,10 +9049,10 @@ FileUpload.displayName = "FileUpload";
8755
9049
  var FileUpload_default = FileUpload;
8756
9050
 
8757
9051
  // src/components/HtmlTypeWriter/HtmlTypeWriter.tsx
8758
- import React24 from "react";
9052
+ import React25 from "react";
8759
9053
 
8760
9054
  // src/components/HtmlTypeWriter/utils.ts
8761
- import React23 from "react";
9055
+ import React24 from "react";
8762
9056
  var voidTags = /* @__PURE__ */ new Set([
8763
9057
  "br",
8764
9058
  "img",
@@ -8826,15 +9120,15 @@ var convertNodeToReactWithRange = (node, typedLen, rangeMap) => {
8826
9120
  props[attr.name] = attr.value;
8827
9121
  });
8828
9122
  if (voidTags.has(tag)) {
8829
- return React23.createElement(tag, props);
9123
+ return React24.createElement(tag, props);
8830
9124
  }
8831
9125
  const children = Array.from(element.childNodes).map((child) => convertNodeToReactWithRange(child, typedLen, rangeMap)).filter((n) => n != null);
8832
- return React23.createElement(tag, props, ...children);
9126
+ return React24.createElement(tag, props, ...children);
8833
9127
  };
8834
9128
  var htmlToReactProgressive = (root, typedLen, rangeMap) => {
8835
9129
  const nodes = Array.from(root.childNodes).map((child, idx) => {
8836
9130
  const node = convertNodeToReactWithRange(child, typedLen, rangeMap);
8837
- return node == null ? null : React23.createElement(React23.Fragment, { key: idx }, node);
9131
+ return node == null ? null : React24.createElement(React24.Fragment, { key: idx }, node);
8838
9132
  }).filter(Boolean);
8839
9133
  return nodes.length === 0 ? null : nodes;
8840
9134
  };
@@ -8847,20 +9141,20 @@ var HtmlTypeWriter = ({
8847
9141
  onDone,
8848
9142
  onChange
8849
9143
  }) => {
8850
- const [typedLen, setTypedLen] = React24.useState(0);
8851
- const doneCalledRef = React24.useRef(false);
8852
- const { doc, rangeMap, totalLength } = React24.useMemo(() => {
9144
+ const [typedLen, setTypedLen] = React25.useState(0);
9145
+ const doneCalledRef = React25.useRef(false);
9146
+ const { doc, rangeMap, totalLength } = React25.useMemo(() => {
8853
9147
  if (typeof window === "undefined") return { doc: null, rangeMap: /* @__PURE__ */ new Map(), totalLength: 0 };
8854
9148
  const decoded = decodeHtmlEntities(html);
8855
9149
  const doc2 = new DOMParser().parseFromString(decoded, "text/html");
8856
9150
  const { rangeMap: rangeMap2, totalLength: totalLength2 } = buildRangeMap(doc2.body);
8857
9151
  return { doc: doc2, rangeMap: rangeMap2, totalLength: totalLength2 };
8858
9152
  }, [html]);
8859
- React24.useEffect(() => {
9153
+ React25.useEffect(() => {
8860
9154
  setTypedLen(0);
8861
9155
  doneCalledRef.current = false;
8862
9156
  }, [html]);
8863
- React24.useEffect(() => {
9157
+ React25.useEffect(() => {
8864
9158
  if (!totalLength) return;
8865
9159
  if (typedLen >= totalLength) return;
8866
9160
  const timer = window.setInterval(() => {
@@ -8868,18 +9162,18 @@ var HtmlTypeWriter = ({
8868
9162
  }, duration);
8869
9163
  return () => window.clearInterval(timer);
8870
9164
  }, [typedLen, totalLength, duration]);
8871
- React24.useEffect(() => {
9165
+ React25.useEffect(() => {
8872
9166
  if (typedLen > 0 && typedLen < totalLength) {
8873
9167
  onChange?.();
8874
9168
  }
8875
9169
  }, [typedLen, totalLength, onChange]);
8876
- React24.useEffect(() => {
9170
+ React25.useEffect(() => {
8877
9171
  if (typedLen === totalLength && totalLength > 0 && !doneCalledRef.current) {
8878
9172
  doneCalledRef.current = true;
8879
9173
  onDone?.();
8880
9174
  }
8881
9175
  }, [typedLen, totalLength, onDone]);
8882
- const parsed = React24.useMemo(
9176
+ const parsed = React25.useMemo(
8883
9177
  () => doc ? htmlToReactProgressive(doc.body, typedLen, rangeMap) : null,
8884
9178
  [doc, typedLen, rangeMap]
8885
9179
  );
@@ -8889,12 +9183,12 @@ HtmlTypeWriter.displayName = "HtmlTypeWriter";
8889
9183
  var HtmlTypeWriter_default = HtmlTypeWriter;
8890
9184
 
8891
9185
  // src/components/ImageSelector/ImageSelector.tsx
8892
- import React25 from "react";
9186
+ import React26 from "react";
8893
9187
  import { jsx as jsx327, jsxs as jsxs210 } from "react/jsx-runtime";
8894
9188
  var ImageSelector = (props) => {
8895
9189
  const { value, label, onChange, validations } = props;
8896
- const [previewUrl, setPreviewUrl] = React25.useState();
8897
- React25.useEffect(() => {
9190
+ const [previewUrl, setPreviewUrl] = React26.useState();
9191
+ React26.useEffect(() => {
8898
9192
  if (!value) {
8899
9193
  setPreviewUrl(void 0);
8900
9194
  return;
@@ -8903,7 +9197,7 @@ var ImageSelector = (props) => {
8903
9197
  setPreviewUrl(url);
8904
9198
  return () => URL.revokeObjectURL(url);
8905
9199
  }, [value]);
8906
- const inputRef = React25.useRef(null);
9200
+ const inputRef = React26.useRef(null);
8907
9201
  const handleFileChange = (e) => {
8908
9202
  const selectedFile = e.target.files?.[0];
8909
9203
  if (selectedFile) {
@@ -8991,11 +9285,12 @@ var NotificationBadge = (props) => {
8991
9285
  dot = false,
8992
9286
  size = "md"
8993
9287
  } = props;
9288
+ const statusType = normalizeStatus(type);
8994
9289
  const showBadge = dot || count !== void 0 && count > 0;
8995
9290
  const displayCount = count !== void 0 && count > maxCount ? `${maxCount}+` : count;
8996
9291
  return /* @__PURE__ */ jsxs211("div", { className: clsx_default("lib-xplat-notification-badge", size), children: [
8997
9292
  children,
8998
- showBadge && /* @__PURE__ */ jsx330("span", { className: clsx_default("badge-indicator", type, { dot }), children: !dot && displayCount })
9293
+ showBadge && /* @__PURE__ */ jsx330("span", { className: clsx_default("badge-indicator", statusType, { dot }), children: !dot && displayCount })
8999
9294
  ] });
9000
9295
  };
9001
9296
  NotificationBadge.displayName = "NotificationBadge";
@@ -9036,8 +9331,9 @@ var Pagination = (props) => {
9036
9331
  siblingCount = 1,
9037
9332
  onChange,
9038
9333
  size = "md",
9039
- type = "brand"
9334
+ type = "primary"
9040
9335
  } = props;
9336
+ const statusType = normalizeStatus(type);
9041
9337
  const totalPages = Math.max(1, Math.ceil(total / pageSize));
9042
9338
  const pages = getPageRange(current, totalPages, siblingCount);
9043
9339
  const handleClick = (page) => {
@@ -9045,7 +9341,7 @@ var Pagination = (props) => {
9045
9341
  onChange?.(page);
9046
9342
  }
9047
9343
  };
9048
- return /* @__PURE__ */ jsxs212("nav", { className: clsx_default("lib-xplat-pagination", size, type), "aria-label": "\uD398\uC774\uC9C0 \uB124\uBE44\uAC8C\uC774\uC158", children: [
9344
+ return /* @__PURE__ */ jsxs212("nav", { className: clsx_default("lib-xplat-pagination", size, statusType), "aria-label": "\uD398\uC774\uC9C0 \uB124\uBE44\uAC8C\uC774\uC158", children: [
9049
9345
  /* @__PURE__ */ jsx331(
9050
9346
  "button",
9051
9347
  {
@@ -9084,17 +9380,21 @@ Pagination.displayName = "Pagination";
9084
9380
  var Pagination_default = Pagination;
9085
9381
 
9086
9382
  // src/components/PopOver/PopOver.tsx
9087
- import React26 from "react";
9383
+ import React27 from "react";
9088
9384
  import { jsx as jsx332, jsxs as jsxs213 } from "react/jsx-runtime";
9089
9385
  var PopOver = (props) => {
9090
9386
  const { children, isOpen, onClose, PopOverEl } = props;
9091
- const popRef = React26.useRef(null);
9092
- const triggerRef = React26.useRef(null);
9093
- const [localOpen, setLocalOpen] = React26.useState(false);
9094
- const [eventTrigger, setEventTrigger] = React26.useState(false);
9387
+ const popRef = React27.useRef(null);
9388
+ const triggerRef = React27.useRef(null);
9389
+ const [localOpen, setLocalOpen] = React27.useState(false);
9390
+ const [eventTrigger, setEventTrigger] = React27.useState(false);
9095
9391
  useClickOutside_default([popRef, triggerRef], onClose, isOpen);
9392
+ useEscapeKey(isOpen, () => {
9393
+ onClose();
9394
+ triggerRef.current?.focus({ preventScroll: true });
9395
+ });
9096
9396
  const position = useAutoPosition_default(triggerRef, popRef, localOpen);
9097
- React26.useEffect(() => {
9397
+ React27.useEffect(() => {
9098
9398
  if (isOpen) {
9099
9399
  setLocalOpen(isOpen);
9100
9400
  setTimeout(() => {
@@ -9146,11 +9446,12 @@ var Progress = (props) => {
9146
9446
  value,
9147
9447
  max = 100,
9148
9448
  size = "md",
9149
- type = "brand",
9449
+ type = "primary",
9150
9450
  showLabel = false
9151
9451
  } = props;
9452
+ const statusType = normalizeStatus(type);
9152
9453
  const percentage = Math.min(100, Math.max(0, value / max * 100));
9153
- return /* @__PURE__ */ jsxs214("div", { className: clsx_default("lib-xplat-progress", size, type), children: [
9454
+ return /* @__PURE__ */ jsxs214("div", { className: clsx_default("lib-xplat-progress", size, statusType), children: [
9154
9455
  /* @__PURE__ */ jsx333(
9155
9456
  "div",
9156
9457
  {
@@ -9178,12 +9479,12 @@ Progress.displayName = "Progress";
9178
9479
  var Progress_default = Progress;
9179
9480
 
9180
9481
  // src/components/Radio/RadioGroupContext.tsx
9181
- import React27 from "react";
9182
- var RadioGroupContext = React27.createContext(
9482
+ import React28 from "react";
9483
+ var RadioGroupContext = React28.createContext(
9183
9484
  null
9184
9485
  );
9185
9486
  var useRadioGroupContext = () => {
9186
- return React27.useContext(RadioGroupContext);
9487
+ return React28.useContext(RadioGroupContext);
9187
9488
  };
9188
9489
  var RadioGroupContext_default = RadioGroupContext;
9189
9490
 
@@ -9195,10 +9496,11 @@ var Radio = (props) => {
9195
9496
  className,
9196
9497
  value,
9197
9498
  size: sizeProp,
9198
- type = "brand",
9499
+ type = "primary",
9199
9500
  validations,
9200
9501
  ...rest
9201
9502
  } = props;
9503
+ const statusType = normalizeStatus(type);
9202
9504
  const context = useRadioGroupContext();
9203
9505
  const size = sizeProp ?? context?.size ?? "md";
9204
9506
  const isGroup = !!context;
@@ -9214,7 +9516,7 @@ var Radio = (props) => {
9214
9516
  className: clsx_default(
9215
9517
  "lib-xplat-radio",
9216
9518
  size,
9217
- type,
9519
+ statusType,
9218
9520
  localChecked ? "checked" : void 0,
9219
9521
  className
9220
9522
  ),
@@ -9258,19 +9560,19 @@ RadioGroup.displayName = "RadioGroup";
9258
9560
  var RadioGroup_default = RadioGroup;
9259
9561
 
9260
9562
  // src/components/Select/Select.tsx
9261
- import React30 from "react";
9563
+ import React31 from "react";
9262
9564
 
9263
9565
  // src/components/Select/context.ts
9264
- import React28 from "react";
9265
- var SelectContext = React28.createContext(null);
9566
+ import React29 from "react";
9567
+ var SelectContext = React29.createContext(null);
9266
9568
  var context_default = SelectContext;
9267
9569
 
9268
9570
  // src/components/Select/SelectItem.tsx
9269
- import React29 from "react";
9571
+ import React30 from "react";
9270
9572
  import { jsx as jsx336 } from "react/jsx-runtime";
9271
9573
  var SelectItem = (props) => {
9272
9574
  const { children, value, onClick, disabled = false } = props;
9273
- const ctx = React29.useContext(context_default);
9575
+ const ctx = React30.useContext(context_default);
9274
9576
  const handleClick = (e) => {
9275
9577
  e.preventDefault();
9276
9578
  e.stopPropagation();
@@ -9310,32 +9612,37 @@ var SelectRoot = (props) => {
9310
9612
  onChange,
9311
9613
  children,
9312
9614
  disabled = false,
9615
+ searchable = false,
9616
+ searchPlaceholder = "\uAC80\uC0C9",
9313
9617
  error = false,
9314
9618
  validations,
9619
+ label,
9620
+ required,
9315
9621
  size = "md"
9316
9622
  } = props;
9317
- const itemChildren = React30.Children.toArray(children).filter(
9318
- (child) => React30.isValidElement(child) && child.type === SelectItem_default
9623
+ const fieldId = React31.useId();
9624
+ const itemChildren = React31.Children.toArray(children).filter(
9625
+ (child) => React31.isValidElement(child) && child.type === SelectItem_default
9319
9626
  );
9320
9627
  const isControlled = valueProp !== void 0;
9321
- const [isOpen, setOpen] = React30.useState(false);
9322
- const [uncontrolledLabel, setUncontrolledLabel] = React30.useState(null);
9323
- const [uncontrolledValue, setUncontrolledValue] = React30.useState(void 0);
9324
- const controlledLabel = React30.useMemo(() => {
9628
+ const [isOpen, setOpen] = React31.useState(false);
9629
+ const [uncontrolledLabel, setUncontrolledLabel] = React31.useState(null);
9630
+ const [uncontrolledValue, setUncontrolledValue] = React31.useState(void 0);
9631
+ const controlledLabel = React31.useMemo(() => {
9325
9632
  if (!isControlled) return null;
9326
9633
  const match = itemChildren.find((child) => child.props.value === valueProp);
9327
9634
  return match ? match.props.children : null;
9328
9635
  }, [isControlled, valueProp, itemChildren]);
9329
9636
  const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
9330
9637
  const selectedValue = isControlled ? valueProp : uncontrolledValue;
9331
- const triggerRef = React30.useRef(null);
9332
- const contentRef = React30.useRef(null);
9333
- const [mounted, setMounted] = React30.useState(false);
9334
- const [visible, setVisible] = React30.useState(false);
9335
- React30.useEffect(() => {
9638
+ const triggerRef = React31.useRef(null);
9639
+ const contentRef = React31.useRef(null);
9640
+ const [mounted, setMounted] = React31.useState(false);
9641
+ const [visible, setVisible] = React31.useState(false);
9642
+ React31.useEffect(() => {
9336
9643
  if (disabled && isOpen) setOpen(false);
9337
9644
  }, [disabled, isOpen]);
9338
- React30.useEffect(() => {
9645
+ React31.useEffect(() => {
9339
9646
  if (isOpen) {
9340
9647
  setMounted(true);
9341
9648
  const t2 = setTimeout(() => setVisible(true), 1);
@@ -9345,22 +9652,42 @@ var SelectRoot = (props) => {
9345
9652
  const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS3);
9346
9653
  return () => clearTimeout(t);
9347
9654
  }, [isOpen]);
9348
- const open = React30.useCallback(() => setOpen(true), []);
9349
- const close = React30.useCallback(() => setOpen(false), []);
9350
- const toggle = React30.useCallback(() => setOpen((prev) => !prev), []);
9655
+ const [query, setQuery] = React31.useState("");
9656
+ const textOf = (node) => {
9657
+ if (node === null || node === void 0 || typeof node === "boolean") return "";
9658
+ if (typeof node === "string" || typeof node === "number") return String(node);
9659
+ if (Array.isArray(node)) return node.map(textOf).join("");
9660
+ if (React31.isValidElement(node)) return textOf(node.props.children);
9661
+ return "";
9662
+ };
9663
+ const visibleItems = React31.useMemo(() => {
9664
+ if (!searchable || !query.trim()) return itemChildren;
9665
+ const q = query.trim().toLowerCase();
9666
+ return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
9667
+ }, [searchable, query, itemChildren]);
9668
+ const open = React31.useCallback(() => setOpen(true), []);
9669
+ const close = React31.useCallback(() => {
9670
+ setOpen(false);
9671
+ setQuery("");
9672
+ }, []);
9673
+ const toggle = React31.useCallback(() => setOpen((prev) => !prev), []);
9351
9674
  useClickOutside_default([contentRef, triggerRef], close, isOpen);
9675
+ useEscapeKey(isOpen, () => {
9676
+ close();
9677
+ triggerRef.current?.focus({ preventScroll: true });
9678
+ });
9352
9679
  const position = useAutoPosition_default(triggerRef, contentRef, mounted);
9353
- const setSelected = React30.useCallback(
9354
- (label, itemValue) => {
9680
+ const setSelected = React31.useCallback(
9681
+ (label2, itemValue) => {
9355
9682
  if (!isControlled) {
9356
- setUncontrolledLabel(label);
9683
+ setUncontrolledLabel(label2);
9357
9684
  setUncontrolledValue(itemValue);
9358
9685
  }
9359
- onChange?.(itemValue, label);
9686
+ onChange?.(itemValue, label2);
9360
9687
  },
9361
9688
  [isControlled, onChange]
9362
9689
  );
9363
- const ctxValue = React30.useMemo(
9690
+ const ctxValue = React31.useMemo(
9364
9691
  () => ({
9365
9692
  isOpen,
9366
9693
  mounted,
@@ -9396,6 +9723,7 @@ var SelectRoot = (props) => {
9396
9723
  /* @__PURE__ */ jsxs216(
9397
9724
  "div",
9398
9725
  {
9726
+ id: fieldId,
9399
9727
  ref: triggerRef,
9400
9728
  className: clsx_default(
9401
9729
  "select-trigger",
@@ -9438,20 +9766,33 @@ var SelectRoot = (props) => {
9438
9766
  ]
9439
9767
  }
9440
9768
  ),
9441
- mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsx337(
9769
+ mounted && /* @__PURE__ */ jsx337(Portal_default, { children: /* @__PURE__ */ jsxs216(
9442
9770
  "div",
9443
9771
  {
9444
9772
  className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
9445
9773
  ref: contentRef,
9446
9774
  style: { ...position.position, width: triggerRef.current?.offsetWidth },
9447
9775
  role: "listbox",
9448
- children: /* @__PURE__ */ jsx337(context_default.Provider, { value: ctxValue, children: itemChildren })
9776
+ children: [
9777
+ searchable && /* @__PURE__ */ jsx337("div", { className: "select-search", children: /* @__PURE__ */ jsx337(
9778
+ "input",
9779
+ {
9780
+ type: "text",
9781
+ value: query,
9782
+ placeholder: searchPlaceholder,
9783
+ onChange: (e) => setQuery(e.target.value),
9784
+ autoFocus: true,
9785
+ "aria-label": searchPlaceholder
9786
+ }
9787
+ ) }),
9788
+ /* @__PURE__ */ jsx337(context_default.Provider, { value: ctxValue, children: visibleItems.length > 0 ? visibleItems : /* @__PURE__ */ jsx337("div", { className: "select-empty", children: "\uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" }) })
9789
+ ]
9449
9790
  }
9450
9791
  ) })
9451
9792
  ]
9452
9793
  }
9453
9794
  ) });
9454
- return /* @__PURE__ */ jsx337(Field, { validations, children: control });
9795
+ return /* @__PURE__ */ jsx337(Field, { validations, label, required, htmlFor: fieldId, children: control });
9455
9796
  };
9456
9797
  SelectRoot.displayName = "Select";
9457
9798
  var Select = Object.assign(SelectRoot, {
@@ -9493,12 +9834,13 @@ import { jsx as jsx339, jsxs as jsxs217 } from "react/jsx-runtime";
9493
9834
  var Spinner = (props) => {
9494
9835
  const {
9495
9836
  size = "md",
9496
- type = "brand"
9837
+ type = "primary"
9497
9838
  } = props;
9839
+ const statusType = normalizeStatus(type);
9498
9840
  return /* @__PURE__ */ jsx339(
9499
9841
  "div",
9500
9842
  {
9501
- className: clsx_default("lib-xplat-spinner", size, type),
9843
+ className: clsx_default("lib-xplat-spinner", size, statusType),
9502
9844
  role: "status",
9503
9845
  "aria-label": "\uB85C\uB529 \uC911",
9504
9846
  children: /* @__PURE__ */ jsxs217("svg", { viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
@@ -9530,21 +9872,58 @@ var Spinner = (props) => {
9530
9872
  Spinner.displayName = "Spinner";
9531
9873
  var Spinner_default = Spinner;
9532
9874
 
9533
- // src/components/Steps/Steps.tsx
9875
+ // src/components/Stat/Stat.tsx
9534
9876
  import { jsx as jsx340, jsxs as jsxs218 } from "react/jsx-runtime";
9877
+ var ARROW = {
9878
+ up: "\u25B2",
9879
+ down: "\u25BC",
9880
+ flat: "\u2014"
9881
+ };
9882
+ var Stat = (props) => {
9883
+ const {
9884
+ label,
9885
+ value,
9886
+ unit,
9887
+ description,
9888
+ trend,
9889
+ icon,
9890
+ size = "md",
9891
+ type = "primary"
9892
+ } = props;
9893
+ const statusType = normalizeStatus(type);
9894
+ return /* @__PURE__ */ jsxs218("div", { className: clsx_default("lib-xplat-stat", size, statusType), children: [
9895
+ /* @__PURE__ */ jsx340("div", { className: "stat-label", children: label }),
9896
+ /* @__PURE__ */ jsxs218("div", { className: "stat-value-row", children: [
9897
+ icon && /* @__PURE__ */ jsx340("span", { className: "stat-icon", children: icon }),
9898
+ /* @__PURE__ */ jsx340("span", { className: "stat-value", children: value }),
9899
+ unit && /* @__PURE__ */ jsx340("span", { className: "stat-unit", children: unit }),
9900
+ trend && /* @__PURE__ */ jsxs218("span", { className: clsx_default("stat-trend", trend.direction), children: [
9901
+ /* @__PURE__ */ jsx340("span", { "aria-hidden": "true", children: ARROW[trend.direction] }),
9902
+ trend.value
9903
+ ] })
9904
+ ] }),
9905
+ description && /* @__PURE__ */ jsx340("div", { className: "stat-description", children: description })
9906
+ ] });
9907
+ };
9908
+ Stat.displayName = "Stat";
9909
+ var Stat_default = Stat;
9910
+
9911
+ // src/components/Steps/Steps.tsx
9912
+ import { jsx as jsx341, jsxs as jsxs219 } from "react/jsx-runtime";
9535
9913
  var Steps = (props) => {
9536
9914
  const {
9537
9915
  items,
9538
9916
  current,
9539
- type = "brand"
9917
+ type = "primary"
9540
9918
  } = props;
9541
- return /* @__PURE__ */ jsx340("div", { className: clsx_default("lib-xplat-steps", type), children: items.map((item, index) => {
9919
+ const statusType = normalizeStatus(type);
9920
+ return /* @__PURE__ */ jsx341("div", { className: clsx_default("lib-xplat-steps", statusType), children: items.map((item, index) => {
9542
9921
  const status = index < current ? "completed" : index === current ? "active" : "pending";
9543
- return /* @__PURE__ */ jsxs218("div", { className: clsx_default("step-item", status), children: [
9544
- /* @__PURE__ */ jsx340("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ jsx340(CheckIcon_default, {}) : /* @__PURE__ */ jsx340("span", { children: index + 1 }) }),
9545
- /* @__PURE__ */ jsxs218("div", { className: "step-content", children: [
9546
- /* @__PURE__ */ jsx340("span", { className: "step-title", children: item.title }),
9547
- item.description && /* @__PURE__ */ jsx340("span", { className: "step-description", children: item.description })
9922
+ return /* @__PURE__ */ jsxs219("div", { className: clsx_default("step-item", status), children: [
9923
+ /* @__PURE__ */ jsx341("div", { className: "step-circle", children: status === "completed" ? /* @__PURE__ */ jsx341(CheckIcon_default, {}) : /* @__PURE__ */ jsx341("span", { children: index + 1 }) }),
9924
+ /* @__PURE__ */ jsxs219("div", { className: "step-content", children: [
9925
+ /* @__PURE__ */ jsx341("span", { className: "step-title", children: item.title }),
9926
+ item.description && /* @__PURE__ */ jsx341("span", { className: "step-description", children: item.description })
9548
9927
  ] })
9549
9928
  ] }, index);
9550
9929
  }) });
@@ -9553,8 +9932,8 @@ Steps.displayName = "Steps";
9553
9932
  var Steps_default = Steps;
9554
9933
 
9555
9934
  // src/components/Swiper/Swiper.tsx
9556
- import React31 from "react";
9557
- import { jsx as jsx341, jsxs as jsxs219 } from "react/jsx-runtime";
9935
+ import React32 from "react";
9936
+ import { jsx as jsx342, jsxs as jsxs220 } from "react/jsx-runtime";
9558
9937
  var Swiper = (props) => {
9559
9938
  const {
9560
9939
  auto = false,
@@ -9578,26 +9957,26 @@ var Swiper = (props) => {
9578
9957
  const maxIndex = Math.max(0, totalSlides - viewItemCount);
9579
9958
  const useLoop = loop && canSlide;
9580
9959
  const cloneCount = useLoop ? totalSlides : 0;
9581
- const extendedItems = React31.useMemo(() => {
9960
+ const extendedItems = React32.useMemo(() => {
9582
9961
  if (!useLoop) return items;
9583
9962
  return [...items, ...items, ...items];
9584
9963
  }, [items, useLoop]);
9585
9964
  const initialIdx = Math.max(0, Math.min(indexProp ?? 0, maxIndex));
9586
- const [innerIndex, setInnerIndex] = React31.useState(
9965
+ const [innerIndex, setInnerIndex] = React32.useState(
9587
9966
  useLoop ? cloneCount + initialIdx : initialIdx
9588
9967
  );
9589
- const [isDragging, setIsDragging] = React31.useState(false);
9590
- const [dragOffset, setDragOffset] = React31.useState(0);
9591
- const [animated, setAnimated] = React31.useState(false);
9592
- const [containerWidth, setContainerWidth] = React31.useState(0);
9593
- const containerRef = React31.useRef(null);
9594
- const startXRef = React31.useRef(0);
9595
- const startTimeRef = React31.useRef(0);
9596
- const autoplayTimerRef = React31.useRef(null);
9597
- const resumeTimeoutRef = React31.useRef(null);
9598
- const [paused, setPaused] = React31.useState(false);
9599
- const initializedRef = React31.useRef(false);
9600
- React31.useEffect(() => {
9968
+ const [isDragging, setIsDragging] = React32.useState(false);
9969
+ const [dragOffset, setDragOffset] = React32.useState(0);
9970
+ const [animated, setAnimated] = React32.useState(false);
9971
+ const [containerWidth, setContainerWidth] = React32.useState(0);
9972
+ const containerRef = React32.useRef(null);
9973
+ const startXRef = React32.useRef(0);
9974
+ const startTimeRef = React32.useRef(0);
9975
+ const autoplayTimerRef = React32.useRef(null);
9976
+ const resumeTimeoutRef = React32.useRef(null);
9977
+ const [paused, setPaused] = React32.useState(false);
9978
+ const initializedRef = React32.useRef(false);
9979
+ React32.useEffect(() => {
9601
9980
  const el = containerRef.current;
9602
9981
  if (!el) return;
9603
9982
  const ro = new ResizeObserver((entries) => {
@@ -9620,7 +9999,7 @@ var Swiper = (props) => {
9620
9999
  return ((inner - cloneCount) % totalSlides + totalSlides) % totalSlides;
9621
10000
  };
9622
10001
  const realIndex = getRealIndex(innerIndex);
9623
- const moveToInner = React31.useCallback(
10002
+ const moveToInner = React32.useCallback(
9624
10003
  (idx, withAnim = true) => {
9625
10004
  if (!useLoop) {
9626
10005
  setAnimated(withAnim);
@@ -9648,7 +10027,7 @@ var Swiper = (props) => {
9648
10027
  },
9649
10028
  [useLoop, cloneCount, totalSlides]
9650
10029
  );
9651
- const handleTransitionEnd = React31.useCallback(() => {
10030
+ const handleTransitionEnd = React32.useCallback(() => {
9652
10031
  if (!useLoop) return;
9653
10032
  const real = getRealIndex(innerIndex);
9654
10033
  const canonical = cloneCount + real;
@@ -9658,7 +10037,7 @@ var Swiper = (props) => {
9658
10037
  }
9659
10038
  onChange?.(Math.min(real, maxIndex));
9660
10039
  }, [useLoop, innerIndex, cloneCount, totalSlides, maxIndex, onChange]);
9661
- const slideTo = React31.useCallback(
10040
+ const slideTo = React32.useCallback(
9662
10041
  (logicalIndex) => {
9663
10042
  if (!canSlide) return;
9664
10043
  const clamped = useLoop ? logicalIndex : Math.max(0, Math.min(logicalIndex, maxIndex));
@@ -9668,7 +10047,7 @@ var Swiper = (props) => {
9668
10047
  },
9669
10048
  [canSlide, useLoop, cloneCount, maxIndex, onChange, moveToInner]
9670
10049
  );
9671
- const slideNext = React31.useCallback(() => {
10050
+ const slideNext = React32.useCallback(() => {
9672
10051
  if (!canSlide) return;
9673
10052
  const nextInner = innerIndex + slideBy;
9674
10053
  if (useLoop) {
@@ -9677,7 +10056,7 @@ var Swiper = (props) => {
9677
10056
  moveToInner(Math.min(nextInner, maxIndex), true);
9678
10057
  }
9679
10058
  }, [canSlide, useLoop, innerIndex, slideBy, maxIndex, moveToInner]);
9680
- const slidePrev = React31.useCallback(() => {
10059
+ const slidePrev = React32.useCallback(() => {
9681
10060
  if (!canSlide) return;
9682
10061
  const prevInner = innerIndex - slideBy;
9683
10062
  if (useLoop) {
@@ -9686,7 +10065,7 @@ var Swiper = (props) => {
9686
10065
  moveToInner(Math.max(prevInner, 0), true);
9687
10066
  }
9688
10067
  }, [canSlide, useLoop, innerIndex, slideBy, moveToInner]);
9689
- React31.useEffect(() => {
10068
+ React32.useEffect(() => {
9690
10069
  if (indexProp === void 0) return;
9691
10070
  const clamped = Math.max(0, Math.min(indexProp, maxIndex));
9692
10071
  const target = useLoop ? cloneCount + clamped : clamped;
@@ -9694,12 +10073,12 @@ var Swiper = (props) => {
9694
10073
  moveToInner(target, true);
9695
10074
  }
9696
10075
  }, [indexProp]);
9697
- React31.useImperativeHandle(swiperRef, () => ({
10076
+ React32.useImperativeHandle(swiperRef, () => ({
9698
10077
  slidePrev,
9699
10078
  slideNext,
9700
10079
  slideTo
9701
10080
  }));
9702
- React31.useEffect(() => {
10081
+ React32.useEffect(() => {
9703
10082
  if (!auto || !canSlide || paused) return;
9704
10083
  autoplayTimerRef.current = setInterval(slideNext, autoplayDelay);
9705
10084
  return () => {
@@ -9725,7 +10104,7 @@ var Swiper = (props) => {
9725
10104
  resumeTimeoutRef.current = null;
9726
10105
  }, pauseOnInteraction);
9727
10106
  };
9728
- React31.useEffect(() => {
10107
+ React32.useEffect(() => {
9729
10108
  return () => {
9730
10109
  if (resumeTimeoutRef.current) clearTimeout(resumeTimeoutRef.current);
9731
10110
  };
@@ -9743,7 +10122,7 @@ var Swiper = (props) => {
9743
10122
  startXRef.current = getClientX(e);
9744
10123
  startTimeRef.current = Date.now();
9745
10124
  };
9746
- React31.useEffect(() => {
10125
+ React32.useEffect(() => {
9747
10126
  if (!isDragging) return;
9748
10127
  const handleMove = (e) => {
9749
10128
  setDragOffset(getClientX(e) - startXRef.current);
@@ -9782,8 +10161,8 @@ var Swiper = (props) => {
9782
10161
  }, [isDragging, dragOffset, innerIndex, useLoop, maxIndex, slideStep, moveToInner]);
9783
10162
  const slideWidthPercent = 100 / viewItemCount;
9784
10163
  const gapAdjust = spaceBetween * (viewItemCount - 1) / viewItemCount;
9785
- const slideElements = React31.useMemo(
9786
- () => extendedItems.map((item, idx) => /* @__PURE__ */ jsx341(
10164
+ const slideElements = React32.useMemo(
10165
+ () => extendedItems.map((item, idx) => /* @__PURE__ */ jsx342(
9787
10166
  "div",
9788
10167
  {
9789
10168
  className: "lib-xplat-swiper__slide",
@@ -9802,15 +10181,15 @@ var Swiper = (props) => {
9802
10181
  Math.floor(realIndex / slideBy),
9803
10182
  totalSteps - 1
9804
10183
  );
9805
- return /* @__PURE__ */ jsxs219("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
9806
- /* @__PURE__ */ jsx341(
10184
+ return /* @__PURE__ */ jsxs220("div", { className: "lib-xplat-swiper", ref: containerRef, children: [
10185
+ /* @__PURE__ */ jsx342(
9807
10186
  "div",
9808
10187
  {
9809
10188
  className: "lib-xplat-swiper__viewport",
9810
10189
  onMouseDown: handleDragStart,
9811
10190
  onTouchStart: handleDragStart,
9812
10191
  onDragStart: (e) => e.preventDefault(),
9813
- children: /* @__PURE__ */ jsx341(
10192
+ children: /* @__PURE__ */ jsx342(
9814
10193
  "div",
9815
10194
  {
9816
10195
  className: clsx_default(
@@ -9828,7 +10207,7 @@ var Swiper = (props) => {
9828
10207
  )
9829
10208
  }
9830
10209
  ),
9831
- showProgress && canSlide && /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ jsx341(
10210
+ showProgress && canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress", children: /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__progress-track", children: /* @__PURE__ */ jsx342(
9832
10211
  "span",
9833
10212
  {
9834
10213
  className: "lib-xplat-swiper__progress-fill",
@@ -9838,7 +10217,7 @@ var Swiper = (props) => {
9838
10217
  }
9839
10218
  }
9840
10219
  ) }) }),
9841
- canSlide && /* @__PURE__ */ jsx341("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ jsx341(
10220
+ canSlide && /* @__PURE__ */ jsx342("div", { className: "lib-xplat-swiper__dots", children: Array.from({ length: totalSteps }, (_, i) => /* @__PURE__ */ jsx342(
9842
10221
  "button",
9843
10222
  {
9844
10223
  className: clsx_default(
@@ -9856,21 +10235,25 @@ Swiper.displayName = "Swiper";
9856
10235
  var Swiper_default = Swiper;
9857
10236
 
9858
10237
  // src/components/Switch/Switch.tsx
9859
- import React32 from "react";
9860
- import { jsx as jsx342 } from "react/jsx-runtime";
10238
+ import React33 from "react";
10239
+ import { jsx as jsx343 } from "react/jsx-runtime";
9861
10240
  var KNOB_TRANSITION_MS = 250;
9862
10241
  var Switch = (props) => {
9863
10242
  const {
9864
10243
  value,
9865
10244
  size = "md",
9866
- type = "brand",
10245
+ type = "primary",
9867
10246
  disabled,
9868
10247
  onChange,
9869
- validations
10248
+ validations,
10249
+ label,
10250
+ required
9870
10251
  } = props;
9871
- const [isAnimating, setIsAnimating] = React32.useState(false);
9872
- const timeoutRef = React32.useRef(null);
9873
- React32.useEffect(() => {
10252
+ const fieldId = React33.useId();
10253
+ const statusType = normalizeStatus(type);
10254
+ const [isAnimating, setIsAnimating] = React33.useState(false);
10255
+ const timeoutRef = React33.useRef(null);
10256
+ React33.useEffect(() => {
9874
10257
  return () => {
9875
10258
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
9876
10259
  };
@@ -9885,13 +10268,14 @@ var Switch = (props) => {
9885
10268
  timeoutRef.current = null;
9886
10269
  }, KNOB_TRANSITION_MS);
9887
10270
  };
9888
- const control = /* @__PURE__ */ jsx342(
10271
+ const control = /* @__PURE__ */ jsx343(
9889
10272
  "div",
9890
10273
  {
10274
+ id: fieldId,
9891
10275
  className: clsx_default(
9892
10276
  "lib-xplat-switch",
9893
10277
  size,
9894
- type,
10278
+ statusType,
9895
10279
  value ? "checked" : void 0,
9896
10280
  disabled && "disabled",
9897
10281
  isAnimating && "animating"
@@ -9899,26 +10283,26 @@ var Switch = (props) => {
9899
10283
  onClick: handleClick,
9900
10284
  "aria-invalid": hasError(validations) || void 0,
9901
10285
  "aria-disabled": disabled || isAnimating,
9902
- children: /* @__PURE__ */ jsx342("div", { className: clsx_default("knob", value ? "checked" : void 0) })
10286
+ children: /* @__PURE__ */ jsx343("div", { className: clsx_default("knob", value ? "checked" : void 0) })
9903
10287
  }
9904
10288
  );
9905
- return /* @__PURE__ */ jsx342(Field, { validations, children: control });
10289
+ return /* @__PURE__ */ jsx343(Field, { validations, label, required, htmlFor: fieldId, children: control });
9906
10290
  };
9907
10291
  Switch.displayName = "Switch";
9908
10292
  var Switch_default = Switch;
9909
10293
 
9910
10294
  // src/components/Table/TableContext.tsx
9911
- import React33 from "react";
9912
- var TableContext = React33.createContext(null);
10295
+ import React34 from "react";
10296
+ var TableContext = React34.createContext(null);
9913
10297
  var useTableContext = () => {
9914
- const ctx = React33.useContext(TableContext);
10298
+ const ctx = React34.useContext(TableContext);
9915
10299
  if (!ctx) throw new Error("Table components must be used inside <Table>");
9916
10300
  return ctx;
9917
10301
  };
9918
10302
  var TableContext_default = TableContext;
9919
10303
 
9920
10304
  // src/components/Table/Table.tsx
9921
- import { jsx as jsx343 } from "react/jsx-runtime";
10305
+ import { jsx as jsx344 } from "react/jsx-runtime";
9922
10306
  var Table = (props) => {
9923
10307
  const {
9924
10308
  children,
@@ -9928,7 +10312,7 @@ var Table = (props) => {
9928
10312
  headerSticky = false,
9929
10313
  stickyShadow = true
9930
10314
  } = props;
9931
- return /* @__PURE__ */ jsx343("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx343(
10315
+ return /* @__PURE__ */ jsx344("div", { className: `lib-xplat-table-wrapper ${size}`, children: /* @__PURE__ */ jsx344(
9932
10316
  TableContext_default.Provider,
9933
10317
  {
9934
10318
  value: {
@@ -9937,7 +10321,7 @@ var Table = (props) => {
9937
10321
  headerSticky,
9938
10322
  stickyShadow
9939
10323
  },
9940
- children: /* @__PURE__ */ jsx343("table", { className: "lib-xplat-table", children })
10324
+ children: /* @__PURE__ */ jsx344("table", { className: "lib-xplat-table", children })
9941
10325
  }
9942
10326
  ) });
9943
10327
  };
@@ -9945,41 +10329,41 @@ Table.displayName = "Table";
9945
10329
  var Table_default = Table;
9946
10330
 
9947
10331
  // src/components/Table/TableBody.tsx
9948
- import { jsx as jsx344 } from "react/jsx-runtime";
10332
+ import { jsx as jsx345 } from "react/jsx-runtime";
9949
10333
  var TableBody = (props) => {
9950
10334
  const { children } = props;
9951
- return /* @__PURE__ */ jsx344("tbody", { children });
10335
+ return /* @__PURE__ */ jsx345("tbody", { children });
9952
10336
  };
9953
10337
  TableBody.displayName = "TableBody";
9954
10338
  var TableBody_default = TableBody;
9955
10339
 
9956
10340
  // src/components/Table/TableCell.tsx
9957
- import React36 from "react";
10341
+ import React37 from "react";
9958
10342
 
9959
10343
  // src/components/Table/TableHeadContext.tsx
9960
- import React34 from "react";
9961
- var TableHeadContext = React34.createContext(
10344
+ import React35 from "react";
10345
+ var TableHeadContext = React35.createContext(
9962
10346
  null
9963
10347
  );
9964
10348
  var useTableHeadContext = () => {
9965
- const ctx = React34.useContext(TableHeadContext);
10349
+ const ctx = React35.useContext(TableHeadContext);
9966
10350
  return ctx;
9967
10351
  };
9968
10352
  var TableHeadContext_default = TableHeadContext;
9969
10353
 
9970
10354
  // src/components/Table/TableRowContext.tsx
9971
- import React35 from "react";
9972
- var TableRowContext = React35.createContext(null);
10355
+ import React36 from "react";
10356
+ var TableRowContext = React36.createContext(null);
9973
10357
  var useTableRowContext = () => {
9974
- const ctx = React35.useContext(TableRowContext);
10358
+ const ctx = React36.useContext(TableRowContext);
9975
10359
  if (!ctx) throw new Error("Table components must be used inside <Table>");
9976
10360
  return ctx;
9977
10361
  };
9978
10362
  var TableRowContext_default = TableRowContext;
9979
10363
 
9980
10364
  // src/components/Table/TableCell.tsx
9981
- import { jsx as jsx345 } from "react/jsx-runtime";
9982
- var TableCell = React36.memo((props) => {
10365
+ import { jsx as jsx346 } from "react/jsx-runtime";
10366
+ var TableCell = React37.memo((props) => {
9983
10367
  const {
9984
10368
  children,
9985
10369
  align = "center",
@@ -9993,9 +10377,9 @@ var TableCell = React36.memo((props) => {
9993
10377
  const { registerStickyCell, stickyCells } = useTableRowContext();
9994
10378
  const { stickyShadow } = useTableContext();
9995
10379
  const headContext = useTableHeadContext();
9996
- const [left, setLeft] = React36.useState(0);
9997
- const cellRef = React36.useRef(null);
9998
- const calculateLeft = React36.useCallback(() => {
10380
+ const [left, setLeft] = React37.useState(0);
10381
+ const cellRef = React37.useRef(null);
10382
+ const calculateLeft = React37.useCallback(() => {
9999
10383
  if (!cellRef.current) return 0;
10000
10384
  let totalLeft = 0;
10001
10385
  for (const ref of stickyCells) {
@@ -10004,7 +10388,7 @@ var TableCell = React36.memo((props) => {
10004
10388
  }
10005
10389
  return totalLeft;
10006
10390
  }, [stickyCells]);
10007
- React36.useEffect(() => {
10391
+ React37.useEffect(() => {
10008
10392
  if (!isSticky || !cellRef.current) return;
10009
10393
  registerStickyCell(cellRef);
10010
10394
  setLeft(calculateLeft());
@@ -10023,7 +10407,7 @@ var TableCell = React36.memo((props) => {
10023
10407
  const CellTag = isHeaderCell ? "th" : "td";
10024
10408
  const isLastSticky = isSticky && stickyCells[stickyCells.length - 1] === cellRef;
10025
10409
  const enableHover = headContext && headContext.cellHover;
10026
- return /* @__PURE__ */ jsx345(
10410
+ return /* @__PURE__ */ jsx346(
10027
10411
  CellTag,
10028
10412
  {
10029
10413
  ref: cellRef,
@@ -10050,21 +10434,21 @@ TableCell.displayName = "TableCell";
10050
10434
  var TableCell_default = TableCell;
10051
10435
 
10052
10436
  // src/components/Table/TableHead.tsx
10053
- import { jsx as jsx346 } from "react/jsx-runtime";
10437
+ import { jsx as jsx347 } from "react/jsx-runtime";
10054
10438
  var TableHead = ({
10055
10439
  children,
10056
10440
  cellHover = false
10057
10441
  }) => {
10058
10442
  const { headerSticky } = useTableContext();
10059
- return /* @__PURE__ */ jsx346(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ jsx346("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
10443
+ return /* @__PURE__ */ jsx347(TableHeadContext_default.Provider, { value: { cellHover }, children: /* @__PURE__ */ jsx347("thead", { className: clsx_default(headerSticky ? "table-sticky" : null), children }) });
10060
10444
  };
10061
10445
  TableHead.displayName = "TableHead";
10062
10446
  var TableHead_default = TableHead;
10063
10447
 
10064
10448
  // src/components/Table/TableRow.tsx
10065
- import React37 from "react";
10066
- import { jsx as jsx347 } from "react/jsx-runtime";
10067
- var TableRow = React37.memo((props) => {
10449
+ import React38 from "react";
10450
+ import { jsx as jsx348 } from "react/jsx-runtime";
10451
+ var TableRow = React38.memo((props) => {
10068
10452
  const {
10069
10453
  children,
10070
10454
  type = "secondary",
@@ -10073,14 +10457,14 @@ var TableRow = React37.memo((props) => {
10073
10457
  onClick
10074
10458
  } = props;
10075
10459
  const { rowBorderUse } = useTableContext();
10076
- const [stickyCells, setStickyCells] = React37.useState([]);
10460
+ const [stickyCells, setStickyCells] = React38.useState([]);
10077
10461
  const registerStickyCell = (ref) => {
10078
10462
  setStickyCells((prev) => {
10079
10463
  if (prev.includes(ref)) return prev;
10080
10464
  return [...prev, ref];
10081
10465
  });
10082
10466
  };
10083
- return /* @__PURE__ */ jsx347(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ jsx347(
10467
+ return /* @__PURE__ */ jsx348(TableRowContext_default.Provider, { value: { stickyCells, registerStickyCell }, children: /* @__PURE__ */ jsx348(
10084
10468
  "tr",
10085
10469
  {
10086
10470
  className: clsx_default(
@@ -10104,29 +10488,31 @@ TableRow.displayName = "TableRow";
10104
10488
  var TableRow_default = TableRow;
10105
10489
 
10106
10490
  // src/components/Tag/Tag.tsx
10107
- import { jsx as jsx348, jsxs as jsxs220 } from "react/jsx-runtime";
10491
+ import { jsx as jsx349, jsxs as jsxs221 } from "react/jsx-runtime";
10108
10492
  var Tag = (props) => {
10109
10493
  const {
10110
10494
  children,
10111
- type = "neutral",
10495
+ variant,
10496
+ type,
10112
10497
  onClose,
10113
10498
  size = "md",
10114
10499
  disabled = false,
10115
10500
  colorIndex
10116
10501
  } = props;
10117
- return /* @__PURE__ */ jsxs220(
10502
+ const shape = variant ?? type ?? "neutral";
10503
+ return /* @__PURE__ */ jsxs221(
10118
10504
  "span",
10119
10505
  {
10120
10506
  className: clsx_default(
10121
10507
  "lib-xplat-tag",
10122
- type,
10508
+ shape,
10123
10509
  size,
10124
- type === "categorical" && colorIndex !== void 0 && `cat-${colorIndex}`,
10510
+ shape === "categorical" && colorIndex !== void 0 && `cat-${colorIndex}`,
10125
10511
  disabled && "disabled"
10126
10512
  ),
10127
10513
  children: [
10128
- /* @__PURE__ */ jsx348("span", { className: "tag-label", children }),
10129
- onClose && /* @__PURE__ */ jsx348("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ jsx348(XIcon_default, {}) })
10514
+ /* @__PURE__ */ jsx349("span", { className: "tag-label", children }),
10515
+ onClose && /* @__PURE__ */ jsx349("button", { className: "tag-close", onClick: onClose, "aria-label": "\uC0AD\uC81C", disabled, children: /* @__PURE__ */ jsx349(XIcon_default, {}) })
10130
10516
  ]
10131
10517
  }
10132
10518
  );
@@ -10135,24 +10521,29 @@ Tag.displayName = "Tag";
10135
10521
  var Tag_default = Tag;
10136
10522
 
10137
10523
  // src/components/TextArea/TextArea.tsx
10138
- import React38 from "react";
10139
- import { jsx as jsx349 } from "react/jsx-runtime";
10140
- var TextArea = React38.forwardRef(
10524
+ import React39 from "react";
10525
+ import { jsx as jsx350 } from "react/jsx-runtime";
10526
+ var TextArea = React39.forwardRef(
10141
10527
  (props, ref) => {
10142
10528
  const {
10143
10529
  className,
10144
10530
  size = "md",
10145
10531
  validations,
10532
+ label,
10533
+ required,
10146
10534
  resize = "vertical",
10147
10535
  rows = 3,
10148
10536
  disabled,
10149
10537
  ...textareaProps
10150
10538
  } = props;
10151
- const control = /* @__PURE__ */ jsx349("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx349(
10539
+ const autoId = React39.useId();
10540
+ const fieldId = props.id ?? autoId;
10541
+ const control = /* @__PURE__ */ jsx350("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx350(
10152
10542
  "textarea",
10153
10543
  {
10154
10544
  ...textareaProps,
10155
10545
  ref,
10546
+ id: fieldId,
10156
10547
  rows,
10157
10548
  disabled,
10158
10549
  "aria-invalid": hasError(validations) || void 0,
@@ -10160,32 +10551,166 @@ var TextArea = React38.forwardRef(
10160
10551
  style: { resize }
10161
10552
  }
10162
10553
  ) });
10163
- return /* @__PURE__ */ jsx349(Field, { validations, children: control });
10554
+ return /* @__PURE__ */ jsx350(Field, { validations, label, required, htmlFor: fieldId, children: control });
10164
10555
  }
10165
10556
  );
10166
10557
  TextArea.displayName = "TextArea";
10167
10558
  var TextArea_default = TextArea;
10168
10559
 
10560
+ // src/components/TimePicker/TimePicker.tsx
10561
+ import React40 from "react";
10562
+ import { jsx as jsx351, jsxs as jsxs222 } from "react/jsx-runtime";
10563
+ var ANIMATION_DURATION_MS4 = 200;
10564
+ var toMinutes = (hhmm) => {
10565
+ if (!hhmm) return null;
10566
+ const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
10567
+ if (!m) return null;
10568
+ const h = Number(m[1]);
10569
+ const min = Number(m[2]);
10570
+ if (h > 23 || min > 59) return null;
10571
+ return h * 60 + min;
10572
+ };
10573
+ var toHHmm = (minutes) => `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
10574
+ var display = (hhmm, use12Hours) => {
10575
+ if (!use12Hours) return hhmm;
10576
+ const total = toMinutes(hhmm);
10577
+ if (total === null) return hhmm;
10578
+ const h24 = Math.floor(total / 60);
10579
+ const mm = String(total % 60).padStart(2, "0");
10580
+ const period = h24 < 12 ? "\uC624\uC804" : "\uC624\uD6C4";
10581
+ const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
10582
+ return `${period} ${h12}:${mm}`;
10583
+ };
10584
+ var TimePicker = (props) => {
10585
+ const {
10586
+ value,
10587
+ onChange,
10588
+ step = 30,
10589
+ min,
10590
+ max,
10591
+ use12Hours = false,
10592
+ placeholder = "\uC2DC\uAC01 \uC120\uD0DD",
10593
+ disabled = false,
10594
+ size = "md",
10595
+ label,
10596
+ required,
10597
+ validations
10598
+ } = props;
10599
+ const fieldId = React40.useId();
10600
+ const triggerRef = React40.useRef(null);
10601
+ const contentRef = React40.useRef(null);
10602
+ const [isOpen, setOpen] = React40.useState(false);
10603
+ const [mounted, setMounted] = React40.useState(false);
10604
+ const [visible, setVisible] = React40.useState(false);
10605
+ const options = React40.useMemo(() => {
10606
+ const safeStep = step > 0 && step <= 720 ? step : 30;
10607
+ const lo = toMinutes(min) ?? 0;
10608
+ const hi = toMinutes(max) ?? 24 * 60 - 1;
10609
+ const out = [];
10610
+ for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
10611
+ return out;
10612
+ }, [step, min, max]);
10613
+ const close = React40.useCallback(() => setOpen(false), []);
10614
+ useClickOutside_default([triggerRef, contentRef], close, isOpen);
10615
+ useEscapeKey(isOpen, () => {
10616
+ close();
10617
+ triggerRef.current?.focus({ preventScroll: true });
10618
+ });
10619
+ const position = useAutoPosition_default(triggerRef, contentRef, mounted);
10620
+ React40.useEffect(() => {
10621
+ if (disabled && isOpen) setOpen(false);
10622
+ }, [disabled, isOpen]);
10623
+ React40.useEffect(() => {
10624
+ if (isOpen) {
10625
+ setMounted(true);
10626
+ const t2 = setTimeout(() => setVisible(true), 1);
10627
+ return () => clearTimeout(t2);
10628
+ }
10629
+ setVisible(false);
10630
+ const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS4);
10631
+ return () => clearTimeout(t);
10632
+ }, [isOpen]);
10633
+ const pick = (hhmm) => {
10634
+ onChange?.(hhmm);
10635
+ close();
10636
+ triggerRef.current?.focus({ preventScroll: true });
10637
+ };
10638
+ const control = /* @__PURE__ */ jsxs222("div", { className: clsx_default("lib-xplat-time-picker", size, disabled && "disabled"), children: [
10639
+ /* @__PURE__ */ jsx351(
10640
+ "div",
10641
+ {
10642
+ id: fieldId,
10643
+ ref: triggerRef,
10644
+ className: clsx_default("time-picker-trigger", hasError(validations) && "error"),
10645
+ role: "combobox",
10646
+ "aria-expanded": isOpen,
10647
+ "aria-haspopup": "listbox",
10648
+ "aria-invalid": hasError(validations) || void 0,
10649
+ tabIndex: disabled ? void 0 : 0,
10650
+ onClick: () => !disabled && setOpen((p) => !p),
10651
+ onKeyDown: (e) => {
10652
+ if (disabled) return;
10653
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
10654
+ e.preventDefault();
10655
+ setOpen(true);
10656
+ }
10657
+ },
10658
+ children: /* @__PURE__ */ jsx351("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
10659
+ }
10660
+ ),
10661
+ mounted && /* @__PURE__ */ jsx351(Portal_default, { children: /* @__PURE__ */ jsx351(
10662
+ "div",
10663
+ {
10664
+ ref: contentRef,
10665
+ className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit"),
10666
+ style: { ...position.position, width: triggerRef.current?.offsetWidth },
10667
+ role: "listbox",
10668
+ children: options.map((t) => /* @__PURE__ */ jsx351(
10669
+ "div",
10670
+ {
10671
+ className: clsx_default("time-picker-item", t === value && "is-selected"),
10672
+ role: "option",
10673
+ "aria-selected": t === value,
10674
+ tabIndex: 0,
10675
+ onClick: () => pick(t),
10676
+ onKeyDown: (e) => {
10677
+ if (e.key === "Enter" || e.key === " ") {
10678
+ e.preventDefault();
10679
+ pick(t);
10680
+ }
10681
+ },
10682
+ children: display(t, use12Hours)
10683
+ },
10684
+ t
10685
+ ))
10686
+ }
10687
+ ) })
10688
+ ] });
10689
+ return /* @__PURE__ */ jsx351(Field, { validations, label, required, htmlFor: fieldId, children: control });
10690
+ };
10691
+ TimePicker.displayName = "TimePicker";
10692
+ var TimePicker_default = TimePicker;
10693
+
10169
10694
  // src/components/Toast/Toast.tsx
10170
- import React39 from "react";
10695
+ import React41 from "react";
10171
10696
  import { createPortal as createPortal3 } from "react-dom";
10172
- import { jsx as jsx350, jsxs as jsxs221 } from "react/jsx-runtime";
10173
- var ToastContext = React39.createContext(null);
10697
+ import { jsx as jsx352, jsxs as jsxs223 } from "react/jsx-runtime";
10698
+ var ToastContext = React41.createContext(null);
10174
10699
  var useToast = () => {
10175
- const ctx = React39.useContext(ToastContext);
10700
+ const ctx = React41.useContext(ToastContext);
10176
10701
  if (!ctx) throw new Error("useToast must be used within ToastProvider");
10177
10702
  return ctx;
10178
10703
  };
10179
10704
  var EXIT_DURATION = 300;
10180
10705
  var ToastItemComponent = ({ item, isExiting, onClose }) => {
10181
- const ref = React39.useRef(null);
10182
- const [height, setHeight] = React39.useState(void 0);
10183
- React39.useEffect(() => {
10706
+ const ref = React41.useRef(null);
10707
+ const [height, setHeight] = React41.useState(void 0);
10708
+ React41.useEffect(() => {
10184
10709
  if (ref.current && !isExiting) {
10185
10710
  setHeight(ref.current.offsetHeight);
10186
10711
  }
10187
10712
  }, [isExiting]);
10188
- return /* @__PURE__ */ jsx350(
10713
+ return /* @__PURE__ */ jsx352(
10189
10714
  "div",
10190
10715
  {
10191
10716
  className: clsx_default("lib-xplat-toast-wrapper", { exit: isExiting }),
@@ -10193,15 +10718,15 @@ var ToastItemComponent = ({ item, isExiting, onClose }) => {
10193
10718
  maxHeight: isExiting ? 0 : height ?? "none",
10194
10719
  marginBottom: isExiting ? 0 : void 0
10195
10720
  },
10196
- children: /* @__PURE__ */ jsxs221(
10721
+ children: /* @__PURE__ */ jsxs223(
10197
10722
  "div",
10198
10723
  {
10199
10724
  ref,
10200
10725
  className: clsx_default("lib-xplat-toast", item.type, { exit: isExiting }),
10201
10726
  role: "alert",
10202
10727
  children: [
10203
- /* @__PURE__ */ jsx350("span", { className: "message", children: item.message }),
10204
- /* @__PURE__ */ jsx350("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
10728
+ /* @__PURE__ */ jsx352("span", { className: "message", children: item.message }),
10729
+ /* @__PURE__ */ jsx352("button", { className: "close-btn", onClick: onClose, "aria-label": "\uB2EB\uAE30", children: "\xD7" })
10205
10730
  ]
10206
10731
  }
10207
10732
  )
@@ -10212,13 +10737,13 @@ var ToastProvider = ({
10212
10737
  children,
10213
10738
  position = "top-right"
10214
10739
  }) => {
10215
- const [toasts, setToasts] = React39.useState([]);
10216
- const [removing, setRemoving] = React39.useState(/* @__PURE__ */ new Set());
10217
- const [mounted, setMounted] = React39.useState(false);
10218
- React39.useEffect(() => {
10740
+ const [toasts, setToasts] = React41.useState([]);
10741
+ const [removing, setRemoving] = React41.useState(/* @__PURE__ */ new Set());
10742
+ const [mounted, setMounted] = React41.useState(false);
10743
+ React41.useEffect(() => {
10219
10744
  setMounted(true);
10220
10745
  }, []);
10221
- const remove = React39.useCallback((id) => {
10746
+ const remove = React41.useCallback((id) => {
10222
10747
  setRemoving((prev) => new Set(prev).add(id));
10223
10748
  setTimeout(() => {
10224
10749
  setToasts((prev) => prev.filter((t) => t.id !== id));
@@ -10229,7 +10754,7 @@ var ToastProvider = ({
10229
10754
  });
10230
10755
  }, EXIT_DURATION);
10231
10756
  }, []);
10232
- const toast = React39.useCallback(
10757
+ const toast = React41.useCallback(
10233
10758
  (type, message, duration = 3e3) => {
10234
10759
  const id = `${Date.now()}-${Math.random()}`;
10235
10760
  setToasts((prev) => [...prev, { id, type, message }]);
@@ -10239,10 +10764,10 @@ var ToastProvider = ({
10239
10764
  },
10240
10765
  [remove]
10241
10766
  );
10242
- return /* @__PURE__ */ jsxs221(ToastContext.Provider, { value: { toast }, children: [
10767
+ return /* @__PURE__ */ jsxs223(ToastContext.Provider, { value: { toast }, children: [
10243
10768
  children,
10244
10769
  mounted && createPortal3(
10245
- /* @__PURE__ */ jsx350("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ jsx350(
10770
+ /* @__PURE__ */ jsx352("div", { className: clsx_default("lib-xplat-toast-container", position), children: toasts.map((t) => /* @__PURE__ */ jsx352(
10246
10771
  ToastItemComponent,
10247
10772
  {
10248
10773
  item: t,
@@ -10258,8 +10783,8 @@ var ToastProvider = ({
10258
10783
  ToastProvider.displayName = "ToastProvider";
10259
10784
 
10260
10785
  // src/components/Tooltip/Tooltip.tsx
10261
- import React40 from "react";
10262
- import { Fragment as Fragment6, jsx as jsx351, jsxs as jsxs222 } from "react/jsx-runtime";
10786
+ import React42 from "react";
10787
+ import { Fragment as Fragment6, jsx as jsx353, jsxs as jsxs224 } from "react/jsx-runtime";
10263
10788
  var OFFSET = 12;
10264
10789
  var GAP = 8;
10265
10790
  var SHOW_DELAY = 300;
@@ -10268,18 +10793,20 @@ var Tooltip = (props) => {
10268
10793
  children,
10269
10794
  title,
10270
10795
  description,
10271
- type = "dark",
10796
+ variant,
10797
+ type,
10272
10798
  follow = false,
10273
10799
  disabled = false
10274
10800
  } = props;
10275
- const triggerRef = React40.useRef(null);
10276
- const tooltipRef = React40.useRef(null);
10277
- const [visible, setVisible] = React40.useState(false);
10278
- const [pos, setPos] = React40.useState({ left: 0, top: 0 });
10279
- const delayTimer = React40.useRef(0);
10280
- const rafRef = React40.useRef(0);
10281
- const cursor = React40.useRef(null);
10282
- const clamp = React40.useCallback((left, top, w, h) => {
10801
+ const shape = variant ?? type ?? "dark";
10802
+ const triggerRef = React42.useRef(null);
10803
+ const tooltipRef = React42.useRef(null);
10804
+ const [visible, setVisible] = React42.useState(false);
10805
+ const [pos, setPos] = React42.useState({ left: 0, top: 0 });
10806
+ const delayTimer = React42.useRef(0);
10807
+ const rafRef = React42.useRef(0);
10808
+ const cursor = React42.useRef(null);
10809
+ const clamp = React42.useCallback((left, top, w, h) => {
10283
10810
  const vw = window.innerWidth;
10284
10811
  const vh = window.innerHeight;
10285
10812
  return {
@@ -10287,7 +10814,7 @@ var Tooltip = (props) => {
10287
10814
  top: Math.min(Math.max(GAP, top), Math.max(GAP, vh - h - GAP))
10288
10815
  };
10289
10816
  }, []);
10290
- const placeAtCursor = React40.useCallback((x, y) => {
10817
+ const placeAtCursor = React42.useCallback((x, y) => {
10291
10818
  const el = tooltipRef.current;
10292
10819
  if (!el) return;
10293
10820
  const w = el.offsetWidth;
@@ -10298,7 +10825,7 @@ var Tooltip = (props) => {
10298
10825
  if (top < GAP) top = y + OFFSET;
10299
10826
  setPos(clamp(left, top, w, h));
10300
10827
  }, [clamp]);
10301
- const placeAtTrigger = React40.useCallback(() => {
10828
+ const placeAtTrigger = React42.useCallback(() => {
10302
10829
  const el = tooltipRef.current;
10303
10830
  const trigger = triggerRef.current;
10304
10831
  if (!el || !trigger) return;
@@ -10310,19 +10837,19 @@ var Tooltip = (props) => {
10310
10837
  const left = rect.left + rect.width / 2 - w / 2;
10311
10838
  setPos(clamp(left, top, w, h));
10312
10839
  }, [clamp]);
10313
- const reposition = React40.useCallback(() => {
10840
+ const reposition = React42.useCallback(() => {
10314
10841
  if (follow && cursor.current) {
10315
10842
  placeAtCursor(cursor.current.x, cursor.current.y);
10316
10843
  } else {
10317
10844
  placeAtTrigger();
10318
10845
  }
10319
10846
  }, [follow, placeAtCursor, placeAtTrigger]);
10320
- const handleMouseEnter = React40.useCallback((e) => {
10847
+ const handleMouseEnter = React42.useCallback((e) => {
10321
10848
  if (disabled) return;
10322
10849
  cursor.current = { x: e.clientX, y: e.clientY };
10323
10850
  delayTimer.current = window.setTimeout(() => setVisible(true), SHOW_DELAY);
10324
10851
  }, [disabled]);
10325
- const handleMouseMove = React40.useCallback((e) => {
10852
+ const handleMouseMove = React42.useCallback((e) => {
10326
10853
  cursor.current = { x: e.clientX, y: e.clientY };
10327
10854
  if (!visible || !follow) return;
10328
10855
  cancelAnimationFrame(rafRef.current);
@@ -10330,25 +10857,25 @@ var Tooltip = (props) => {
10330
10857
  if (cursor.current) placeAtCursor(cursor.current.x, cursor.current.y);
10331
10858
  });
10332
10859
  }, [visible, follow, placeAtCursor]);
10333
- const close = React40.useCallback(() => {
10860
+ const close = React42.useCallback(() => {
10334
10861
  window.clearTimeout(delayTimer.current);
10335
10862
  cancelAnimationFrame(rafRef.current);
10336
10863
  setVisible(false);
10337
10864
  }, []);
10338
- const handleMouseLeave = React40.useCallback(() => {
10865
+ const handleMouseLeave = React42.useCallback(() => {
10339
10866
  cursor.current = null;
10340
10867
  close();
10341
10868
  }, [close]);
10342
- const handleFocus = React40.useCallback(() => {
10869
+ const handleFocus = React42.useCallback(() => {
10343
10870
  if (disabled) return;
10344
10871
  cursor.current = null;
10345
10872
  setVisible(true);
10346
10873
  }, [disabled]);
10347
- React40.useLayoutEffect(() => {
10874
+ React42.useLayoutEffect(() => {
10348
10875
  if (!visible) return;
10349
10876
  reposition();
10350
10877
  }, [visible, reposition]);
10351
- React40.useEffect(() => {
10878
+ React42.useEffect(() => {
10352
10879
  if (!visible || follow) return;
10353
10880
  const onChange = () => placeAtTrigger();
10354
10881
  window.addEventListener("scroll", onChange, true);
@@ -10358,12 +10885,12 @@ var Tooltip = (props) => {
10358
10885
  window.removeEventListener("resize", onChange);
10359
10886
  };
10360
10887
  }, [visible, follow, placeAtTrigger]);
10361
- React40.useEffect(() => () => {
10888
+ React42.useEffect(() => () => {
10362
10889
  window.clearTimeout(delayTimer.current);
10363
10890
  cancelAnimationFrame(rafRef.current);
10364
10891
  }, []);
10365
- if (!title && !description) return /* @__PURE__ */ jsx351(Fragment6, { children });
10366
- return /* @__PURE__ */ jsxs222(
10892
+ if (!title && !description) return /* @__PURE__ */ jsx353(Fragment6, { children });
10893
+ return /* @__PURE__ */ jsxs224(
10367
10894
  "div",
10368
10895
  {
10369
10896
  ref: triggerRef,
@@ -10376,16 +10903,16 @@ var Tooltip = (props) => {
10376
10903
  onBlur: close,
10377
10904
  children: [
10378
10905
  children,
10379
- visible && /* @__PURE__ */ jsx351(Portal_default, { children: /* @__PURE__ */ jsxs222(
10906
+ visible && /* @__PURE__ */ jsx353(Portal_default, { children: /* @__PURE__ */ jsxs224(
10380
10907
  "div",
10381
10908
  {
10382
10909
  ref: tooltipRef,
10383
10910
  role: "tooltip",
10384
- className: clsx_default("lib-xplat-tooltip", type),
10911
+ className: clsx_default("lib-xplat-tooltip", shape),
10385
10912
  style: { position: "fixed", left: pos.left, top: pos.top },
10386
10913
  children: [
10387
- title && /* @__PURE__ */ jsx351("div", { className: "tooltip-title", children: title }),
10388
- description && /* @__PURE__ */ jsx351("div", { className: "tooltip-desc", children: description })
10914
+ title && /* @__PURE__ */ jsx353("div", { className: "tooltip-title", children: title }),
10915
+ description && /* @__PURE__ */ jsx353("div", { className: "tooltip-desc", children: description })
10389
10916
  ]
10390
10917
  }
10391
10918
  ) })
@@ -10397,11 +10924,11 @@ Tooltip.displayName = "Tooltip";
10397
10924
  var Tooltip_default = Tooltip;
10398
10925
 
10399
10926
  // src/components/Video/Video.tsx
10400
- import React41 from "react";
10401
- import { jsx as jsx352, jsxs as jsxs223 } from "react/jsx-runtime";
10402
- var PipIcon = () => /* @__PURE__ */ jsxs223("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
10403
- /* @__PURE__ */ jsx352("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
10404
- /* @__PURE__ */ jsx352("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
10927
+ import React43 from "react";
10928
+ import { jsx as jsx354, jsxs as jsxs225 } from "react/jsx-runtime";
10929
+ var PipIcon = () => /* @__PURE__ */ jsxs225("svg", { viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
10930
+ /* @__PURE__ */ jsx354("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
10931
+ /* @__PURE__ */ jsx354("rect", { x: "12", y: "11", width: "7", height: "6", rx: "1", fill: "currentColor" })
10405
10932
  ] });
10406
10933
  var formatTime = (sec) => {
10407
10934
  if (!Number.isFinite(sec) || sec < 0) return "0:00";
@@ -10409,7 +10936,7 @@ var formatTime = (sec) => {
10409
10936
  const s = Math.floor(sec % 60);
10410
10937
  return `${m}:${s.toString().padStart(2, "0")}`;
10411
10938
  };
10412
- var Video = React41.forwardRef((props, ref) => {
10939
+ var Video = React43.forwardRef((props, ref) => {
10413
10940
  const {
10414
10941
  src,
10415
10942
  poster,
@@ -10433,21 +10960,21 @@ var Video = React41.forwardRef((props, ref) => {
10433
10960
  children,
10434
10961
  ...rest
10435
10962
  } = props;
10436
- const containerRef = React41.useRef(null);
10437
- const videoRef = React41.useRef(null);
10438
- const [isPlaying, setIsPlaying] = React41.useState(Boolean(autoPlay));
10439
- const [isLoaded, setIsLoaded] = React41.useState(false);
10440
- const [currentTime, setCurrentTime] = React41.useState(0);
10441
- const [duration, setDuration] = React41.useState(0);
10442
- const [buffered, setBuffered] = React41.useState(0);
10443
- const [volume, setVolume] = React41.useState(1);
10444
- const [isMuted, setIsMuted] = React41.useState(Boolean(muted));
10445
- const [isFullscreen, setIsFullscreen] = React41.useState(false);
10446
- const [playbackRate, setPlaybackRate] = React41.useState(1);
10447
- const [rateMenuOpen, setRateMenuOpen] = React41.useState(false);
10448
- const [captionsOn, setCaptionsOn] = React41.useState(false);
10449
- const [isPip, setIsPip] = React41.useState(false);
10450
- const setRefs = React41.useCallback(
10963
+ const containerRef = React43.useRef(null);
10964
+ const videoRef = React43.useRef(null);
10965
+ const [isPlaying, setIsPlaying] = React43.useState(Boolean(autoPlay));
10966
+ const [isLoaded, setIsLoaded] = React43.useState(false);
10967
+ const [currentTime, setCurrentTime] = React43.useState(0);
10968
+ const [duration, setDuration] = React43.useState(0);
10969
+ const [buffered, setBuffered] = React43.useState(0);
10970
+ const [volume, setVolume] = React43.useState(1);
10971
+ const [isMuted, setIsMuted] = React43.useState(Boolean(muted));
10972
+ const [isFullscreen, setIsFullscreen] = React43.useState(false);
10973
+ const [playbackRate, setPlaybackRate] = React43.useState(1);
10974
+ const [rateMenuOpen, setRateMenuOpen] = React43.useState(false);
10975
+ const [captionsOn, setCaptionsOn] = React43.useState(false);
10976
+ const [isPip, setIsPip] = React43.useState(false);
10977
+ const setRefs = React43.useCallback(
10451
10978
  (el) => {
10452
10979
  videoRef.current = el;
10453
10980
  if (typeof ref === "function") ref(el);
@@ -10455,14 +10982,14 @@ var Video = React41.forwardRef((props, ref) => {
10455
10982
  },
10456
10983
  [ref]
10457
10984
  );
10458
- React41.useEffect(() => {
10985
+ React43.useEffect(() => {
10459
10986
  const onFsChange = () => {
10460
10987
  setIsFullscreen(document.fullscreenElement === containerRef.current);
10461
10988
  };
10462
10989
  document.addEventListener("fullscreenchange", onFsChange);
10463
10990
  return () => document.removeEventListener("fullscreenchange", onFsChange);
10464
10991
  }, []);
10465
- React41.useEffect(() => {
10992
+ React43.useEffect(() => {
10466
10993
  const v = videoRef.current;
10467
10994
  if (!v) return;
10468
10995
  const onEnter = () => setIsPip(true);
@@ -10576,13 +11103,13 @@ var Video = React41.forwardRef((props, ref) => {
10576
11103
  const volumePct = (isMuted ? 0 : volume) * 100;
10577
11104
  const VolumeGlyph = isMuted || volume === 0 ? VolumeXIcon_default : volume < 0.5 ? VolumeIcon_default : Volume2Icon_default;
10578
11105
  const pipSupported = typeof document !== "undefined" && "pictureInPictureEnabled" in document && document.pictureInPictureEnabled;
10579
- return /* @__PURE__ */ jsxs223(
11106
+ return /* @__PURE__ */ jsxs225(
10580
11107
  "div",
10581
11108
  {
10582
11109
  ref: containerRef,
10583
11110
  className: clsx_default("lib-xplat-video", showControls && "has-controls"),
10584
11111
  children: [
10585
- /* @__PURE__ */ jsx352(
11112
+ /* @__PURE__ */ jsx354(
10586
11113
  "video",
10587
11114
  {
10588
11115
  ref: setRefs,
@@ -10603,7 +11130,7 @@ var Video = React41.forwardRef((props, ref) => {
10603
11130
  children
10604
11131
  }
10605
11132
  ),
10606
- showCenterPlay && /* @__PURE__ */ jsx352(
11133
+ showCenterPlay && /* @__PURE__ */ jsx354(
10607
11134
  "button",
10608
11135
  {
10609
11136
  type: "button",
@@ -10615,11 +11142,11 @@ var Video = React41.forwardRef((props, ref) => {
10615
11142
  onClick: togglePlay,
10616
11143
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
10617
11144
  tabIndex: -1,
10618
- children: /* @__PURE__ */ jsx352("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx352(PlayCircleIcon_default, {}) })
11145
+ children: /* @__PURE__ */ jsx354("span", { className: "center-play-icon", children: /* @__PURE__ */ jsx354(PlayCircleIcon_default, {}) })
10619
11146
  }
10620
11147
  ),
10621
- showControls && /* @__PURE__ */ jsxs223("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
10622
- /* @__PURE__ */ jsx352(
11148
+ showControls && /* @__PURE__ */ jsxs225("div", { className: "controls", onClick: (e) => e.stopPropagation(), children: [
11149
+ /* @__PURE__ */ jsx354(
10623
11150
  "input",
10624
11151
  {
10625
11152
  type: "range",
@@ -10636,29 +11163,29 @@ var Video = React41.forwardRef((props, ref) => {
10636
11163
  }
10637
11164
  }
10638
11165
  ),
10639
- /* @__PURE__ */ jsxs223("div", { className: "controls-row", children: [
10640
- /* @__PURE__ */ jsx352(
11166
+ /* @__PURE__ */ jsxs225("div", { className: "controls-row", children: [
11167
+ /* @__PURE__ */ jsx354(
10641
11168
  "button",
10642
11169
  {
10643
11170
  type: "button",
10644
11171
  className: "control-btn",
10645
11172
  onClick: togglePlay,
10646
11173
  "aria-label": isPlaying ? "\uC77C\uC2DC\uC815\uC9C0" : "\uC7AC\uC0DD",
10647
- children: isPlaying ? /* @__PURE__ */ jsx352(PauseIcon_default, {}) : /* @__PURE__ */ jsx352(PlayIcon_default, {})
11174
+ children: isPlaying ? /* @__PURE__ */ jsx354(PauseIcon_default, {}) : /* @__PURE__ */ jsx354(PlayIcon_default, {})
10648
11175
  }
10649
11176
  ),
10650
- /* @__PURE__ */ jsxs223("div", { className: "volume-group", children: [
10651
- /* @__PURE__ */ jsx352(
11177
+ /* @__PURE__ */ jsxs225("div", { className: "volume-group", children: [
11178
+ /* @__PURE__ */ jsx354(
10652
11179
  "button",
10653
11180
  {
10654
11181
  type: "button",
10655
11182
  className: "control-btn",
10656
11183
  onClick: toggleMute,
10657
11184
  "aria-label": isMuted ? "\uC74C\uC18C\uAC70 \uD574\uC81C" : "\uC74C\uC18C\uAC70",
10658
- children: /* @__PURE__ */ jsx352(VolumeGlyph, {})
11185
+ children: /* @__PURE__ */ jsx354(VolumeGlyph, {})
10659
11186
  }
10660
11187
  ),
10661
- /* @__PURE__ */ jsx352(
11188
+ /* @__PURE__ */ jsx354(
10662
11189
  "input",
10663
11190
  {
10664
11191
  type: "range",
@@ -10673,14 +11200,14 @@ var Video = React41.forwardRef((props, ref) => {
10673
11200
  }
10674
11201
  )
10675
11202
  ] }),
10676
- /* @__PURE__ */ jsxs223("span", { className: "time", children: [
11203
+ /* @__PURE__ */ jsxs225("span", { className: "time", children: [
10677
11204
  formatTime(currentTime),
10678
11205
  " / ",
10679
11206
  formatTime(duration)
10680
11207
  ] }),
10681
- /* @__PURE__ */ jsx352("div", { className: "controls-spacer" }),
10682
- playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs223("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
10683
- /* @__PURE__ */ jsxs223(
11208
+ /* @__PURE__ */ jsx354("div", { className: "controls-spacer" }),
11209
+ playbackRates && playbackRates.length > 0 && /* @__PURE__ */ jsxs225("div", { className: clsx_default("rate-group", rateMenuOpen && "is-open"), children: [
11210
+ /* @__PURE__ */ jsxs225(
10684
11211
  "button",
10685
11212
  {
10686
11213
  type: "button",
@@ -10694,7 +11221,7 @@ var Video = React41.forwardRef((props, ref) => {
10694
11221
  ]
10695
11222
  }
10696
11223
  ),
10697
- rateMenuOpen && /* @__PURE__ */ jsx352("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx352("li", { children: /* @__PURE__ */ jsxs223(
11224
+ rateMenuOpen && /* @__PURE__ */ jsx354("ul", { className: "rate-menu", role: "menu", children: playbackRates.map((r2) => /* @__PURE__ */ jsx354("li", { children: /* @__PURE__ */ jsxs225(
10698
11225
  "button",
10699
11226
  {
10700
11227
  type: "button",
@@ -10708,7 +11235,7 @@ var Video = React41.forwardRef((props, ref) => {
10708
11235
  }
10709
11236
  ) }, r2)) })
10710
11237
  ] }),
10711
- showCaptions && /* @__PURE__ */ jsx352(
11238
+ showCaptions && /* @__PURE__ */ jsx354(
10712
11239
  "button",
10713
11240
  {
10714
11241
  type: "button",
@@ -10716,37 +11243,37 @@ var Video = React41.forwardRef((props, ref) => {
10716
11243
  onClick: toggleCaptions,
10717
11244
  "aria-label": captionsOn ? "\uC790\uB9C9 \uB044\uAE30" : "\uC790\uB9C9 \uCF1C\uAE30",
10718
11245
  "aria-pressed": captionsOn,
10719
- children: /* @__PURE__ */ jsx352(TypeIcon_default, {})
11246
+ children: /* @__PURE__ */ jsx354(TypeIcon_default, {})
10720
11247
  }
10721
11248
  ),
10722
- showPip && pipSupported && /* @__PURE__ */ jsx352(
11249
+ showPip && pipSupported && /* @__PURE__ */ jsx354(
10723
11250
  "button",
10724
11251
  {
10725
11252
  type: "button",
10726
11253
  className: clsx_default("control-btn", isPip && "is-active"),
10727
11254
  onClick: togglePip,
10728
11255
  "aria-label": isPip ? "PIP \uC885\uB8CC" : "PIP",
10729
- children: /* @__PURE__ */ jsx352(PipIcon, {})
11256
+ children: /* @__PURE__ */ jsx354(PipIcon, {})
10730
11257
  }
10731
11258
  ),
10732
- showDownload && /* @__PURE__ */ jsx352(
11259
+ showDownload && /* @__PURE__ */ jsx354(
10733
11260
  "a",
10734
11261
  {
10735
11262
  className: "control-btn",
10736
11263
  href: src,
10737
11264
  download: downloadFileName ?? true,
10738
11265
  "aria-label": "\uB2E4\uC6B4\uB85C\uB4DC",
10739
- children: /* @__PURE__ */ jsx352(DownloadIcon_default, {})
11266
+ children: /* @__PURE__ */ jsx354(DownloadIcon_default, {})
10740
11267
  }
10741
11268
  ),
10742
- /* @__PURE__ */ jsx352(
11269
+ /* @__PURE__ */ jsx354(
10743
11270
  "button",
10744
11271
  {
10745
11272
  type: "button",
10746
11273
  className: "control-btn",
10747
11274
  onClick: toggleFullscreen,
10748
11275
  "aria-label": isFullscreen ? "\uC804\uCCB4\uD654\uBA74 \uC885\uB8CC" : "\uC804\uCCB4\uD654\uBA74",
10749
- children: isFullscreen ? /* @__PURE__ */ jsx352(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx352(MaximizeIcon_default, {})
11276
+ children: isFullscreen ? /* @__PURE__ */ jsx354(MinimizeIcon_default, {}) : /* @__PURE__ */ jsx354(MaximizeIcon_default, {})
10750
11277
  }
10751
11278
  )
10752
11279
  ] })
@@ -10759,7 +11286,7 @@ Video.displayName = "Video";
10759
11286
  var Video_default = Video;
10760
11287
 
10761
11288
  // src/layout/Grid/FullGrid/FullGrid.tsx
10762
- import { jsx as jsx353 } from "react/jsx-runtime";
11289
+ import { jsx as jsx355 } from "react/jsx-runtime";
10763
11290
  var GAP_MAP = {
10764
11291
  none: "var(--spacing-space-none)",
10765
11292
  xs: "var(--spacing-space-1)",
@@ -10772,13 +11299,13 @@ var GAP_MAP = {
10772
11299
  var FullGrid = (props) => {
10773
11300
  const { children, gap } = props;
10774
11301
  const style = gap != null ? { gap: GAP_MAP[gap] } : void 0;
10775
- return /* @__PURE__ */ jsx353("div", { className: "lib-xplat-full-grid", style, children });
11302
+ return /* @__PURE__ */ jsx355("div", { className: "lib-xplat-full-grid", style, children });
10776
11303
  };
10777
11304
  FullGrid.displayName = "FullGrid";
10778
11305
  var FullGrid_default = FullGrid;
10779
11306
 
10780
11307
  // src/layout/Grid/FullScreen/FullScreen.tsx
10781
- import { jsx as jsx354 } from "react/jsx-runtime";
11308
+ import { jsx as jsx356 } from "react/jsx-runtime";
10782
11309
  var GAP_MAP2 = {
10783
11310
  none: "var(--spacing-space-none)",
10784
11311
  xs: "var(--spacing-space-1)",
@@ -10791,13 +11318,13 @@ var GAP_MAP2 = {
10791
11318
  var FullScreen = (props) => {
10792
11319
  const { children, gap } = props;
10793
11320
  const style = gap != null ? { gap: GAP_MAP2[gap] } : void 0;
10794
- return /* @__PURE__ */ jsx354("div", { className: "lib-xplat-full-screen", style, children });
11321
+ return /* @__PURE__ */ jsx356("div", { className: "lib-xplat-full-screen", style, children });
10795
11322
  };
10796
11323
  FullScreen.displayName = "FullScreen";
10797
11324
  var FullScreen_default = FullScreen;
10798
11325
 
10799
11326
  // src/layout/Grid/Item/Item.tsx
10800
- import { jsx as jsx355 } from "react/jsx-runtime";
11327
+ import { jsx as jsx357 } from "react/jsx-runtime";
10801
11328
  var calculateSpans = (column) => {
10802
11329
  const spans = {};
10803
11330
  let inherited = column.default;
@@ -10814,35 +11341,35 @@ var GridItem = ({ column, children, className }) => {
10814
11341
  Object.entries(spans).forEach(([key, value]) => {
10815
11342
  style[`--column-${key}`] = value;
10816
11343
  });
10817
- return /* @__PURE__ */ jsx355("div", { className: clsx_default("lib-xplat-grid-item", className), style, children });
11344
+ return /* @__PURE__ */ jsx357("div", { className: clsx_default("lib-xplat-grid-item", className), style, children });
10818
11345
  };
10819
11346
  GridItem.displayName = "GridItem";
10820
11347
  var Item_default = GridItem;
10821
11348
 
10822
11349
  // src/layout/Header/Header.tsx
10823
- import { jsx as jsx356, jsxs as jsxs224 } from "react/jsx-runtime";
11350
+ import { jsx as jsx358, jsxs as jsxs226 } from "react/jsx-runtime";
10824
11351
  var Header = ({
10825
11352
  logo,
10826
11353
  centerContent,
10827
11354
  rightContent
10828
11355
  }) => {
10829
- return /* @__PURE__ */ jsxs224("div", { className: "lib-xplat-layout-header", children: [
10830
- /* @__PURE__ */ jsx356("div", { children: logo }),
10831
- /* @__PURE__ */ jsx356("div", { children: centerContent }),
10832
- /* @__PURE__ */ jsx356("div", { children: rightContent })
11356
+ return /* @__PURE__ */ jsxs226("div", { className: "lib-xplat-layout-header", children: [
11357
+ /* @__PURE__ */ jsx358("div", { children: logo }),
11358
+ /* @__PURE__ */ jsx358("div", { children: centerContent }),
11359
+ /* @__PURE__ */ jsx358("div", { children: rightContent })
10833
11360
  ] });
10834
11361
  };
10835
11362
  Header.displayName = "Header";
10836
11363
  var Header_default = Header;
10837
11364
 
10838
11365
  // src/layout/Layout/Layout.tsx
10839
- import { Fragment as Fragment7, jsx as jsx357, jsxs as jsxs225 } from "react/jsx-runtime";
11366
+ import { Fragment as Fragment7, jsx as jsx359, jsxs as jsxs227 } from "react/jsx-runtime";
10840
11367
  var Layout = (props) => {
10841
11368
  const { header, sideBar, children } = props;
10842
- return /* @__PURE__ */ jsx357("div", { className: "lib-xplat-layout", children: /* @__PURE__ */ jsxs225("div", { className: "lib-xplat-layout-content-wrapper", children: [
10843
- sideBar && /* @__PURE__ */ jsx357(Fragment7, { children: sideBar }),
10844
- /* @__PURE__ */ jsxs225("div", { className: "lib-xplat-layout-content", children: [
10845
- header && /* @__PURE__ */ jsx357("div", { className: "lib-xplat-layout-conent-header", children: header }),
11369
+ return /* @__PURE__ */ jsx359("div", { className: "lib-xplat-layout", children: /* @__PURE__ */ jsxs227("div", { className: "lib-xplat-layout-content-wrapper", children: [
11370
+ sideBar && /* @__PURE__ */ jsx359(Fragment7, { children: sideBar }),
11371
+ /* @__PURE__ */ jsxs227("div", { className: "lib-xplat-layout-content", children: [
11372
+ header && /* @__PURE__ */ jsx359("div", { className: "lib-xplat-layout-conent-header", children: header }),
10846
11373
  children
10847
11374
  ] })
10848
11375
  ] }) });
@@ -10851,31 +11378,31 @@ Layout.displayName = "Layout";
10851
11378
  var Layout_default = Layout;
10852
11379
 
10853
11380
  // src/layout/SideBar/SideBar.tsx
10854
- import React43 from "react";
11381
+ import React45 from "react";
10855
11382
 
10856
11383
  // src/layout/SideBar/SideBarContext.tsx
10857
- import React42 from "react";
10858
- var SideBarContext = React42.createContext(null);
11384
+ import React44 from "react";
11385
+ var SideBarContext = React44.createContext(null);
10859
11386
  var useSideBarContext = () => {
10860
- const ctx = React42.useContext(SideBarContext);
11387
+ const ctx = React44.useContext(SideBarContext);
10861
11388
  if (!ctx) throw new Error("Error");
10862
11389
  return ctx;
10863
11390
  };
10864
11391
  var SideBarContext_default = SideBarContext;
10865
11392
 
10866
11393
  // src/layout/SideBar/SideBar.tsx
10867
- import { jsx as jsx358 } from "react/jsx-runtime";
11394
+ import { jsx as jsx360 } from "react/jsx-runtime";
10868
11395
  var SideBar = (props) => {
10869
11396
  const { children, className } = props;
10870
- const [isOpen, setIsOpen] = React43.useState(true);
11397
+ const [isOpen, setIsOpen] = React45.useState(true);
10871
11398
  const handleSwitchSideBar = () => {
10872
11399
  setIsOpen((prev) => !prev);
10873
11400
  };
10874
- return /* @__PURE__ */ jsx358(
11401
+ return /* @__PURE__ */ jsx360(
10875
11402
  SideBarContext_default.Provider,
10876
11403
  {
10877
11404
  value: { isSidebarOpen: isOpen, handleSwitchSideBar },
10878
- children: /* @__PURE__ */ jsx358(
11405
+ children: /* @__PURE__ */ jsx360(
10879
11406
  "div",
10880
11407
  {
10881
11408
  className: clsx_default(
@@ -11182,6 +11709,7 @@ export {
11182
11709
  Spinner_default as Spinner,
11183
11710
  SquareIcon_default as SquareIcon,
11184
11711
  StarIcon_default as StarIcon,
11712
+ Stat_default as Stat,
11185
11713
  Steps_default as Steps,
11186
11714
  StopCircleIcon_default as StopCircleIcon,
11187
11715
  SuccessIcon_default as SuccessIcon,
@@ -11206,6 +11734,7 @@ export {
11206
11734
  ThermometerIcon_default as ThermometerIcon,
11207
11735
  ThumbsDownIcon_default as ThumbsDownIcon,
11208
11736
  ThumbsUpIcon_default as ThumbsUpIcon,
11737
+ TimePicker_default as TimePicker,
11209
11738
  ToastProvider,
11210
11739
  ToggleLeftIcon_default as ToggleLeftIcon,
11211
11740
  ToggleRightIcon_default as ToggleRightIcon,