@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.
- package/dist/components/AutoResizeTextArea/index.cjs +14 -5
- package/dist/components/AutoResizeTextArea/index.css +15 -0
- package/dist/components/AutoResizeTextArea/index.d.cts +4 -0
- package/dist/components/AutoResizeTextArea/index.d.ts +4 -0
- package/dist/components/AutoResizeTextArea/index.js +14 -5
- package/dist/components/Badge/index.d.cts +1 -1
- package/dist/components/Badge/index.d.ts +1 -1
- package/dist/components/ChatInput/index.cjs +20 -7
- package/dist/components/ChatInput/index.css +15 -0
- package/dist/components/ChatInput/index.d.cts +4 -0
- package/dist/components/ChatInput/index.d.ts +4 -0
- package/dist/components/ChatInput/index.js +20 -7
- package/dist/components/CheckBox/index.cjs +8 -3
- package/dist/components/CheckBox/index.css +15 -0
- package/dist/components/CheckBox/index.d.cts +1 -1
- package/dist/components/CheckBox/index.d.ts +1 -1
- package/dist/components/CheckBox/index.js +8 -3
- package/dist/components/DatePicker/index.cjs +179 -64
- package/dist/components/DatePicker/index.css +19 -0
- package/dist/components/DatePicker/index.js +179 -64
- package/dist/components/Drawer/index.cjs +83 -4
- package/dist/components/Drawer/index.js +83 -4
- package/dist/components/Dropdown/index.cjs +57 -16
- package/dist/components/Dropdown/index.css +3 -0
- package/dist/components/Dropdown/index.js +57 -16
- package/dist/components/Editor/index.cjs +779 -50
- package/dist/components/Editor/index.css +100 -0
- package/dist/components/Editor/index.d.cts +1 -1
- package/dist/components/Editor/index.d.ts +1 -1
- package/dist/components/Editor/index.js +779 -50
- package/dist/components/FieldMessage/index.cjs +8 -3
- package/dist/components/FieldMessage/index.css +15 -0
- package/dist/components/FieldMessage/index.d.cts +11 -4
- package/dist/components/FieldMessage/index.d.ts +11 -4
- package/dist/components/FieldMessage/index.js +8 -3
- package/dist/components/FileUpload/index.cjs +8 -3
- package/dist/components/FileUpload/index.css +15 -0
- package/dist/components/FileUpload/index.js +8 -3
- package/dist/components/ImageSelector/index.cjs +8 -3
- package/dist/components/ImageSelector/index.css +15 -0
- package/dist/components/ImageSelector/index.js +8 -3
- package/dist/components/Input/index.cjs +15 -5
- package/dist/components/Input/index.css +15 -0
- package/dist/components/Input/index.d.cts +4 -0
- package/dist/components/Input/index.d.ts +4 -0
- package/dist/components/Input/index.js +15 -5
- package/dist/components/Modal/index.cjs +84 -5
- package/dist/components/Modal/index.js +84 -5
- package/dist/components/NotificationBadge/index.d.cts +1 -1
- package/dist/components/NotificationBadge/index.d.ts +1 -1
- package/dist/components/Pagination/index.d.cts +1 -1
- package/dist/components/Pagination/index.d.ts +1 -1
- package/dist/components/PopOver/index.cjs +55 -13
- package/dist/components/PopOver/index.css +3 -0
- package/dist/components/PopOver/index.js +55 -13
- package/dist/components/Progress/index.d.cts +1 -1
- package/dist/components/Progress/index.d.ts +1 -1
- package/dist/components/Radio/index.cjs +8 -3
- package/dist/components/Radio/index.css +15 -0
- package/dist/components/Radio/index.d.cts +1 -1
- package/dist/components/Radio/index.d.ts +1 -1
- package/dist/components/Radio/index.js +8 -3
- package/dist/components/Select/index.cjs +120 -39
- package/dist/components/Select/index.css +57 -0
- package/dist/components/Select/index.d.cts +11 -0
- package/dist/components/Select/index.d.ts +11 -0
- package/dist/components/Select/index.js +120 -39
- package/dist/components/Spinner/index.d.cts +1 -1
- package/dist/components/Spinner/index.d.ts +1 -1
- package/dist/components/Stat/index.cjs +84 -0
- package/dist/components/Stat/index.css +96 -0
- package/dist/components/Stat/index.d.cts +37 -0
- package/dist/components/Stat/index.d.ts +37 -0
- package/dist/components/Stat/index.js +57 -0
- package/dist/components/Steps/index.d.cts +1 -1
- package/dist/components/Steps/index.d.ts +1 -1
- package/dist/components/Switch/index.cjs +14 -5
- package/dist/components/Switch/index.css +15 -0
- package/dist/components/Switch/index.d.cts +6 -1
- package/dist/components/Switch/index.d.ts +6 -1
- package/dist/components/Switch/index.js +14 -5
- package/dist/components/Tab/index.cjs +49 -25
- package/dist/components/Tab/index.css +4 -0
- package/dist/components/Tab/index.js +49 -25
- package/dist/components/TextArea/index.cjs +14 -4
- package/dist/components/TextArea/index.css +15 -0
- package/dist/components/TextArea/index.d.cts +4 -0
- package/dist/components/TextArea/index.d.ts +4 -0
- package/dist/components/TextArea/index.js +14 -4
- package/dist/components/TimePicker/index.cjs +461 -0
- package/dist/components/TimePicker/index.css +175 -0
- package/dist/components/TimePicker/index.d.cts +42 -0
- package/dist/components/TimePicker/index.d.ts +42 -0
- package/dist/components/TimePicker/index.js +424 -0
- package/dist/components/index.cjs +1500 -398
- package/dist/components/index.css +385 -0
- package/dist/components/index.d.cts +3 -1
- package/dist/components/index.d.ts +3 -1
- package/dist/components/index.js +1498 -398
- package/dist/index.cjs +1524 -422
- package/dist/index.css +385 -0
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1522 -422
- package/dist/status-njWqQWFV.d.cts +20 -0
- package/dist/status-njWqQWFV.d.ts +20 -0
- package/guidelines/AGENT_PROMPT.md +3 -3
- package/guidelines/Guidelines.md +3 -0
- package/guidelines/components/editor.md +141 -0
- package/guidelines/components/form.md +19 -0
- package/guidelines/components/stat.md +31 -0
- package/guidelines/components/time-picker.md +49 -0
- package/package.json +1 -1
- package/dist/status-g_KP3qT6.d.cts +0 -8
- package/dist/status-g_KP3qT6.d.ts +0 -8
|
@@ -35,7 +35,7 @@ __export(PopOver_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(PopOver_exports);
|
|
36
36
|
|
|
37
37
|
// src/components/PopOver/PopOver.tsx
|
|
38
|
-
var
|
|
38
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
39
39
|
|
|
40
40
|
// src/tokens/hooks/Portal.tsx
|
|
41
41
|
var import_react_dom = __toESM(require("react-dom"), 1);
|
|
@@ -51,8 +51,10 @@ var import_react = __toESM(require("react"), 1);
|
|
|
51
51
|
var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
52
52
|
const [position, setPosition] = import_react.default.useState({
|
|
53
53
|
position: {},
|
|
54
|
-
direction: "bottom"
|
|
54
|
+
direction: "bottom",
|
|
55
|
+
repositioning: false
|
|
55
56
|
});
|
|
57
|
+
const placedRef = import_react.default.useRef(false);
|
|
56
58
|
const calculatePosition = import_react.default.useCallback(() => {
|
|
57
59
|
if (!triggerRef.current || !popRef.current) return;
|
|
58
60
|
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
@@ -77,11 +79,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
77
79
|
if (left < 8) left = 8;
|
|
78
80
|
setPosition({
|
|
79
81
|
position: { top, left },
|
|
80
|
-
direction
|
|
82
|
+
direction,
|
|
83
|
+
repositioning: placedRef.current
|
|
81
84
|
});
|
|
85
|
+
placedRef.current = true;
|
|
82
86
|
}, [triggerRef, popRef]);
|
|
83
87
|
import_react.default.useLayoutEffect(() => {
|
|
84
|
-
if (!enabled)
|
|
88
|
+
if (!enabled) {
|
|
89
|
+
placedRef.current = false;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
85
92
|
calculatePosition();
|
|
86
93
|
const raf = requestAnimationFrame(calculatePosition);
|
|
87
94
|
return () => cancelAnimationFrame(raf);
|
|
@@ -96,11 +103,17 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
96
103
|
}, [calculatePosition, enabled, popRef]);
|
|
97
104
|
import_react.default.useEffect(() => {
|
|
98
105
|
if (!enabled) return;
|
|
99
|
-
|
|
100
|
-
|
|
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 });
|
|
101
113
|
return () => {
|
|
102
|
-
|
|
103
|
-
window.removeEventListener("
|
|
114
|
+
cancelAnimationFrame(raf);
|
|
115
|
+
window.removeEventListener("resize", onScrollOrResize);
|
|
116
|
+
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
104
117
|
};
|
|
105
118
|
}, [calculatePosition, enabled]);
|
|
106
119
|
return position;
|
|
@@ -132,6 +145,30 @@ var useClickOutside = (refs, handler, enabled = true) => {
|
|
|
132
145
|
};
|
|
133
146
|
var useClickOutside_default = useClickOutside;
|
|
134
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
|
+
|
|
135
172
|
// ../../node_modules/clsx/dist/clsx.mjs
|
|
136
173
|
function r(e) {
|
|
137
174
|
var t, f, n = "";
|
|
@@ -152,13 +189,17 @@ var clsx_default = clsx;
|
|
|
152
189
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
153
190
|
var PopOver = (props) => {
|
|
154
191
|
const { children, isOpen, onClose, PopOverEl } = props;
|
|
155
|
-
const popRef =
|
|
156
|
-
const triggerRef =
|
|
157
|
-
const [localOpen, setLocalOpen] =
|
|
158
|
-
const [eventTrigger, setEventTrigger] =
|
|
192
|
+
const popRef = import_react4.default.useRef(null);
|
|
193
|
+
const triggerRef = import_react4.default.useRef(null);
|
|
194
|
+
const [localOpen, setLocalOpen] = import_react4.default.useState(false);
|
|
195
|
+
const [eventTrigger, setEventTrigger] = import_react4.default.useState(false);
|
|
159
196
|
useClickOutside_default([popRef, triggerRef], onClose, isOpen);
|
|
197
|
+
useEscapeKey(isOpen, () => {
|
|
198
|
+
onClose();
|
|
199
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
200
|
+
});
|
|
160
201
|
const position = useAutoPosition_default(triggerRef, popRef, localOpen);
|
|
161
|
-
|
|
202
|
+
import_react4.default.useEffect(() => {
|
|
162
203
|
if (isOpen) {
|
|
163
204
|
setLocalOpen(isOpen);
|
|
164
205
|
setTimeout(() => {
|
|
@@ -187,6 +228,7 @@ var PopOver = (props) => {
|
|
|
187
228
|
className: clsx_default(
|
|
188
229
|
"lib-xplat-pop-over-content",
|
|
189
230
|
position.direction,
|
|
231
|
+
position.repositioning && "repositioning",
|
|
190
232
|
eventTrigger && "visible"
|
|
191
233
|
),
|
|
192
234
|
ref: popRef,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/PopOver/PopOver.tsx
|
|
2
|
-
import
|
|
2
|
+
import React4 from "react";
|
|
3
3
|
|
|
4
4
|
// src/tokens/hooks/Portal.tsx
|
|
5
5
|
import ReactDOM from "react-dom";
|
|
@@ -15,8 +15,10 @@ import React from "react";
|
|
|
15
15
|
var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
16
16
|
const [position, setPosition] = React.useState({
|
|
17
17
|
position: {},
|
|
18
|
-
direction: "bottom"
|
|
18
|
+
direction: "bottom",
|
|
19
|
+
repositioning: false
|
|
19
20
|
});
|
|
21
|
+
const placedRef = React.useRef(false);
|
|
20
22
|
const calculatePosition = React.useCallback(() => {
|
|
21
23
|
if (!triggerRef.current || !popRef.current) return;
|
|
22
24
|
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
@@ -41,11 +43,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
41
43
|
if (left < 8) left = 8;
|
|
42
44
|
setPosition({
|
|
43
45
|
position: { top, left },
|
|
44
|
-
direction
|
|
46
|
+
direction,
|
|
47
|
+
repositioning: placedRef.current
|
|
45
48
|
});
|
|
49
|
+
placedRef.current = true;
|
|
46
50
|
}, [triggerRef, popRef]);
|
|
47
51
|
React.useLayoutEffect(() => {
|
|
48
|
-
if (!enabled)
|
|
52
|
+
if (!enabled) {
|
|
53
|
+
placedRef.current = false;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
49
56
|
calculatePosition();
|
|
50
57
|
const raf = requestAnimationFrame(calculatePosition);
|
|
51
58
|
return () => cancelAnimationFrame(raf);
|
|
@@ -60,11 +67,17 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
60
67
|
}, [calculatePosition, enabled, popRef]);
|
|
61
68
|
React.useEffect(() => {
|
|
62
69
|
if (!enabled) return;
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
let raf = 0;
|
|
71
|
+
const onScrollOrResize = () => {
|
|
72
|
+
cancelAnimationFrame(raf);
|
|
73
|
+
raf = requestAnimationFrame(calculatePosition);
|
|
74
|
+
};
|
|
75
|
+
window.addEventListener("resize", onScrollOrResize, { passive: true });
|
|
76
|
+
window.addEventListener("scroll", onScrollOrResize, { passive: true, capture: true });
|
|
65
77
|
return () => {
|
|
66
|
-
|
|
67
|
-
window.removeEventListener("
|
|
78
|
+
cancelAnimationFrame(raf);
|
|
79
|
+
window.removeEventListener("resize", onScrollOrResize);
|
|
80
|
+
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
68
81
|
};
|
|
69
82
|
}, [calculatePosition, enabled]);
|
|
70
83
|
return position;
|
|
@@ -96,6 +109,30 @@ var useClickOutside = (refs, handler, enabled = true) => {
|
|
|
96
109
|
};
|
|
97
110
|
var useClickOutside_default = useClickOutside;
|
|
98
111
|
|
|
112
|
+
// src/tokens/hooks/useOverlayKeyboard.ts
|
|
113
|
+
import React3 from "react";
|
|
114
|
+
var FOCUSABLE = [
|
|
115
|
+
"a[href]",
|
|
116
|
+
"button:not([disabled])",
|
|
117
|
+
"input:not([disabled]):not([type='hidden'])",
|
|
118
|
+
"select:not([disabled])",
|
|
119
|
+
"textarea:not([disabled])",
|
|
120
|
+
"[tabindex]:not([tabindex='-1'])"
|
|
121
|
+
].join(",");
|
|
122
|
+
var useEscapeKey = (enabled, onEscape) => {
|
|
123
|
+
React3.useEffect(() => {
|
|
124
|
+
if (!enabled) return;
|
|
125
|
+
const onKey = (e) => {
|
|
126
|
+
if (e.key !== "Escape") return;
|
|
127
|
+
if (e.defaultPrevented) return;
|
|
128
|
+
e.preventDefault();
|
|
129
|
+
onEscape();
|
|
130
|
+
};
|
|
131
|
+
document.addEventListener("keydown", onKey);
|
|
132
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
133
|
+
}, [enabled, onEscape]);
|
|
134
|
+
};
|
|
135
|
+
|
|
99
136
|
// ../../node_modules/clsx/dist/clsx.mjs
|
|
100
137
|
function r(e) {
|
|
101
138
|
var t, f, n = "";
|
|
@@ -116,13 +153,17 @@ var clsx_default = clsx;
|
|
|
116
153
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
117
154
|
var PopOver = (props) => {
|
|
118
155
|
const { children, isOpen, onClose, PopOverEl } = props;
|
|
119
|
-
const popRef =
|
|
120
|
-
const triggerRef =
|
|
121
|
-
const [localOpen, setLocalOpen] =
|
|
122
|
-
const [eventTrigger, setEventTrigger] =
|
|
156
|
+
const popRef = React4.useRef(null);
|
|
157
|
+
const triggerRef = React4.useRef(null);
|
|
158
|
+
const [localOpen, setLocalOpen] = React4.useState(false);
|
|
159
|
+
const [eventTrigger, setEventTrigger] = React4.useState(false);
|
|
123
160
|
useClickOutside_default([popRef, triggerRef], onClose, isOpen);
|
|
161
|
+
useEscapeKey(isOpen, () => {
|
|
162
|
+
onClose();
|
|
163
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
164
|
+
});
|
|
124
165
|
const position = useAutoPosition_default(triggerRef, popRef, localOpen);
|
|
125
|
-
|
|
166
|
+
React4.useEffect(() => {
|
|
126
167
|
if (isOpen) {
|
|
127
168
|
setLocalOpen(isOpen);
|
|
128
169
|
setTimeout(() => {
|
|
@@ -151,6 +192,7 @@ var PopOver = (props) => {
|
|
|
151
192
|
className: clsx_default(
|
|
152
193
|
"lib-xplat-pop-over-content",
|
|
153
194
|
position.direction,
|
|
195
|
+
position.repositioning && "repositioning",
|
|
154
196
|
eventTrigger && "visible"
|
|
155
197
|
),
|
|
156
198
|
ref: popRef,
|
|
@@ -177,11 +177,16 @@ var FieldMessage = (props) => {
|
|
|
177
177
|
};
|
|
178
178
|
FieldMessage.displayName = "FieldMessage";
|
|
179
179
|
var Field = (props) => {
|
|
180
|
-
const { validations, children } = props;
|
|
181
|
-
|
|
180
|
+
const { label, required = false, htmlFor, validations, children } = props;
|
|
181
|
+
const hasMessages = !!validations && validations.length > 0;
|
|
182
|
+
if (!label && !hasMessages) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children });
|
|
182
183
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lib-xplat-field", children: [
|
|
184
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "lib-xplat-field-label", htmlFor, children: [
|
|
185
|
+
label,
|
|
186
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "required", "aria-hidden": "true", children: "*" })
|
|
187
|
+
] }),
|
|
183
188
|
children,
|
|
184
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FieldMessage, { validations })
|
|
189
|
+
hasMessages && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FieldMessage, { validations })
|
|
185
190
|
] });
|
|
186
191
|
};
|
|
187
192
|
Field.displayName = "Field";
|
|
@@ -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);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { I as InputAttributes } from '../../attributes-DJIWir_0.cjs';
|
|
3
|
-
import { L as LegacyStatusType } from '../../status-
|
|
3
|
+
import { L as LegacyStatusType } from '../../status-njWqQWFV.cjs';
|
|
4
4
|
import { V as Validation } from '../../validation-Dqo1zqhT.cjs';
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { I as InputAttributes } from '../../attributes-DJIWir_0.js';
|
|
3
|
-
import { L as LegacyStatusType } from '../../status-
|
|
3
|
+
import { L as LegacyStatusType } from '../../status-njWqQWFV.js';
|
|
4
4
|
import { V as Validation } from '../../validation-Dqo1zqhT.js';
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
@@ -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
|
-
|
|
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";
|
|
@@ -36,7 +36,7 @@ __export(Select_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(Select_exports);
|
|
37
37
|
|
|
38
38
|
// src/components/Select/Select.tsx
|
|
39
|
-
var
|
|
39
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
40
40
|
|
|
41
41
|
// src/tokens/hooks/Portal.tsx
|
|
42
42
|
var import_react_dom = __toESM(require("react-dom"), 1);
|
|
@@ -52,8 +52,10 @@ var import_react = __toESM(require("react"), 1);
|
|
|
52
52
|
var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
53
53
|
const [position, setPosition] = import_react.default.useState({
|
|
54
54
|
position: {},
|
|
55
|
-
direction: "bottom"
|
|
55
|
+
direction: "bottom",
|
|
56
|
+
repositioning: false
|
|
56
57
|
});
|
|
58
|
+
const placedRef = import_react.default.useRef(false);
|
|
57
59
|
const calculatePosition = import_react.default.useCallback(() => {
|
|
58
60
|
if (!triggerRef.current || !popRef.current) return;
|
|
59
61
|
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
@@ -78,11 +80,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
78
80
|
if (left < 8) left = 8;
|
|
79
81
|
setPosition({
|
|
80
82
|
position: { top, left },
|
|
81
|
-
direction
|
|
83
|
+
direction,
|
|
84
|
+
repositioning: placedRef.current
|
|
82
85
|
});
|
|
86
|
+
placedRef.current = true;
|
|
83
87
|
}, [triggerRef, popRef]);
|
|
84
88
|
import_react.default.useLayoutEffect(() => {
|
|
85
|
-
if (!enabled)
|
|
89
|
+
if (!enabled) {
|
|
90
|
+
placedRef.current = false;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
86
93
|
calculatePosition();
|
|
87
94
|
const raf = requestAnimationFrame(calculatePosition);
|
|
88
95
|
return () => cancelAnimationFrame(raf);
|
|
@@ -97,11 +104,17 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
|
|
|
97
104
|
}, [calculatePosition, enabled, popRef]);
|
|
98
105
|
import_react.default.useEffect(() => {
|
|
99
106
|
if (!enabled) return;
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
let raf = 0;
|
|
108
|
+
const onScrollOrResize = () => {
|
|
109
|
+
cancelAnimationFrame(raf);
|
|
110
|
+
raf = requestAnimationFrame(calculatePosition);
|
|
111
|
+
};
|
|
112
|
+
window.addEventListener("resize", onScrollOrResize, { passive: true });
|
|
113
|
+
window.addEventListener("scroll", onScrollOrResize, { passive: true, capture: true });
|
|
102
114
|
return () => {
|
|
103
|
-
|
|
104
|
-
window.removeEventListener("
|
|
115
|
+
cancelAnimationFrame(raf);
|
|
116
|
+
window.removeEventListener("resize", onScrollOrResize);
|
|
117
|
+
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
105
118
|
};
|
|
106
119
|
}, [calculatePosition, enabled]);
|
|
107
120
|
return position;
|
|
@@ -133,6 +146,30 @@ var useClickOutside = (refs, handler, enabled = true) => {
|
|
|
133
146
|
};
|
|
134
147
|
var useClickOutside_default = useClickOutside;
|
|
135
148
|
|
|
149
|
+
// src/tokens/hooks/useOverlayKeyboard.ts
|
|
150
|
+
var import_react3 = __toESM(require("react"), 1);
|
|
151
|
+
var FOCUSABLE = [
|
|
152
|
+
"a[href]",
|
|
153
|
+
"button:not([disabled])",
|
|
154
|
+
"input:not([disabled]):not([type='hidden'])",
|
|
155
|
+
"select:not([disabled])",
|
|
156
|
+
"textarea:not([disabled])",
|
|
157
|
+
"[tabindex]:not([tabindex='-1'])"
|
|
158
|
+
].join(",");
|
|
159
|
+
var useEscapeKey = (enabled, onEscape) => {
|
|
160
|
+
import_react3.default.useEffect(() => {
|
|
161
|
+
if (!enabled) return;
|
|
162
|
+
const onKey = (e) => {
|
|
163
|
+
if (e.key !== "Escape") return;
|
|
164
|
+
if (e.defaultPrevented) return;
|
|
165
|
+
e.preventDefault();
|
|
166
|
+
onEscape();
|
|
167
|
+
};
|
|
168
|
+
document.addEventListener("keydown", onKey);
|
|
169
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
170
|
+
}, [enabled, onEscape]);
|
|
171
|
+
};
|
|
172
|
+
|
|
136
173
|
// src/tokens/svg/action/CopyIcon.tsx
|
|
137
174
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
138
175
|
|
|
@@ -1163,27 +1200,32 @@ var FieldMessage = (props) => {
|
|
|
1163
1200
|
};
|
|
1164
1201
|
FieldMessage.displayName = "FieldMessage";
|
|
1165
1202
|
var Field = (props) => {
|
|
1166
|
-
const { validations, children } = props;
|
|
1167
|
-
|
|
1203
|
+
const { label, required = false, htmlFor, validations, children } = props;
|
|
1204
|
+
const hasMessages = !!validations && validations.length > 0;
|
|
1205
|
+
if (!label && !hasMessages) return /* @__PURE__ */ (0, import_jsx_runtime295.jsx)(import_jsx_runtime295.Fragment, { children });
|
|
1168
1206
|
return /* @__PURE__ */ (0, import_jsx_runtime295.jsxs)("div", { className: "lib-xplat-field", children: [
|
|
1207
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime295.jsxs)("label", { className: "lib-xplat-field-label", htmlFor, children: [
|
|
1208
|
+
label,
|
|
1209
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime295.jsx)("span", { className: "required", "aria-hidden": "true", children: "*" })
|
|
1210
|
+
] }),
|
|
1169
1211
|
children,
|
|
1170
|
-
/* @__PURE__ */ (0, import_jsx_runtime295.jsx)(FieldMessage, { validations })
|
|
1212
|
+
hasMessages && /* @__PURE__ */ (0, import_jsx_runtime295.jsx)(FieldMessage, { validations })
|
|
1171
1213
|
] });
|
|
1172
1214
|
};
|
|
1173
1215
|
Field.displayName = "Field";
|
|
1174
1216
|
var hasError = (validations) => !!validations?.some((v) => v.status === "error");
|
|
1175
1217
|
|
|
1176
1218
|
// src/components/Select/context.ts
|
|
1177
|
-
var
|
|
1178
|
-
var SelectContext =
|
|
1219
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
1220
|
+
var SelectContext = import_react4.default.createContext(null);
|
|
1179
1221
|
var context_default = SelectContext;
|
|
1180
1222
|
|
|
1181
1223
|
// src/components/Select/SelectItem.tsx
|
|
1182
|
-
var
|
|
1224
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
1183
1225
|
var import_jsx_runtime296 = require("react/jsx-runtime");
|
|
1184
1226
|
var SelectItem = (props) => {
|
|
1185
1227
|
const { children, value, onClick, disabled = false } = props;
|
|
1186
|
-
const ctx =
|
|
1228
|
+
const ctx = import_react5.default.useContext(context_default);
|
|
1187
1229
|
const handleClick = (e) => {
|
|
1188
1230
|
e.preventDefault();
|
|
1189
1231
|
e.stopPropagation();
|
|
@@ -1223,32 +1265,37 @@ var SelectRoot = (props) => {
|
|
|
1223
1265
|
onChange,
|
|
1224
1266
|
children,
|
|
1225
1267
|
disabled = false,
|
|
1268
|
+
searchable = false,
|
|
1269
|
+
searchPlaceholder = "\uAC80\uC0C9",
|
|
1226
1270
|
error = false,
|
|
1227
1271
|
validations,
|
|
1272
|
+
label,
|
|
1273
|
+
required,
|
|
1228
1274
|
size = "md"
|
|
1229
1275
|
} = props;
|
|
1230
|
-
const
|
|
1231
|
-
|
|
1276
|
+
const fieldId = import_react6.default.useId();
|
|
1277
|
+
const itemChildren = import_react6.default.Children.toArray(children).filter(
|
|
1278
|
+
(child) => import_react6.default.isValidElement(child) && child.type === SelectItem_default
|
|
1232
1279
|
);
|
|
1233
1280
|
const isControlled = valueProp !== void 0;
|
|
1234
|
-
const [isOpen, setOpen] =
|
|
1235
|
-
const [uncontrolledLabel, setUncontrolledLabel] =
|
|
1236
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
1237
|
-
const controlledLabel =
|
|
1281
|
+
const [isOpen, setOpen] = import_react6.default.useState(false);
|
|
1282
|
+
const [uncontrolledLabel, setUncontrolledLabel] = import_react6.default.useState(null);
|
|
1283
|
+
const [uncontrolledValue, setUncontrolledValue] = import_react6.default.useState(void 0);
|
|
1284
|
+
const controlledLabel = import_react6.default.useMemo(() => {
|
|
1238
1285
|
if (!isControlled) return null;
|
|
1239
1286
|
const match = itemChildren.find((child) => child.props.value === valueProp);
|
|
1240
1287
|
return match ? match.props.children : null;
|
|
1241
1288
|
}, [isControlled, valueProp, itemChildren]);
|
|
1242
1289
|
const selectedLabel = isControlled ? controlledLabel : uncontrolledLabel;
|
|
1243
1290
|
const selectedValue = isControlled ? valueProp : uncontrolledValue;
|
|
1244
|
-
const triggerRef =
|
|
1245
|
-
const contentRef =
|
|
1246
|
-
const [mounted, setMounted] =
|
|
1247
|
-
const [visible, setVisible] =
|
|
1248
|
-
|
|
1291
|
+
const triggerRef = import_react6.default.useRef(null);
|
|
1292
|
+
const contentRef = import_react6.default.useRef(null);
|
|
1293
|
+
const [mounted, setMounted] = import_react6.default.useState(false);
|
|
1294
|
+
const [visible, setVisible] = import_react6.default.useState(false);
|
|
1295
|
+
import_react6.default.useEffect(() => {
|
|
1249
1296
|
if (disabled && isOpen) setOpen(false);
|
|
1250
1297
|
}, [disabled, isOpen]);
|
|
1251
|
-
|
|
1298
|
+
import_react6.default.useEffect(() => {
|
|
1252
1299
|
if (isOpen) {
|
|
1253
1300
|
setMounted(true);
|
|
1254
1301
|
const t2 = setTimeout(() => setVisible(true), 1);
|
|
@@ -1258,22 +1305,42 @@ var SelectRoot = (props) => {
|
|
|
1258
1305
|
const t = setTimeout(() => setMounted(false), ANIMATION_DURATION_MS);
|
|
1259
1306
|
return () => clearTimeout(t);
|
|
1260
1307
|
}, [isOpen]);
|
|
1261
|
-
const
|
|
1262
|
-
const
|
|
1263
|
-
|
|
1308
|
+
const [query, setQuery] = import_react6.default.useState("");
|
|
1309
|
+
const textOf = (node) => {
|
|
1310
|
+
if (node === null || node === void 0 || typeof node === "boolean") return "";
|
|
1311
|
+
if (typeof node === "string" || typeof node === "number") return String(node);
|
|
1312
|
+
if (Array.isArray(node)) return node.map(textOf).join("");
|
|
1313
|
+
if (import_react6.default.isValidElement(node)) return textOf(node.props.children);
|
|
1314
|
+
return "";
|
|
1315
|
+
};
|
|
1316
|
+
const visibleItems = import_react6.default.useMemo(() => {
|
|
1317
|
+
if (!searchable || !query.trim()) return itemChildren;
|
|
1318
|
+
const q = query.trim().toLowerCase();
|
|
1319
|
+
return itemChildren.filter((c) => textOf(c.props.children).toLowerCase().includes(q));
|
|
1320
|
+
}, [searchable, query, itemChildren]);
|
|
1321
|
+
const open = import_react6.default.useCallback(() => setOpen(true), []);
|
|
1322
|
+
const close = import_react6.default.useCallback(() => {
|
|
1323
|
+
setOpen(false);
|
|
1324
|
+
setQuery("");
|
|
1325
|
+
}, []);
|
|
1326
|
+
const toggle = import_react6.default.useCallback(() => setOpen((prev) => !prev), []);
|
|
1264
1327
|
useClickOutside_default([contentRef, triggerRef], close, isOpen);
|
|
1328
|
+
useEscapeKey(isOpen, () => {
|
|
1329
|
+
close();
|
|
1330
|
+
triggerRef.current?.focus({ preventScroll: true });
|
|
1331
|
+
});
|
|
1265
1332
|
const position = useAutoPosition_default(triggerRef, contentRef, mounted);
|
|
1266
|
-
const setSelected =
|
|
1267
|
-
(
|
|
1333
|
+
const setSelected = import_react6.default.useCallback(
|
|
1334
|
+
(label2, itemValue) => {
|
|
1268
1335
|
if (!isControlled) {
|
|
1269
|
-
setUncontrolledLabel(
|
|
1336
|
+
setUncontrolledLabel(label2);
|
|
1270
1337
|
setUncontrolledValue(itemValue);
|
|
1271
1338
|
}
|
|
1272
|
-
onChange?.(itemValue,
|
|
1339
|
+
onChange?.(itemValue, label2);
|
|
1273
1340
|
},
|
|
1274
1341
|
[isControlled, onChange]
|
|
1275
1342
|
);
|
|
1276
|
-
const ctxValue =
|
|
1343
|
+
const ctxValue = import_react6.default.useMemo(
|
|
1277
1344
|
() => ({
|
|
1278
1345
|
isOpen,
|
|
1279
1346
|
mounted,
|
|
@@ -1309,6 +1376,7 @@ var SelectRoot = (props) => {
|
|
|
1309
1376
|
/* @__PURE__ */ (0, import_jsx_runtime297.jsxs)(
|
|
1310
1377
|
"div",
|
|
1311
1378
|
{
|
|
1379
|
+
id: fieldId,
|
|
1312
1380
|
ref: triggerRef,
|
|
1313
1381
|
className: clsx_default(
|
|
1314
1382
|
"select-trigger",
|
|
@@ -1351,20 +1419,33 @@ var SelectRoot = (props) => {
|
|
|
1351
1419
|
]
|
|
1352
1420
|
}
|
|
1353
1421
|
),
|
|
1354
|
-
mounted && /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime297.
|
|
1422
|
+
mounted && /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(Portal_default, { children: /* @__PURE__ */ (0, import_jsx_runtime297.jsxs)(
|
|
1355
1423
|
"div",
|
|
1356
1424
|
{
|
|
1357
|
-
className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass),
|
|
1425
|
+
className: clsx_default("lib-xplat-select-content", size, position.direction, stateClass, position.repositioning && "repositioning"),
|
|
1358
1426
|
ref: contentRef,
|
|
1359
1427
|
style: { ...position.position, width: triggerRef.current?.offsetWidth },
|
|
1360
1428
|
role: "listbox",
|
|
1361
|
-
children:
|
|
1429
|
+
children: [
|
|
1430
|
+
searchable && /* @__PURE__ */ (0, import_jsx_runtime297.jsx)("div", { className: "select-search", children: /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(
|
|
1431
|
+
"input",
|
|
1432
|
+
{
|
|
1433
|
+
type: "text",
|
|
1434
|
+
value: query,
|
|
1435
|
+
placeholder: searchPlaceholder,
|
|
1436
|
+
onChange: (e) => setQuery(e.target.value),
|
|
1437
|
+
autoFocus: true,
|
|
1438
|
+
"aria-label": searchPlaceholder
|
|
1439
|
+
}
|
|
1440
|
+
) }),
|
|
1441
|
+
/* @__PURE__ */ (0, import_jsx_runtime297.jsx)(context_default.Provider, { value: ctxValue, children: visibleItems.length > 0 ? visibleItems : /* @__PURE__ */ (0, import_jsx_runtime297.jsx)("div", { className: "select-empty", children: "\uACB0\uACFC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" }) })
|
|
1442
|
+
]
|
|
1362
1443
|
}
|
|
1363
1444
|
) })
|
|
1364
1445
|
]
|
|
1365
1446
|
}
|
|
1366
1447
|
) });
|
|
1367
|
-
return /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(Field, { validations, children: control });
|
|
1448
|
+
return /* @__PURE__ */ (0, import_jsx_runtime297.jsx)(Field, { validations, label, required, htmlFor: fieldId, children: control });
|
|
1368
1449
|
};
|
|
1369
1450
|
SelectRoot.displayName = "Select";
|
|
1370
1451
|
var Select = Object.assign(SelectRoot, {
|