@x-plat/design-system 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/dist/components/AutoResizeTextArea/index.cjs +14 -5
  2. package/dist/components/AutoResizeTextArea/index.css +15 -0
  3. package/dist/components/AutoResizeTextArea/index.d.cts +4 -0
  4. package/dist/components/AutoResizeTextArea/index.d.ts +4 -0
  5. package/dist/components/AutoResizeTextArea/index.js +14 -5
  6. package/dist/components/Badge/index.d.cts +1 -1
  7. package/dist/components/Badge/index.d.ts +1 -1
  8. package/dist/components/ChatInput/index.cjs +20 -7
  9. package/dist/components/ChatInput/index.css +15 -0
  10. package/dist/components/ChatInput/index.d.cts +4 -0
  11. package/dist/components/ChatInput/index.d.ts +4 -0
  12. package/dist/components/ChatInput/index.js +20 -7
  13. package/dist/components/CheckBox/index.cjs +8 -3
  14. package/dist/components/CheckBox/index.css +15 -0
  15. package/dist/components/CheckBox/index.d.cts +1 -1
  16. package/dist/components/CheckBox/index.d.ts +1 -1
  17. package/dist/components/CheckBox/index.js +8 -3
  18. package/dist/components/DatePicker/index.cjs +179 -64
  19. package/dist/components/DatePicker/index.css +19 -0
  20. package/dist/components/DatePicker/index.js +179 -64
  21. package/dist/components/Drawer/index.cjs +83 -4
  22. package/dist/components/Drawer/index.js +83 -4
  23. package/dist/components/Dropdown/index.cjs +35 -7
  24. package/dist/components/Dropdown/index.js +35 -7
  25. package/dist/components/Editor/index.cjs +178 -21
  26. package/dist/components/Editor/index.js +178 -21
  27. package/dist/components/FieldMessage/index.cjs +8 -3
  28. package/dist/components/FieldMessage/index.css +15 -0
  29. package/dist/components/FieldMessage/index.d.cts +11 -4
  30. package/dist/components/FieldMessage/index.d.ts +11 -4
  31. package/dist/components/FieldMessage/index.js +8 -3
  32. package/dist/components/FileUpload/index.cjs +8 -3
  33. package/dist/components/FileUpload/index.css +15 -0
  34. package/dist/components/FileUpload/index.js +8 -3
  35. package/dist/components/ImageSelector/index.cjs +8 -3
  36. package/dist/components/ImageSelector/index.css +15 -0
  37. package/dist/components/ImageSelector/index.js +8 -3
  38. package/dist/components/Input/index.cjs +15 -5
  39. package/dist/components/Input/index.css +15 -0
  40. package/dist/components/Input/index.d.cts +4 -0
  41. package/dist/components/Input/index.d.ts +4 -0
  42. package/dist/components/Input/index.js +15 -5
  43. package/dist/components/Modal/index.cjs +84 -5
  44. package/dist/components/Modal/index.js +84 -5
  45. package/dist/components/NotificationBadge/index.d.cts +1 -1
  46. package/dist/components/NotificationBadge/index.d.ts +1 -1
  47. package/dist/components/Pagination/index.d.cts +1 -1
  48. package/dist/components/Pagination/index.d.ts +1 -1
  49. package/dist/components/PopOver/index.cjs +34 -6
  50. package/dist/components/PopOver/index.js +34 -6
  51. package/dist/components/Progress/index.d.cts +1 -1
  52. package/dist/components/Progress/index.d.ts +1 -1
  53. package/dist/components/Radio/index.cjs +8 -3
  54. package/dist/components/Radio/index.css +15 -0
  55. package/dist/components/Radio/index.d.cts +1 -1
  56. package/dist/components/Radio/index.d.ts +1 -1
  57. package/dist/components/Radio/index.js +8 -3
  58. package/dist/components/Select/index.cjs +99 -31
  59. package/dist/components/Select/index.css +54 -0
  60. package/dist/components/Select/index.d.cts +11 -0
  61. package/dist/components/Select/index.d.ts +11 -0
  62. package/dist/components/Select/index.js +99 -31
  63. package/dist/components/Spinner/index.d.cts +1 -1
  64. package/dist/components/Spinner/index.d.ts +1 -1
  65. package/dist/components/Stat/index.cjs +84 -0
  66. package/dist/components/Stat/index.css +96 -0
  67. package/dist/components/Stat/index.d.cts +37 -0
  68. package/dist/components/Stat/index.d.ts +37 -0
  69. package/dist/components/Stat/index.js +57 -0
  70. package/dist/components/Steps/index.d.cts +1 -1
  71. package/dist/components/Steps/index.d.ts +1 -1
  72. package/dist/components/Switch/index.cjs +14 -5
  73. package/dist/components/Switch/index.css +15 -0
  74. package/dist/components/Switch/index.d.cts +6 -1
  75. package/dist/components/Switch/index.d.ts +6 -1
  76. package/dist/components/Switch/index.js +14 -5
  77. package/dist/components/Tab/index.cjs +49 -25
  78. package/dist/components/Tab/index.css +4 -0
  79. package/dist/components/Tab/index.js +49 -25
  80. package/dist/components/TextArea/index.cjs +14 -4
  81. package/dist/components/TextArea/index.css +15 -0
  82. package/dist/components/TextArea/index.d.cts +4 -0
  83. package/dist/components/TextArea/index.d.ts +4 -0
  84. package/dist/components/TextArea/index.js +14 -4
  85. package/dist/components/TimePicker/index.cjs +448 -0
  86. package/dist/components/TimePicker/index.css +172 -0
  87. package/dist/components/TimePicker/index.d.cts +42 -0
  88. package/dist/components/TimePicker/index.d.ts +42 -0
  89. package/dist/components/TimePicker/index.js +411 -0
  90. package/dist/components/index.cjs +873 -359
  91. package/dist/components/index.css +275 -0
  92. package/dist/components/index.d.cts +3 -1
  93. package/dist/components/index.d.ts +3 -1
  94. package/dist/components/index.js +871 -359
  95. package/dist/index.cjs +897 -383
  96. package/dist/index.css +275 -0
  97. package/dist/index.d.cts +3 -1
  98. package/dist/index.d.ts +3 -1
  99. package/dist/index.js +895 -383
  100. package/dist/status-njWqQWFV.d.cts +20 -0
  101. package/dist/status-njWqQWFV.d.ts +20 -0
  102. package/guidelines/AGENT_PROMPT.md +3 -3
  103. package/guidelines/Guidelines.md +3 -0
  104. package/guidelines/components/editor.md +86 -0
  105. package/guidelines/components/form.md +19 -0
  106. package/guidelines/components/stat.md +31 -0
  107. package/guidelines/components/time-picker.md +49 -0
  108. package/package.json +1 -1
  109. package/dist/status-g_KP3qT6.d.cts +0 -8
  110. package/dist/status-g_KP3qT6.d.ts +0 -8
@@ -4,6 +4,21 @@
4
4
  flex-direction: column;
5
5
  gap: var(--spacing-space-2);
6
6
  }
7
+ .lib-xplat-field-label {
8
+ font-family: var(--semantic-typo-label-2-m-font);
9
+ font-size: var(--semantic-typo-label-2-m-size);
10
+ line-height: var(--semantic-typo-label-2-m-lh);
11
+ font-weight: var(--semantic-typo-label-2-m-weight);
12
+ letter-spacing: var(--semantic-typo-label-2-m-ls);
13
+ color: var(--semantic-text-secondary);
14
+ display: inline-flex;
15
+ align-items: center;
16
+ gap: var(--spacing-space-1);
17
+ cursor: pointer;
18
+ }
19
+ .lib-xplat-field-label > .required {
20
+ color: var(--semantic-text-error);
21
+ }
7
22
  .lib-xplat-field-message-wrap {
8
23
  display: flex;
9
24
  gap: var(--spacing-space-2);
@@ -6,6 +6,10 @@ type TextAreaSize = "sm" | "md" | "lg";
6
6
  type TextAreaResize = "none" | "vertical" | "horizontal" | "both";
7
7
  interface TextAreaProps extends Omit<TextareaAttributes, "size"> {
8
8
  /** 안쪽 여백과 글자 크기 */
9
+ /** 컨트롤 위에 붙는 라벨. 클릭하면 컨트롤에 포커스가 간다 */
10
+ label?: React.ReactNode;
11
+ /** 라벨 뒤에 필수 표시(*)를 붙인다 */
12
+ required?: boolean;
9
13
  size?: TextAreaSize;
10
14
  /** 컨트롤 아래에 표시할 검증 메시지. DS 폼 컴포넌트 공통 */
11
15
  validations?: Validation[];
@@ -6,6 +6,10 @@ type TextAreaSize = "sm" | "md" | "lg";
6
6
  type TextAreaResize = "none" | "vertical" | "horizontal" | "both";
7
7
  interface TextAreaProps extends Omit<TextareaAttributes, "size"> {
8
8
  /** 안쪽 여백과 글자 크기 */
9
+ /** 컨트롤 위에 붙는 라벨. 클릭하면 컨트롤에 포커스가 간다 */
10
+ label?: React.ReactNode;
11
+ /** 라벨 뒤에 필수 표시(*)를 붙인다 */
12
+ required?: boolean;
9
13
  size?: TextAreaSize;
10
14
  /** 컨트롤 아래에 표시할 검증 메시지. DS 폼 컴포넌트 공통 */
11
15
  validations?: Validation[];
@@ -140,11 +140,16 @@ var FieldMessage = (props) => {
140
140
  };
141
141
  FieldMessage.displayName = "FieldMessage";
142
142
  var Field = (props) => {
143
- const { validations, children } = props;
144
- if (!validations || validations.length === 0) return /* @__PURE__ */ jsx4(Fragment, { children });
143
+ const { label, required = false, htmlFor, validations, children } = props;
144
+ const hasMessages = !!validations && validations.length > 0;
145
+ if (!label && !hasMessages) return /* @__PURE__ */ jsx4(Fragment, { children });
145
146
  return /* @__PURE__ */ jsxs3("div", { className: "lib-xplat-field", children: [
147
+ label && /* @__PURE__ */ jsxs3("label", { className: "lib-xplat-field-label", htmlFor, children: [
148
+ label,
149
+ required && /* @__PURE__ */ jsx4("span", { className: "required", "aria-hidden": "true", children: "*" })
150
+ ] }),
146
151
  children,
147
- /* @__PURE__ */ jsx4(FieldMessage, { validations })
152
+ hasMessages && /* @__PURE__ */ jsx4(FieldMessage, { validations })
148
153
  ] });
149
154
  };
150
155
  Field.displayName = "Field";
@@ -158,16 +163,21 @@ var TextArea = React.forwardRef(
158
163
  className,
159
164
  size = "md",
160
165
  validations,
166
+ label,
167
+ required,
161
168
  resize = "vertical",
162
169
  rows = 3,
163
170
  disabled,
164
171
  ...textareaProps
165
172
  } = props;
173
+ const autoId = React.useId();
174
+ const fieldId = props.id ?? autoId;
166
175
  const control = /* @__PURE__ */ jsx5("div", { className: clsx_default("lib-xplat-textarea-wrap", className), children: /* @__PURE__ */ jsx5(
167
176
  "textarea",
168
177
  {
169
178
  ...textareaProps,
170
179
  ref,
180
+ id: fieldId,
171
181
  rows,
172
182
  disabled,
173
183
  "aria-invalid": hasError(validations) || void 0,
@@ -175,7 +185,7 @@ var TextArea = React.forwardRef(
175
185
  style: { resize }
176
186
  }
177
187
  ) });
178
- return /* @__PURE__ */ jsx5(Field, { validations, children: control });
188
+ return /* @__PURE__ */ jsx5(Field, { validations, label, required, htmlFor: fieldId, children: control });
179
189
  }
180
190
  );
181
191
  TextArea.displayName = "TextArea";
@@ -0,0 +1,448 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/components/TimePicker/index.ts
31
+ var TimePicker_exports = {};
32
+ __export(TimePicker_exports, {
33
+ TimePicker: () => TimePicker_default
34
+ });
35
+ module.exports = __toCommonJS(TimePicker_exports);
36
+
37
+ // src/components/TimePicker/TimePicker.tsx
38
+ var import_react4 = __toESM(require("react"), 1);
39
+
40
+ // src/tokens/hooks/Portal.tsx
41
+ var import_react_dom = __toESM(require("react-dom"), 1);
42
+ var Portal = ({ children }) => {
43
+ if (typeof document === "undefined") return null;
44
+ return import_react_dom.default.createPortal(children, document.body);
45
+ };
46
+ Portal.displayName = "Portal";
47
+ var Portal_default = Portal;
48
+
49
+ // src/tokens/hooks/useAutoPosition.ts
50
+ var import_react = __toESM(require("react"), 1);
51
+ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
52
+ const [position, setPosition] = import_react.default.useState({
53
+ position: {},
54
+ direction: "bottom"
55
+ });
56
+ const calculatePosition = import_react.default.useCallback(() => {
57
+ if (!triggerRef.current || !popRef.current) return;
58
+ const triggerRect = triggerRef.current.getBoundingClientRect();
59
+ const popW = popRef.current.offsetWidth;
60
+ const popH = popRef.current.offsetHeight;
61
+ const viewportHeight = window.innerHeight;
62
+ const viewportWidth = window.innerWidth;
63
+ if (popH === 0 || popW === 0) return;
64
+ let direction = "bottom";
65
+ let top;
66
+ let left;
67
+ if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
68
+ direction = "top";
69
+ top = triggerRect.top - popH;
70
+ } else {
71
+ top = triggerRect.bottom;
72
+ }
73
+ left = triggerRect.left;
74
+ if (left + popW > viewportWidth - 8) {
75
+ left = triggerRect.right - popW;
76
+ }
77
+ if (left < 8) left = 8;
78
+ setPosition({
79
+ position: { top, left },
80
+ direction
81
+ });
82
+ }, [triggerRef, popRef]);
83
+ import_react.default.useLayoutEffect(() => {
84
+ if (!enabled) return;
85
+ calculatePosition();
86
+ const raf = requestAnimationFrame(calculatePosition);
87
+ return () => cancelAnimationFrame(raf);
88
+ }, [calculatePosition, enabled]);
89
+ import_react.default.useEffect(() => {
90
+ if (!enabled || !popRef.current) return;
91
+ const observer = new ResizeObserver(() => {
92
+ calculatePosition();
93
+ });
94
+ observer.observe(popRef.current);
95
+ return () => observer.disconnect();
96
+ }, [calculatePosition, enabled, popRef]);
97
+ import_react.default.useEffect(() => {
98
+ if (!enabled) return;
99
+ window.addEventListener("resize", calculatePosition);
100
+ window.addEventListener("scroll", calculatePosition, true);
101
+ return () => {
102
+ window.removeEventListener("resize", calculatePosition);
103
+ window.removeEventListener("scroll", calculatePosition, true);
104
+ };
105
+ }, [calculatePosition, enabled]);
106
+ return position;
107
+ };
108
+ var useAutoPosition_default = useAutoPosition;
109
+
110
+ // src/tokens/hooks/useClickOutside.ts
111
+ var import_react2 = __toESM(require("react"), 1);
112
+ var useClickOutside = (refs, handler, enabled = true) => {
113
+ import_react2.default.useEffect(() => {
114
+ if (!enabled) return;
115
+ const refArray = Array.isArray(refs) ? refs : [refs];
116
+ const listener = (event) => {
117
+ const target = event.target;
118
+ const isInside = refArray.some(
119
+ (ref) => ref.current && ref.current.contains(target)
120
+ );
121
+ if (!isInside) {
122
+ handler();
123
+ }
124
+ };
125
+ document.addEventListener("mousedown", listener);
126
+ document.addEventListener("touchstart", listener);
127
+ return () => {
128
+ document.removeEventListener("mousedown", listener);
129
+ document.removeEventListener("touchstart", listener);
130
+ };
131
+ }, [refs, handler, enabled]);
132
+ };
133
+ var useClickOutside_default = useClickOutside;
134
+
135
+ // src/tokens/hooks/useOverlayKeyboard.ts
136
+ var import_react3 = __toESM(require("react"), 1);
137
+ var FOCUSABLE = [
138
+ "a[href]",
139
+ "button:not([disabled])",
140
+ "input:not([disabled]):not([type='hidden'])",
141
+ "select:not([disabled])",
142
+ "textarea:not([disabled])",
143
+ "[tabindex]:not([tabindex='-1'])"
144
+ ].join(",");
145
+ var useEscapeKey = (enabled, onEscape) => {
146
+ import_react3.default.useEffect(() => {
147
+ if (!enabled) return;
148
+ const onKey = (e) => {
149
+ if (e.key !== "Escape") return;
150
+ if (e.defaultPrevented) return;
151
+ e.preventDefault();
152
+ onEscape();
153
+ };
154
+ document.addEventListener("keydown", onKey);
155
+ return () => document.removeEventListener("keydown", onKey);
156
+ }, [enabled, onEscape]);
157
+ };
158
+
159
+ // ../../node_modules/clsx/dist/clsx.mjs
160
+ function r(e) {
161
+ var t, f, n = "";
162
+ if ("string" == typeof e || "number" == typeof e) n += e;
163
+ else if ("object" == typeof e) if (Array.isArray(e)) {
164
+ var o = e.length;
165
+ for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
166
+ } else for (f in e) e[f] && (n && (n += " "), n += f);
167
+ return n;
168
+ }
169
+ function clsx() {
170
+ for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
171
+ return n;
172
+ }
173
+ var clsx_default = clsx;
174
+
175
+ // src/tokens/svg/status/ErrorIcon.tsx
176
+ var import_jsx_runtime = require("react/jsx-runtime");
177
+ var ErrorIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
178
+ "svg",
179
+ {
180
+ xmlns: "http://www.w3.org/2000/svg",
181
+ width: "1em",
182
+ height: "1em",
183
+ viewBox: "0 0 16 16",
184
+ fill: "none",
185
+ children: [
186
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { clipPath: "url(#clip0_1196_9603)", children: [
187
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
188
+ "path",
189
+ {
190
+ d: "M9.57588 5.57559C9.81019 5.34127 10.19 5.34127 10.4243 5.57559C10.6586 5.8099 10.6586 6.18971 10.4243 6.42402L8.84854 7.9998L10.4243 9.57559C10.6586 9.8099 10.6586 10.1897 10.4243 10.424C10.19 10.6583 9.81019 10.6583 9.57588 10.424L8.0001 8.84824L6.42432 10.424C6.19 10.6583 5.81019 10.6583 5.57588 10.424C5.34156 10.1897 5.34156 9.8099 5.57588 9.57559L7.15166 7.9998L5.57588 6.42402C5.34156 6.18971 5.34156 5.8099 5.57588 5.57559C5.81019 5.34127 6.19 5.34127 6.42432 5.57559L8.0001 7.15137L9.57588 5.57559Z",
191
+ fill: "currentColor"
192
+ }
193
+ ),
194
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
195
+ "path",
196
+ {
197
+ fillRule: "evenodd",
198
+ clipRule: "evenodd",
199
+ d: "M8.0001 0.733398C12.0131 0.73361 15.2671 3.98679 15.2673 7.9998C15.2672 12.0129 12.0131 15.2668 8.0001 15.267C3.98701 15.2669 0.733016 12.0129 0.73291 7.9998C0.733051 3.98674 3.98704 0.733539 8.0001 0.733398ZM8.0001 1.9334C4.64978 1.93354 1.93383 4.64948 1.93369 7.9998C1.9338 11.3502 4.64975 14.0669 8.0001 14.067C11.3504 14.0668 14.0672 11.3501 14.0673 7.9998C14.0671 4.64953 11.3504 1.93361 8.0001 1.9334Z",
200
+ fill: "currentColor"
201
+ }
202
+ )
203
+ ] }),
204
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("clipPath", { id: "clip0_1196_9603", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("rect", { width: "16", height: "16", fill: "white" }) }) })
205
+ ]
206
+ }
207
+ );
208
+ var ErrorIcon_default = ErrorIcon;
209
+
210
+ // src/tokens/svg/status/InfoIcon.tsx
211
+ var import_jsx_runtime2 = require("react/jsx-runtime");
212
+ var InfoIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
213
+ "svg",
214
+ {
215
+ xmlns: "http://www.w3.org/2000/svg",
216
+ width: "1em",
217
+ height: "1em",
218
+ viewBox: "0 0 16 16",
219
+ fill: "none",
220
+ children: [
221
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { clipPath: "url(#clip0_1188_11261)", children: [
222
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
223
+ "path",
224
+ {
225
+ d: "M8.00156 7.39999C8.33293 7.39999 8.60156 7.66862 8.60156 7.99999V10.6664C8.60156 10.9978 8.33293 11.2664 8.00156 11.2664C7.67019 11.2664 7.40156 10.9978 7.40156 10.6664V7.99999C7.40156 7.66862 7.67019 7.39999 8.00156 7.39999Z",
226
+ fill: "currentColor"
227
+ }
228
+ ),
229
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
230
+ "path",
231
+ {
232
+ d: "M8.00859 4.73358C8.3398 4.73378 8.60859 5.00233 8.60859 5.33358C8.60849 5.66474 8.33973 5.93338 8.00859 5.93358H8.00156C7.67026 5.93358 7.40167 5.66486 7.40156 5.33358C7.40156 5.00221 7.67019 4.73358 8.00156 4.73358H8.00859Z",
233
+ fill: "currentColor"
234
+ }
235
+ ),
236
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
237
+ "path",
238
+ {
239
+ fillRule: "evenodd",
240
+ clipRule: "evenodd",
241
+ d: "M8.00156 0.733582C12.0146 0.733793 15.2686 3.98697 15.2688 7.99999C15.2686 12.013 12.0146 15.267 8.00156 15.2672C3.98848 15.267 0.734481 12.0131 0.734375 7.99999C0.734516 3.98693 3.9885 0.733722 8.00156 0.733582ZM8.00156 1.93358C4.65124 1.93372 1.9353 4.64967 1.93516 7.99999C1.93526 11.3503 4.65122 14.067 8.00156 14.0672C11.3518 14.067 14.0686 11.3503 14.0688 7.99999C14.0686 4.64971 11.3518 1.93379 8.00156 1.93358Z",
242
+ fill: "currentColor"
243
+ }
244
+ )
245
+ ] }),
246
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("clipPath", { id: "clip0_1188_11261", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { width: "16", height: "16", fill: "white" }) }) })
247
+ ]
248
+ }
249
+ );
250
+ var InfoIcon_default = InfoIcon;
251
+
252
+ // src/tokens/svg/status/SuccessIcon.tsx
253
+ var import_jsx_runtime3 = require("react/jsx-runtime");
254
+ var SuccessIcon = () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
255
+ "svg",
256
+ {
257
+ xmlns: "http://www.w3.org/2000/svg",
258
+ width: "1em",
259
+ height: "1em",
260
+ viewBox: "0 0 16 16",
261
+ fill: "none",
262
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
263
+ "path",
264
+ {
265
+ d: "M12.9084 3.57597C13.1426 3.34172 13.5225 3.34185 13.7568 3.57597C13.9911 3.81028 13.9911 4.19009 13.7568 4.4244L6.424 11.758C6.31157 11.8703 6.15869 11.9337 5.99978 11.9338C5.8409 11.9337 5.68798 11.8703 5.57556 11.758L2.24197 8.4244C2.00782 8.19018 2.00795 7.81028 2.24197 7.57597C2.47626 7.34167 2.85609 7.34172 3.09041 7.57597L5.999 10.4846L12.9084 3.57597Z",
266
+ fill: "currentColor"
267
+ }
268
+ )
269
+ }
270
+ );
271
+ var SuccessIcon_default = SuccessIcon;
272
+
273
+ // src/components/FieldMessage/FieldMessage.tsx
274
+ var import_jsx_runtime4 = require("react/jsx-runtime");
275
+ var ICON = {
276
+ default: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InfoIcon_default, {}),
277
+ success: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SuccessIcon_default, {}),
278
+ warning: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InfoIcon_default, {}),
279
+ error: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ErrorIcon_default, {})
280
+ };
281
+ var FieldMessage = (props) => {
282
+ const { validations } = props;
283
+ if (!validations || validations.length === 0) return null;
284
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "lib-xplat-field-message-wrap", children: validations.map((v, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
285
+ "div",
286
+ {
287
+ className: clsx_default("lib-xplat-field-message", v.status),
288
+ children: [
289
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "icon", children: ICON[v.status] }),
290
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: v.message })
291
+ ]
292
+ },
293
+ `${v.message}_${idx}`
294
+ )) });
295
+ };
296
+ FieldMessage.displayName = "FieldMessage";
297
+ var Field = (props) => {
298
+ const { label, required = false, htmlFor, validations, children } = props;
299
+ const hasMessages = !!validations && validations.length > 0;
300
+ if (!label && !hasMessages) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children });
301
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lib-xplat-field", children: [
302
+ label && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "lib-xplat-field-label", htmlFor, children: [
303
+ label,
304
+ required && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "required", "aria-hidden": "true", children: "*" })
305
+ ] }),
306
+ children,
307
+ hasMessages && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FieldMessage, { validations })
308
+ ] });
309
+ };
310
+ Field.displayName = "Field";
311
+ var hasError = (validations) => !!validations?.some((v) => v.status === "error");
312
+
313
+ // src/components/TimePicker/TimePicker.tsx
314
+ var import_jsx_runtime5 = require("react/jsx-runtime");
315
+ var ANIMATION_DURATION_MS = 200;
316
+ var toMinutes = (hhmm) => {
317
+ if (!hhmm) return null;
318
+ const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
319
+ if (!m) return null;
320
+ const h = Number(m[1]);
321
+ const min = Number(m[2]);
322
+ if (h > 23 || min > 59) return null;
323
+ return h * 60 + min;
324
+ };
325
+ var toHHmm = (minutes) => `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
326
+ var display = (hhmm, use12Hours) => {
327
+ if (!use12Hours) return hhmm;
328
+ const total = toMinutes(hhmm);
329
+ if (total === null) return hhmm;
330
+ const h24 = Math.floor(total / 60);
331
+ const mm = String(total % 60).padStart(2, "0");
332
+ const period = h24 < 12 ? "\uC624\uC804" : "\uC624\uD6C4";
333
+ const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
334
+ return `${period} ${h12}:${mm}`;
335
+ };
336
+ var TimePicker = (props) => {
337
+ const {
338
+ value,
339
+ onChange,
340
+ step = 30,
341
+ min,
342
+ max,
343
+ use12Hours = false,
344
+ placeholder = "\uC2DC\uAC01 \uC120\uD0DD",
345
+ disabled = false,
346
+ size = "md",
347
+ label,
348
+ required,
349
+ validations
350
+ } = props;
351
+ const fieldId = import_react4.default.useId();
352
+ const triggerRef = import_react4.default.useRef(null);
353
+ const contentRef = import_react4.default.useRef(null);
354
+ const [isOpen, setOpen] = import_react4.default.useState(false);
355
+ const [mounted, setMounted] = import_react4.default.useState(false);
356
+ const [visible, setVisible] = import_react4.default.useState(false);
357
+ const options = import_react4.default.useMemo(() => {
358
+ const safeStep = step > 0 && step <= 720 ? step : 30;
359
+ const lo = toMinutes(min) ?? 0;
360
+ const hi = toMinutes(max) ?? 24 * 60 - 1;
361
+ const out = [];
362
+ for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
363
+ return out;
364
+ }, [step, min, max]);
365
+ const close = import_react4.default.useCallback(() => setOpen(false), []);
366
+ useClickOutside_default([triggerRef, contentRef], close, isOpen);
367
+ useEscapeKey(isOpen, () => {
368
+ close();
369
+ triggerRef.current?.focus({ preventScroll: true });
370
+ });
371
+ const position = useAutoPosition_default(triggerRef, contentRef, mounted);
372
+ import_react4.default.useEffect(() => {
373
+ if (disabled && isOpen) setOpen(false);
374
+ }, [disabled, isOpen]);
375
+ import_react4.default.useEffect(() => {
376
+ if (isOpen) {
377
+ setMounted(true);
378
+ const t2 = setTimeout(() => setVisible(true), 1);
379
+ return () => clearTimeout(t2);
380
+ }
381
+ setVisible(false);
382
+ const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS);
383
+ return () => clearTimeout(t);
384
+ }, [isOpen]);
385
+ const pick = (hhmm) => {
386
+ onChange?.(hhmm);
387
+ close();
388
+ triggerRef.current?.focus({ preventScroll: true });
389
+ };
390
+ const control = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: clsx_default("lib-xplat-time-picker", size, disabled && "disabled"), children: [
391
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
392
+ "div",
393
+ {
394
+ id: fieldId,
395
+ ref: triggerRef,
396
+ className: clsx_default("time-picker-trigger", hasError(validations) && "error"),
397
+ role: "combobox",
398
+ "aria-expanded": isOpen,
399
+ "aria-haspopup": "listbox",
400
+ "aria-invalid": hasError(validations) || void 0,
401
+ tabIndex: disabled ? void 0 : 0,
402
+ onClick: () => !disabled && setOpen((p) => !p),
403
+ onKeyDown: (e) => {
404
+ if (disabled) return;
405
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
406
+ e.preventDefault();
407
+ setOpen(true);
408
+ }
409
+ },
410
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
411
+ }
412
+ ),
413
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
414
+ "div",
415
+ {
416
+ ref: contentRef,
417
+ className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit"),
418
+ style: { ...position.position, width: triggerRef.current?.offsetWidth },
419
+ role: "listbox",
420
+ children: options.map((t) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
421
+ "div",
422
+ {
423
+ className: clsx_default("time-picker-item", t === value && "is-selected"),
424
+ role: "option",
425
+ "aria-selected": t === value,
426
+ tabIndex: 0,
427
+ onClick: () => pick(t),
428
+ onKeyDown: (e) => {
429
+ if (e.key === "Enter" || e.key === " ") {
430
+ e.preventDefault();
431
+ pick(t);
432
+ }
433
+ },
434
+ children: display(t, use12Hours)
435
+ },
436
+ t
437
+ ))
438
+ }
439
+ ) })
440
+ ] });
441
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
442
+ };
443
+ TimePicker.displayName = "TimePicker";
444
+ var TimePicker_default = TimePicker;
445
+ // Annotate the CommonJS export names for ESM import in node:
446
+ 0 && (module.exports = {
447
+ TimePicker
448
+ });