@x-plat/design-system 0.10.0 → 0.12.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 (115) 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 +57 -16
  24. package/dist/components/Dropdown/index.css +3 -0
  25. package/dist/components/Dropdown/index.js +57 -16
  26. package/dist/components/Editor/index.cjs +779 -50
  27. package/dist/components/Editor/index.css +100 -0
  28. package/dist/components/Editor/index.d.cts +1 -1
  29. package/dist/components/Editor/index.d.ts +1 -1
  30. package/dist/components/Editor/index.js +779 -50
  31. package/dist/components/FieldMessage/index.cjs +8 -3
  32. package/dist/components/FieldMessage/index.css +15 -0
  33. package/dist/components/FieldMessage/index.d.cts +11 -4
  34. package/dist/components/FieldMessage/index.d.ts +11 -4
  35. package/dist/components/FieldMessage/index.js +8 -3
  36. package/dist/components/FileUpload/index.cjs +8 -3
  37. package/dist/components/FileUpload/index.css +15 -0
  38. package/dist/components/FileUpload/index.js +8 -3
  39. package/dist/components/ImageSelector/index.cjs +8 -3
  40. package/dist/components/ImageSelector/index.css +15 -0
  41. package/dist/components/ImageSelector/index.js +8 -3
  42. package/dist/components/Input/index.cjs +15 -5
  43. package/dist/components/Input/index.css +15 -0
  44. package/dist/components/Input/index.d.cts +4 -0
  45. package/dist/components/Input/index.d.ts +4 -0
  46. package/dist/components/Input/index.js +15 -5
  47. package/dist/components/Modal/index.cjs +84 -5
  48. package/dist/components/Modal/index.js +84 -5
  49. package/dist/components/NotificationBadge/index.d.cts +1 -1
  50. package/dist/components/NotificationBadge/index.d.ts +1 -1
  51. package/dist/components/Pagination/index.d.cts +1 -1
  52. package/dist/components/Pagination/index.d.ts +1 -1
  53. package/dist/components/PopOver/index.cjs +55 -13
  54. package/dist/components/PopOver/index.css +3 -0
  55. package/dist/components/PopOver/index.js +55 -13
  56. package/dist/components/Progress/index.d.cts +1 -1
  57. package/dist/components/Progress/index.d.ts +1 -1
  58. package/dist/components/Radio/index.cjs +8 -3
  59. package/dist/components/Radio/index.css +15 -0
  60. package/dist/components/Radio/index.d.cts +1 -1
  61. package/dist/components/Radio/index.d.ts +1 -1
  62. package/dist/components/Radio/index.js +8 -3
  63. package/dist/components/Select/index.cjs +120 -39
  64. package/dist/components/Select/index.css +57 -0
  65. package/dist/components/Select/index.d.cts +11 -0
  66. package/dist/components/Select/index.d.ts +11 -0
  67. package/dist/components/Select/index.js +120 -39
  68. package/dist/components/Spinner/index.d.cts +1 -1
  69. package/dist/components/Spinner/index.d.ts +1 -1
  70. package/dist/components/Stat/index.cjs +84 -0
  71. package/dist/components/Stat/index.css +96 -0
  72. package/dist/components/Stat/index.d.cts +37 -0
  73. package/dist/components/Stat/index.d.ts +37 -0
  74. package/dist/components/Stat/index.js +57 -0
  75. package/dist/components/Steps/index.d.cts +1 -1
  76. package/dist/components/Steps/index.d.ts +1 -1
  77. package/dist/components/Switch/index.cjs +14 -5
  78. package/dist/components/Switch/index.css +15 -0
  79. package/dist/components/Switch/index.d.cts +6 -1
  80. package/dist/components/Switch/index.d.ts +6 -1
  81. package/dist/components/Switch/index.js +14 -5
  82. package/dist/components/Tab/index.cjs +49 -25
  83. package/dist/components/Tab/index.css +4 -0
  84. package/dist/components/Tab/index.js +49 -25
  85. package/dist/components/TextArea/index.cjs +14 -4
  86. package/dist/components/TextArea/index.css +15 -0
  87. package/dist/components/TextArea/index.d.cts +4 -0
  88. package/dist/components/TextArea/index.d.ts +4 -0
  89. package/dist/components/TextArea/index.js +14 -4
  90. package/dist/components/TimePicker/index.cjs +461 -0
  91. package/dist/components/TimePicker/index.css +175 -0
  92. package/dist/components/TimePicker/index.d.cts +42 -0
  93. package/dist/components/TimePicker/index.d.ts +42 -0
  94. package/dist/components/TimePicker/index.js +424 -0
  95. package/dist/components/index.cjs +1500 -398
  96. package/dist/components/index.css +385 -0
  97. package/dist/components/index.d.cts +3 -1
  98. package/dist/components/index.d.ts +3 -1
  99. package/dist/components/index.js +1498 -398
  100. package/dist/index.cjs +1524 -422
  101. package/dist/index.css +385 -0
  102. package/dist/index.d.cts +3 -1
  103. package/dist/index.d.ts +3 -1
  104. package/dist/index.js +1522 -422
  105. package/dist/status-njWqQWFV.d.cts +20 -0
  106. package/dist/status-njWqQWFV.d.ts +20 -0
  107. package/guidelines/AGENT_PROMPT.md +3 -3
  108. package/guidelines/Guidelines.md +3 -0
  109. package/guidelines/components/editor.md +141 -0
  110. package/guidelines/components/form.md +19 -0
  111. package/guidelines/components/stat.md +31 -0
  112. package/guidelines/components/time-picker.md +49 -0
  113. package/package.json +1 -1
  114. package/dist/status-g_KP3qT6.d.cts +0 -8
  115. package/dist/status-g_KP3qT6.d.ts +0 -8
@@ -0,0 +1,461 @@
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
+ repositioning: false
56
+ });
57
+ const placedRef = import_react.default.useRef(false);
58
+ const calculatePosition = import_react.default.useCallback(() => {
59
+ if (!triggerRef.current || !popRef.current) return;
60
+ const triggerRect = triggerRef.current.getBoundingClientRect();
61
+ const popW = popRef.current.offsetWidth;
62
+ const popH = popRef.current.offsetHeight;
63
+ const viewportHeight = window.innerHeight;
64
+ const viewportWidth = window.innerWidth;
65
+ if (popH === 0 || popW === 0) return;
66
+ let direction = "bottom";
67
+ let top;
68
+ let left;
69
+ if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
70
+ direction = "top";
71
+ top = triggerRect.top - popH;
72
+ } else {
73
+ top = triggerRect.bottom;
74
+ }
75
+ left = triggerRect.left;
76
+ if (left + popW > viewportWidth - 8) {
77
+ left = triggerRect.right - popW;
78
+ }
79
+ if (left < 8) left = 8;
80
+ setPosition({
81
+ position: { top, left },
82
+ direction,
83
+ repositioning: placedRef.current
84
+ });
85
+ placedRef.current = true;
86
+ }, [triggerRef, popRef]);
87
+ import_react.default.useLayoutEffect(() => {
88
+ if (!enabled) {
89
+ placedRef.current = false;
90
+ return;
91
+ }
92
+ calculatePosition();
93
+ const raf = requestAnimationFrame(calculatePosition);
94
+ return () => cancelAnimationFrame(raf);
95
+ }, [calculatePosition, enabled]);
96
+ import_react.default.useEffect(() => {
97
+ if (!enabled || !popRef.current) return;
98
+ const observer = new ResizeObserver(() => {
99
+ calculatePosition();
100
+ });
101
+ observer.observe(popRef.current);
102
+ return () => observer.disconnect();
103
+ }, [calculatePosition, enabled, popRef]);
104
+ import_react.default.useEffect(() => {
105
+ if (!enabled) return;
106
+ let raf = 0;
107
+ const onScrollOrResize = () => {
108
+ cancelAnimationFrame(raf);
109
+ raf = requestAnimationFrame(calculatePosition);
110
+ };
111
+ window.addEventListener("resize", onScrollOrResize, { passive: true });
112
+ window.addEventListener("scroll", onScrollOrResize, { passive: true, capture: true });
113
+ return () => {
114
+ cancelAnimationFrame(raf);
115
+ window.removeEventListener("resize", onScrollOrResize);
116
+ window.removeEventListener("scroll", onScrollOrResize, true);
117
+ };
118
+ }, [calculatePosition, enabled]);
119
+ return position;
120
+ };
121
+ var useAutoPosition_default = useAutoPosition;
122
+
123
+ // src/tokens/hooks/useClickOutside.ts
124
+ var import_react2 = __toESM(require("react"), 1);
125
+ var useClickOutside = (refs, handler, enabled = true) => {
126
+ import_react2.default.useEffect(() => {
127
+ if (!enabled) return;
128
+ const refArray = Array.isArray(refs) ? refs : [refs];
129
+ const listener = (event) => {
130
+ const target = event.target;
131
+ const isInside = refArray.some(
132
+ (ref) => ref.current && ref.current.contains(target)
133
+ );
134
+ if (!isInside) {
135
+ handler();
136
+ }
137
+ };
138
+ document.addEventListener("mousedown", listener);
139
+ document.addEventListener("touchstart", listener);
140
+ return () => {
141
+ document.removeEventListener("mousedown", listener);
142
+ document.removeEventListener("touchstart", listener);
143
+ };
144
+ }, [refs, handler, enabled]);
145
+ };
146
+ var useClickOutside_default = useClickOutside;
147
+
148
+ // src/tokens/hooks/useOverlayKeyboard.ts
149
+ var import_react3 = __toESM(require("react"), 1);
150
+ var FOCUSABLE = [
151
+ "a[href]",
152
+ "button:not([disabled])",
153
+ "input:not([disabled]):not([type='hidden'])",
154
+ "select:not([disabled])",
155
+ "textarea:not([disabled])",
156
+ "[tabindex]:not([tabindex='-1'])"
157
+ ].join(",");
158
+ var useEscapeKey = (enabled, onEscape) => {
159
+ import_react3.default.useEffect(() => {
160
+ if (!enabled) return;
161
+ const onKey = (e) => {
162
+ if (e.key !== "Escape") return;
163
+ if (e.defaultPrevented) return;
164
+ e.preventDefault();
165
+ onEscape();
166
+ };
167
+ document.addEventListener("keydown", onKey);
168
+ return () => document.removeEventListener("keydown", onKey);
169
+ }, [enabled, onEscape]);
170
+ };
171
+
172
+ // ../../node_modules/clsx/dist/clsx.mjs
173
+ function r(e) {
174
+ var t, f, n = "";
175
+ if ("string" == typeof e || "number" == typeof e) n += e;
176
+ else if ("object" == typeof e) if (Array.isArray(e)) {
177
+ var o = e.length;
178
+ for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
179
+ } else for (f in e) e[f] && (n && (n += " "), n += f);
180
+ return n;
181
+ }
182
+ function clsx() {
183
+ for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
184
+ return n;
185
+ }
186
+ var clsx_default = clsx;
187
+
188
+ // src/tokens/svg/status/ErrorIcon.tsx
189
+ var import_jsx_runtime = require("react/jsx-runtime");
190
+ var ErrorIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
191
+ "svg",
192
+ {
193
+ xmlns: "http://www.w3.org/2000/svg",
194
+ width: "1em",
195
+ height: "1em",
196
+ viewBox: "0 0 16 16",
197
+ fill: "none",
198
+ children: [
199
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { clipPath: "url(#clip0_1196_9603)", children: [
200
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
201
+ "path",
202
+ {
203
+ 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",
204
+ fill: "currentColor"
205
+ }
206
+ ),
207
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
208
+ "path",
209
+ {
210
+ fillRule: "evenodd",
211
+ clipRule: "evenodd",
212
+ 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",
213
+ fill: "currentColor"
214
+ }
215
+ )
216
+ ] }),
217
+ /* @__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" }) }) })
218
+ ]
219
+ }
220
+ );
221
+ var ErrorIcon_default = ErrorIcon;
222
+
223
+ // src/tokens/svg/status/InfoIcon.tsx
224
+ var import_jsx_runtime2 = require("react/jsx-runtime");
225
+ var InfoIcon = () => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
226
+ "svg",
227
+ {
228
+ xmlns: "http://www.w3.org/2000/svg",
229
+ width: "1em",
230
+ height: "1em",
231
+ viewBox: "0 0 16 16",
232
+ fill: "none",
233
+ children: [
234
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { clipPath: "url(#clip0_1188_11261)", children: [
235
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
236
+ "path",
237
+ {
238
+ 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",
239
+ fill: "currentColor"
240
+ }
241
+ ),
242
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
243
+ "path",
244
+ {
245
+ 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",
246
+ fill: "currentColor"
247
+ }
248
+ ),
249
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
250
+ "path",
251
+ {
252
+ fillRule: "evenodd",
253
+ clipRule: "evenodd",
254
+ 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",
255
+ fill: "currentColor"
256
+ }
257
+ )
258
+ ] }),
259
+ /* @__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" }) }) })
260
+ ]
261
+ }
262
+ );
263
+ var InfoIcon_default = InfoIcon;
264
+
265
+ // src/tokens/svg/status/SuccessIcon.tsx
266
+ var import_jsx_runtime3 = require("react/jsx-runtime");
267
+ var SuccessIcon = () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
268
+ "svg",
269
+ {
270
+ xmlns: "http://www.w3.org/2000/svg",
271
+ width: "1em",
272
+ height: "1em",
273
+ viewBox: "0 0 16 16",
274
+ fill: "none",
275
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
276
+ "path",
277
+ {
278
+ 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",
279
+ fill: "currentColor"
280
+ }
281
+ )
282
+ }
283
+ );
284
+ var SuccessIcon_default = SuccessIcon;
285
+
286
+ // src/components/FieldMessage/FieldMessage.tsx
287
+ var import_jsx_runtime4 = require("react/jsx-runtime");
288
+ var ICON = {
289
+ default: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InfoIcon_default, {}),
290
+ success: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SuccessIcon_default, {}),
291
+ warning: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InfoIcon_default, {}),
292
+ error: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ErrorIcon_default, {})
293
+ };
294
+ var FieldMessage = (props) => {
295
+ const { validations } = props;
296
+ if (!validations || validations.length === 0) return null;
297
+ 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)(
298
+ "div",
299
+ {
300
+ className: clsx_default("lib-xplat-field-message", v.status),
301
+ children: [
302
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "icon", children: ICON[v.status] }),
303
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: v.message })
304
+ ]
305
+ },
306
+ `${v.message}_${idx}`
307
+ )) });
308
+ };
309
+ FieldMessage.displayName = "FieldMessage";
310
+ var Field = (props) => {
311
+ const { label, required = false, htmlFor, validations, children } = props;
312
+ const hasMessages = !!validations && validations.length > 0;
313
+ if (!label && !hasMessages) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children });
314
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lib-xplat-field", children: [
315
+ label && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "lib-xplat-field-label", htmlFor, children: [
316
+ label,
317
+ required && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "required", "aria-hidden": "true", children: "*" })
318
+ ] }),
319
+ children,
320
+ hasMessages && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FieldMessage, { validations })
321
+ ] });
322
+ };
323
+ Field.displayName = "Field";
324
+ var hasError = (validations) => !!validations?.some((v) => v.status === "error");
325
+
326
+ // src/components/TimePicker/TimePicker.tsx
327
+ var import_jsx_runtime5 = require("react/jsx-runtime");
328
+ var ANIMATION_DURATION_MS = 200;
329
+ var toMinutes = (hhmm) => {
330
+ if (!hhmm) return null;
331
+ const m = /^(\d{1,2}):(\d{2})$/.exec(hhmm.trim());
332
+ if (!m) return null;
333
+ const h = Number(m[1]);
334
+ const min = Number(m[2]);
335
+ if (h > 23 || min > 59) return null;
336
+ return h * 60 + min;
337
+ };
338
+ var toHHmm = (minutes) => `${String(Math.floor(minutes / 60)).padStart(2, "0")}:${String(minutes % 60).padStart(2, "0")}`;
339
+ var display = (hhmm, use12Hours) => {
340
+ if (!use12Hours) return hhmm;
341
+ const total = toMinutes(hhmm);
342
+ if (total === null) return hhmm;
343
+ const h24 = Math.floor(total / 60);
344
+ const mm = String(total % 60).padStart(2, "0");
345
+ const period = h24 < 12 ? "\uC624\uC804" : "\uC624\uD6C4";
346
+ const h12 = h24 % 12 === 0 ? 12 : h24 % 12;
347
+ return `${period} ${h12}:${mm}`;
348
+ };
349
+ var TimePicker = (props) => {
350
+ const {
351
+ value,
352
+ onChange,
353
+ step = 30,
354
+ min,
355
+ max,
356
+ use12Hours = false,
357
+ placeholder = "\uC2DC\uAC01 \uC120\uD0DD",
358
+ disabled = false,
359
+ size = "md",
360
+ label,
361
+ required,
362
+ validations
363
+ } = props;
364
+ const fieldId = import_react4.default.useId();
365
+ const triggerRef = import_react4.default.useRef(null);
366
+ const contentRef = import_react4.default.useRef(null);
367
+ const [isOpen, setOpen] = import_react4.default.useState(false);
368
+ const [mounted, setMounted] = import_react4.default.useState(false);
369
+ const [visible, setVisible] = import_react4.default.useState(false);
370
+ const options = import_react4.default.useMemo(() => {
371
+ const safeStep = step > 0 && step <= 720 ? step : 30;
372
+ const lo = toMinutes(min) ?? 0;
373
+ const hi = toMinutes(max) ?? 24 * 60 - 1;
374
+ const out = [];
375
+ for (let t = lo; t <= hi; t += safeStep) out.push(toHHmm(t));
376
+ return out;
377
+ }, [step, min, max]);
378
+ const close = import_react4.default.useCallback(() => setOpen(false), []);
379
+ useClickOutside_default([triggerRef, contentRef], close, isOpen);
380
+ useEscapeKey(isOpen, () => {
381
+ close();
382
+ triggerRef.current?.focus({ preventScroll: true });
383
+ });
384
+ const position = useAutoPosition_default(triggerRef, contentRef, mounted);
385
+ import_react4.default.useEffect(() => {
386
+ if (disabled && isOpen) setOpen(false);
387
+ }, [disabled, isOpen]);
388
+ import_react4.default.useEffect(() => {
389
+ if (isOpen) {
390
+ setMounted(true);
391
+ const t2 = setTimeout(() => setVisible(true), 1);
392
+ return () => clearTimeout(t2);
393
+ }
394
+ setVisible(false);
395
+ const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS);
396
+ return () => clearTimeout(t);
397
+ }, [isOpen]);
398
+ const pick = (hhmm) => {
399
+ onChange?.(hhmm);
400
+ close();
401
+ triggerRef.current?.focus({ preventScroll: true });
402
+ };
403
+ const control = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: clsx_default("lib-xplat-time-picker", size, disabled && "disabled"), children: [
404
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
405
+ "div",
406
+ {
407
+ id: fieldId,
408
+ ref: triggerRef,
409
+ className: clsx_default("time-picker-trigger", hasError(validations) && "error"),
410
+ role: "combobox",
411
+ "aria-expanded": isOpen,
412
+ "aria-haspopup": "listbox",
413
+ "aria-invalid": hasError(validations) || void 0,
414
+ tabIndex: disabled ? void 0 : 0,
415
+ onClick: () => !disabled && setOpen((p) => !p),
416
+ onKeyDown: (e) => {
417
+ if (disabled) return;
418
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
419
+ e.preventDefault();
420
+ setOpen(true);
421
+ }
422
+ },
423
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: clsx_default("time-picker-value", !value && "placeholder"), children: value ? display(value, use12Hours) : placeholder })
424
+ }
425
+ ),
426
+ mounted && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
427
+ "div",
428
+ {
429
+ ref: contentRef,
430
+ className: clsx_default("lib-xplat-time-picker-content", size, visible ? "enter" : "exit", position.repositioning && "repositioning"),
431
+ style: { ...position.position, width: triggerRef.current?.offsetWidth },
432
+ role: "listbox",
433
+ children: options.map((t) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
434
+ "div",
435
+ {
436
+ className: clsx_default("time-picker-item", t === value && "is-selected"),
437
+ role: "option",
438
+ "aria-selected": t === value,
439
+ tabIndex: 0,
440
+ onClick: () => pick(t),
441
+ onKeyDown: (e) => {
442
+ if (e.key === "Enter" || e.key === " ") {
443
+ e.preventDefault();
444
+ pick(t);
445
+ }
446
+ },
447
+ children: display(t, use12Hours)
448
+ },
449
+ t
450
+ ))
451
+ }
452
+ ) })
453
+ ] });
454
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
455
+ };
456
+ TimePicker.displayName = "TimePicker";
457
+ var TimePicker_default = TimePicker;
458
+ // Annotate the CommonJS export names for ESM import in node:
459
+ 0 && (module.exports = {
460
+ TimePicker
461
+ });
@@ -0,0 +1,175 @@
1
+ /* src/components/FieldMessage/fieldMessage.scss */
2
+ .lib-xplat-field {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--spacing-space-2);
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
+ }
22
+ .lib-xplat-field-message-wrap {
23
+ display: flex;
24
+ gap: var(--spacing-space-2);
25
+ margin-left: var(--spacing-space-1);
26
+ }
27
+ .lib-xplat-field-message-wrap > .lib-xplat-field-message {
28
+ display: flex;
29
+ gap: var(--spacing-space-1);
30
+ font-family: var(--semantic-typo-caption-2-r-font);
31
+ font-size: var(--semantic-typo-caption-2-r-size);
32
+ line-height: var(--semantic-typo-caption-2-r-lh);
33
+ font-weight: var(--semantic-typo-caption-2-r-weight);
34
+ letter-spacing: var(--semantic-typo-caption-2-r-ls);
35
+ align-items: center;
36
+ user-select: none;
37
+ }
38
+ .lib-xplat-field-message-wrap > .lib-xplat-field-message.default {
39
+ color: var(--semantic-icon-secondary);
40
+ }
41
+ .lib-xplat-field-message-wrap > .lib-xplat-field-message.success {
42
+ color: var(--semantic-text-success);
43
+ }
44
+ .lib-xplat-field-message-wrap > .lib-xplat-field-message.warning {
45
+ color: var(--semantic-text-warning);
46
+ }
47
+ .lib-xplat-field-message-wrap > .lib-xplat-field-message.error {
48
+ color: var(--semantic-text-error);
49
+ }
50
+ .lib-xplat-field-message-wrap > .lib-xplat-field-message > .icon {
51
+ font-size: var(--semantic-typo-label-2-m-size);
52
+ }
53
+
54
+ /* src/components/TimePicker/timePicker.scss */
55
+ .lib-xplat-time-picker {
56
+ position: relative;
57
+ width: 100%;
58
+ }
59
+ .lib-xplat-time-picker .time-picker-trigger {
60
+ display: flex;
61
+ align-items: center;
62
+ width: 100%;
63
+ cursor: pointer;
64
+ user-select: none;
65
+ outline: none;
66
+ border: 1px solid var(--semantic-border-primary);
67
+ border-radius: var(--spacing-radius-md);
68
+ background-color: var(--semantic-surface-neutral-primary);
69
+ color: var(--semantic-text-primary);
70
+ padding: 0 var(--spacing-space-3);
71
+ transition: border-color 0.28s cubic-bezier(0.25, 0.46, 0.45, 0.94), box-shadow 0.28s cubic-bezier(0.25, 0.46, 0.45, 0.94);
72
+ }
73
+ .lib-xplat-time-picker .time-picker-trigger:hover {
74
+ border-color: var(--semantic-border-tertiary);
75
+ }
76
+ .lib-xplat-time-picker .time-picker-trigger:focus-visible {
77
+ border-color: var(--semantic-interaction-focus-ring);
78
+ box-shadow: 0 0 0 2px var(--semantic-interaction-overlay-10);
79
+ outline: 2px solid transparent;
80
+ outline-offset: 2px;
81
+ }
82
+ .lib-xplat-time-picker .time-picker-trigger.error {
83
+ border-color: var(--semantic-border-error);
84
+ }
85
+ .lib-xplat-time-picker .time-picker-value.placeholder {
86
+ color: var(--semantic-text-tertiary);
87
+ }
88
+ .lib-xplat-time-picker.sm .time-picker-trigger {
89
+ height: var(--spacing-control-height-sm);
90
+ font-family: var(--semantic-typo-caption-1-r-font);
91
+ font-size: var(--semantic-typo-caption-1-r-size);
92
+ line-height: var(--semantic-typo-caption-1-r-lh);
93
+ font-weight: var(--semantic-typo-caption-1-r-weight);
94
+ letter-spacing: var(--semantic-typo-caption-1-r-ls);
95
+ }
96
+ .lib-xplat-time-picker.md .time-picker-trigger {
97
+ height: var(--spacing-control-height-md);
98
+ font-family: var(--semantic-typo-label-2-m-font);
99
+ font-size: var(--semantic-typo-label-2-m-size);
100
+ line-height: var(--semantic-typo-label-2-m-lh);
101
+ font-weight: var(--semantic-typo-label-2-m-weight);
102
+ letter-spacing: var(--semantic-typo-label-2-m-ls);
103
+ }
104
+ .lib-xplat-time-picker.lg .time-picker-trigger {
105
+ height: var(--spacing-control-height-lg);
106
+ font-family: var(--semantic-typo-label-1-m-font);
107
+ font-size: var(--semantic-typo-label-1-m-size);
108
+ line-height: var(--semantic-typo-label-1-m-lh);
109
+ font-weight: var(--semantic-typo-label-1-m-weight);
110
+ letter-spacing: var(--semantic-typo-label-1-m-ls);
111
+ }
112
+ .lib-xplat-time-picker.disabled .time-picker-trigger {
113
+ cursor: not-allowed;
114
+ pointer-events: none;
115
+ background-color: var(--semantic-surface-neutral-disabled);
116
+ color: var(--semantic-text-disabled);
117
+ }
118
+ .lib-xplat-time-picker-content {
119
+ position: fixed;
120
+ z-index: 1000;
121
+ max-height: 220px;
122
+ overflow-y: auto;
123
+ padding: var(--spacing-space-1) 0;
124
+ border-radius: var(--spacing-radius-md);
125
+ background-color: var(--semantic-surface-neutral-primary);
126
+ box-shadow: var(--semantic-shadow-md);
127
+ opacity: 0;
128
+ transition: opacity 0.2s ease;
129
+ }
130
+ .lib-xplat-time-picker-content.enter {
131
+ opacity: 1;
132
+ }
133
+ .lib-xplat-time-picker-content.exit {
134
+ opacity: 0;
135
+ }
136
+ .lib-xplat-time-picker-content .time-picker-item {
137
+ padding: var(--spacing-space-2) var(--spacing-space-3);
138
+ cursor: pointer;
139
+ outline: none;
140
+ color: var(--semantic-text-primary);
141
+ font-variant-numeric: tabular-nums;
142
+ transition: background-color 0.15s ease;
143
+ }
144
+ .lib-xplat-time-picker-content .time-picker-item:hover,
145
+ .lib-xplat-time-picker-content .time-picker-item:focus-visible {
146
+ background-color: var(--semantic-surface-neutral-secondary);
147
+ }
148
+ .lib-xplat-time-picker-content .time-picker-item.is-selected {
149
+ color: var(--semantic-text-brand-primary);
150
+ font-weight: var(--semantic-typo-label-2-sb-weight);
151
+ }
152
+ .lib-xplat-time-picker-content.sm .time-picker-item {
153
+ font-family: var(--semantic-typo-caption-1-r-font);
154
+ font-size: var(--semantic-typo-caption-1-r-size);
155
+ line-height: var(--semantic-typo-caption-1-r-lh);
156
+ font-weight: var(--semantic-typo-caption-1-r-weight);
157
+ letter-spacing: var(--semantic-typo-caption-1-r-ls);
158
+ }
159
+ .lib-xplat-time-picker-content.md .time-picker-item {
160
+ font-family: var(--semantic-typo-label-2-m-font);
161
+ font-size: var(--semantic-typo-label-2-m-size);
162
+ line-height: var(--semantic-typo-label-2-m-lh);
163
+ font-weight: var(--semantic-typo-label-2-m-weight);
164
+ letter-spacing: var(--semantic-typo-label-2-m-ls);
165
+ }
166
+ .lib-xplat-time-picker-content.lg .time-picker-item {
167
+ font-family: var(--semantic-typo-label-1-m-font);
168
+ font-size: var(--semantic-typo-label-1-m-size);
169
+ line-height: var(--semantic-typo-label-1-m-lh);
170
+ font-weight: var(--semantic-typo-label-1-m-weight);
171
+ letter-spacing: var(--semantic-typo-label-1-m-ls);
172
+ }
173
+ .lib-xplat-time-picker-content.repositioning {
174
+ transition: none;
175
+ }
@@ -0,0 +1,42 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React from 'react';
3
+ import { V as Validation } from '../../validation-Dqo1zqhT.cjs';
4
+
5
+ type TimePickerSize = "sm" | "md" | "lg";
6
+ interface TimePickerProps {
7
+ /** `"HH:mm"` 24시간 표기. 비어 있으면 placeholder 가 보인다 */
8
+ value?: string;
9
+ /** 시각을 고르면 `"HH:mm"` 로 준다 */
10
+ onChange?: (value: string) => void;
11
+ /** 목록 간격(분). 기본 30 — 30이면 하루 48개가 나온다 */
12
+ step?: number;
13
+ /** 고를 수 있는 가장 이른 시각 `"HH:mm"` */
14
+ min?: string;
15
+ /** 고를 수 있는 가장 늦은 시각 `"HH:mm"` */
16
+ max?: string;
17
+ /** 오전/오후 12시간 표기로 보여준다. onChange 는 그대로 24시간 `"HH:mm"` */
18
+ use12Hours?: boolean;
19
+ /** 비어 있을 때 표시할 안내 글자 */
20
+ placeholder?: string;
21
+ disabled?: boolean;
22
+ size?: TimePickerSize;
23
+ /** 컨트롤 위에 붙는 라벨. 클릭하면 컨트롤에 포커스가 간다 */
24
+ label?: React.ReactNode;
25
+ /** 라벨 뒤에 필수 표시(*)를 붙인다 */
26
+ required?: boolean;
27
+ /** 컨트롤 아래에 표시할 검증 메시지. DS 폼 컴포넌트 공통 */
28
+ validations?: Validation[];
29
+ }
30
+ /**
31
+ * 시각을 고르는 드롭다운.
32
+ *
33
+ * `DatePicker` 는 날짜 전용이다. 날짜와 시각이 함께 필요하면 둘을 나란히 두고
34
+ * 호출부에서 합친다 — `DatePicker` 에 시간을 끼워 넣으면 하위 4종의 날짜 전용
35
+ * 비교 로직을 전부 건드려야 해서 기존 사용처가 깨질 위험이 크다.
36
+ */
37
+ declare const TimePicker: {
38
+ (props: TimePickerProps): react_jsx_runtime.JSX.Element;
39
+ displayName: string;
40
+ };
41
+
42
+ export { TimePicker };