@x-plat/design-system 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AutoResizeTextArea/index.cjs +14 -5
- package/dist/components/AutoResizeTextArea/index.css +15 -0
- package/dist/components/AutoResizeTextArea/index.d.cts +5 -0
- package/dist/components/AutoResizeTextArea/index.d.ts +5 -0
- package/dist/components/AutoResizeTextArea/index.js +14 -5
- package/dist/components/Badge/index.cjs +5 -1
- package/dist/components/Badge/index.css +1 -0
- package/dist/components/Badge/index.d.cts +1 -0
- package/dist/components/Badge/index.d.ts +1 -0
- package/dist/components/Badge/index.js +5 -1
- package/dist/components/Box/index.d.cts +3 -0
- package/dist/components/Box/index.d.ts +3 -0
- package/dist/components/Chart/index.cjs +7 -6
- package/dist/components/Chart/index.d.cts +12 -1
- package/dist/components/Chart/index.d.ts +12 -1
- package/dist/components/Chart/index.js +7 -6
- package/dist/components/ChatInput/index.cjs +20 -7
- package/dist/components/ChatInput/index.css +15 -0
- package/dist/components/ChatInput/index.d.cts +10 -0
- package/dist/components/ChatInput/index.d.ts +10 -0
- package/dist/components/ChatInput/index.js +20 -7
- package/dist/components/CheckBox/index.cjs +14 -5
- package/dist/components/CheckBox/index.css +17 -0
- package/dist/components/CheckBox/index.d.cts +10 -2
- package/dist/components/CheckBox/index.d.ts +10 -2
- package/dist/components/CheckBox/index.js +14 -5
- package/dist/components/Chip/index.d.cts +2 -0
- package/dist/components/Chip/index.d.ts +2 -0
- package/dist/components/DatePicker/index.cjs +181 -65
- package/dist/components/DatePicker/index.css +19 -0
- package/dist/components/DatePicker/index.js +181 -65
- package/dist/components/Drawer/index.cjs +83 -4
- package/dist/components/Drawer/index.d.cts +1 -0
- package/dist/components/Drawer/index.d.ts +1 -0
- package/dist/components/Drawer/index.js +83 -4
- package/dist/components/Dropdown/index.cjs +35 -7
- package/dist/components/Dropdown/index.js +35 -7
- package/dist/components/Editor/index.cjs +178 -21
- package/dist/components/Editor/index.js +178 -21
- 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.d.cts +6 -0
- package/dist/components/FileUpload/index.d.ts +6 -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.d.cts +3 -0
- package/dist/components/ImageSelector/index.d.ts +3 -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 +8 -0
- package/dist/components/Input/index.d.ts +8 -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.cjs +5 -1
- package/dist/components/NotificationBadge/index.css +1 -0
- package/dist/components/NotificationBadge/index.d.cts +6 -2
- package/dist/components/NotificationBadge/index.d.ts +6 -2
- package/dist/components/NotificationBadge/index.js +5 -1
- package/dist/components/Pagination/index.cjs +6 -2
- package/dist/components/Pagination/index.css +1 -0
- package/dist/components/Pagination/index.d.cts +13 -2
- package/dist/components/Pagination/index.d.ts +13 -2
- package/dist/components/Pagination/index.js +6 -2
- package/dist/components/PopOver/index.cjs +34 -6
- package/dist/components/PopOver/index.js +34 -6
- package/dist/components/Progress/index.cjs +6 -2
- package/dist/components/Progress/index.css +1 -0
- package/dist/components/Progress/index.d.cts +11 -2
- package/dist/components/Progress/index.d.ts +11 -2
- package/dist/components/Progress/index.js +6 -2
- package/dist/components/Radio/index.cjs +14 -5
- package/dist/components/Radio/index.css +17 -0
- package/dist/components/Radio/index.d.cts +11 -2
- package/dist/components/Radio/index.d.ts +11 -2
- package/dist/components/Radio/index.js +14 -5
- package/dist/components/Select/index.cjs +99 -31
- package/dist/components/Select/index.css +54 -0
- package/dist/components/Select/index.d.cts +16 -1
- package/dist/components/Select/index.d.ts +16 -1
- package/dist/components/Select/index.js +99 -31
- package/dist/components/Skeleton/index.d.cts +3 -0
- package/dist/components/Skeleton/index.d.ts +3 -0
- package/dist/components/Spinner/index.cjs +6 -2
- package/dist/components/Spinner/index.css +1 -0
- package/dist/components/Spinner/index.d.cts +8 -2
- package/dist/components/Spinner/index.d.ts +8 -2
- package/dist/components/Spinner/index.js +6 -2
- 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.cjs +6 -2
- package/dist/components/Steps/index.css +11 -0
- package/dist/components/Steps/index.d.cts +9 -2
- package/dist/components/Steps/index.d.ts +9 -2
- package/dist/components/Steps/index.js +6 -2
- package/dist/components/Switch/index.cjs +20 -7
- package/dist/components/Switch/index.css +17 -0
- package/dist/components/Switch/index.d.cts +15 -2
- package/dist/components/Switch/index.d.ts +15 -2
- package/dist/components/Switch/index.js +20 -7
- package/dist/components/Tab/index.cjs +51 -26
- package/dist/components/Tab/index.css +4 -0
- package/dist/components/Tab/index.d.cts +12 -1
- package/dist/components/Tab/index.d.ts +12 -1
- package/dist/components/Tab/index.js +51 -26
- package/dist/components/Tag/index.cjs +5 -3
- package/dist/components/Tag/index.d.cts +12 -2
- package/dist/components/Tag/index.d.ts +12 -2
- package/dist/components/Tag/index.js +5 -3
- package/dist/components/TextArea/index.cjs +14 -4
- package/dist/components/TextArea/index.css +15 -0
- package/dist/components/TextArea/index.d.cts +7 -0
- package/dist/components/TextArea/index.d.ts +7 -0
- package/dist/components/TextArea/index.js +14 -4
- package/dist/components/TimePicker/index.cjs +448 -0
- package/dist/components/TimePicker/index.css +172 -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 +411 -0
- package/dist/components/Tooltip/index.cjs +4 -2
- package/dist/components/Tooltip/index.d.cts +11 -1
- package/dist/components/Tooltip/index.d.ts +11 -1
- package/dist/components/Tooltip/index.js +4 -2
- package/dist/components/index.cjs +916 -385
- package/dist/components/index.css +296 -0
- package/dist/components/index.d.cts +3 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.js +914 -385
- package/dist/index.cjs +940 -409
- package/dist/index.css +296 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +938 -409
- package/dist/status-njWqQWFV.d.cts +20 -0
- package/dist/status-njWqQWFV.d.ts +20 -0
- package/guidelines/AGENT_PROMPT.md +18 -3
- package/guidelines/Guidelines.md +3 -0
- package/guidelines/components/card.md +3 -3
- package/guidelines/components/editor.md +86 -0
- package/guidelines/components/feedback.md +1 -1
- package/guidelines/components/form.md +19 -0
- package/guidelines/components/navigation.md +16 -15
- package/guidelines/components/overlay.md +43 -4
- package/guidelines/components/stat.md +31 -0
- package/guidelines/components/time-picker.md +49 -0
- package/package.json +1 -1
|
@@ -178,11 +178,16 @@ var FieldMessage = (props) => {
|
|
|
178
178
|
FieldMessage.displayName = "FieldMessage";
|
|
179
179
|
var FieldMessage_default = FieldMessage;
|
|
180
180
|
var Field = (props) => {
|
|
181
|
-
const { validations, children } = props;
|
|
182
|
-
|
|
181
|
+
const { label, required = false, htmlFor, validations, children } = props;
|
|
182
|
+
const hasMessages = !!validations && validations.length > 0;
|
|
183
|
+
if (!label && !hasMessages) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children });
|
|
183
184
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "lib-xplat-field", children: [
|
|
185
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "lib-xplat-field-label", htmlFor, children: [
|
|
186
|
+
label,
|
|
187
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "required", "aria-hidden": "true", children: "*" })
|
|
188
|
+
] }),
|
|
184
189
|
children,
|
|
185
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FieldMessage, { validations })
|
|
190
|
+
hasMessages && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FieldMessage, { validations })
|
|
186
191
|
] });
|
|
187
192
|
};
|
|
188
193
|
Field.displayName = "Field";
|
|
@@ -281,8 +286,12 @@ var Input = import_react.default.forwardRef((props, ref) => {
|
|
|
281
286
|
suffix,
|
|
282
287
|
disabled,
|
|
283
288
|
validations,
|
|
289
|
+
label,
|
|
290
|
+
required,
|
|
284
291
|
...inputProps
|
|
285
292
|
} = props;
|
|
293
|
+
const autoId = import_react.default.useId();
|
|
294
|
+
const fieldId = inputProps.id ?? autoId;
|
|
286
295
|
const localValue = formatValue(type, value);
|
|
287
296
|
const handleChange = (e) => {
|
|
288
297
|
let val = e.target.value;
|
|
@@ -298,7 +307,7 @@ var Input = import_react.default.forwardRef((props, ref) => {
|
|
|
298
307
|
onChange(event);
|
|
299
308
|
}
|
|
300
309
|
};
|
|
301
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
|
|
310
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Field, { label, required, htmlFor: fieldId, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
|
|
302
311
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
303
312
|
"div",
|
|
304
313
|
{
|
|
@@ -309,6 +318,7 @@ var Input = import_react.default.forwardRef((props, ref) => {
|
|
|
309
318
|
{
|
|
310
319
|
...inputProps,
|
|
311
320
|
ref,
|
|
321
|
+
id: fieldId,
|
|
312
322
|
disabled,
|
|
313
323
|
type: type === "number" ? "text" : type,
|
|
314
324
|
value: localValue,
|
|
@@ -321,7 +331,7 @@ var Input = import_react.default.forwardRef((props, ref) => {
|
|
|
321
331
|
}
|
|
322
332
|
),
|
|
323
333
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(FieldMessage_default, { validations })
|
|
324
|
-
] });
|
|
334
|
+
] }) });
|
|
325
335
|
});
|
|
326
336
|
Input.displayName = "Input";
|
|
327
337
|
var Input_default = Input;
|
|
@@ -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);
|
|
@@ -4,9 +4,16 @@ import { V as Validation } from '../../validation-Dqo1zqhT.cjs';
|
|
|
4
4
|
|
|
5
5
|
type InputSize$1 = "sm" | "md" | "lg";
|
|
6
6
|
interface InputProps extends Omit<InputAttributes, "size"> {
|
|
7
|
+
/** 입력 종류. number 는 천 단위 구분, tel 은 하이픈을 자동으로 넣는다 */
|
|
7
8
|
type?: "text" | "number" | "email" | "password" | "tel";
|
|
9
|
+
/** 높이와 글자 크기 */
|
|
8
10
|
size?: InputSize$1;
|
|
9
11
|
validations?: Validation[];
|
|
12
|
+
/** 컨트롤 위에 붙는 라벨. 클릭하면 입력칸에 포커스가 간다 */
|
|
13
|
+
label?: React.ReactNode;
|
|
14
|
+
/** 라벨 뒤에 필수 표시(*)를 붙인다 */
|
|
15
|
+
required?: boolean;
|
|
16
|
+
/** 입력칸 오른쪽에 붙일 요소 (단위·아이콘 등) */
|
|
10
17
|
suffix?: React.ReactNode;
|
|
11
18
|
}
|
|
12
19
|
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -14,6 +21,7 @@ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttri
|
|
|
14
21
|
type InputSize = "sm" | "md" | "lg";
|
|
15
22
|
interface PasswordInputProps extends Omit<InputAttributes, "size"> {
|
|
16
23
|
validations?: Validation[];
|
|
24
|
+
/** 높이와 글자 크기 */
|
|
17
25
|
size?: InputSize;
|
|
18
26
|
reg?: RegExp;
|
|
19
27
|
}
|
|
@@ -4,9 +4,16 @@ import { V as Validation } from '../../validation-Dqo1zqhT.js';
|
|
|
4
4
|
|
|
5
5
|
type InputSize$1 = "sm" | "md" | "lg";
|
|
6
6
|
interface InputProps extends Omit<InputAttributes, "size"> {
|
|
7
|
+
/** 입력 종류. number 는 천 단위 구분, tel 은 하이픈을 자동으로 넣는다 */
|
|
7
8
|
type?: "text" | "number" | "email" | "password" | "tel";
|
|
9
|
+
/** 높이와 글자 크기 */
|
|
8
10
|
size?: InputSize$1;
|
|
9
11
|
validations?: Validation[];
|
|
12
|
+
/** 컨트롤 위에 붙는 라벨. 클릭하면 입력칸에 포커스가 간다 */
|
|
13
|
+
label?: React.ReactNode;
|
|
14
|
+
/** 라벨 뒤에 필수 표시(*)를 붙인다 */
|
|
15
|
+
required?: boolean;
|
|
16
|
+
/** 입력칸 오른쪽에 붙일 요소 (단위·아이콘 등) */
|
|
10
17
|
suffix?: React.ReactNode;
|
|
11
18
|
}
|
|
12
19
|
declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -14,6 +21,7 @@ declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttri
|
|
|
14
21
|
type InputSize = "sm" | "md" | "lg";
|
|
15
22
|
interface PasswordInputProps extends Omit<InputAttributes, "size"> {
|
|
16
23
|
validations?: Validation[];
|
|
24
|
+
/** 높이와 글자 크기 */
|
|
17
25
|
size?: InputSize;
|
|
18
26
|
reg?: RegExp;
|
|
19
27
|
}
|
|
@@ -141,11 +141,16 @@ var FieldMessage = (props) => {
|
|
|
141
141
|
FieldMessage.displayName = "FieldMessage";
|
|
142
142
|
var FieldMessage_default = FieldMessage;
|
|
143
143
|
var Field = (props) => {
|
|
144
|
-
const { validations, children } = props;
|
|
145
|
-
|
|
144
|
+
const { label, required = false, htmlFor, validations, children } = props;
|
|
145
|
+
const hasMessages = !!validations && validations.length > 0;
|
|
146
|
+
if (!label && !hasMessages) return /* @__PURE__ */ jsx4(Fragment, { children });
|
|
146
147
|
return /* @__PURE__ */ jsxs3("div", { className: "lib-xplat-field", children: [
|
|
148
|
+
label && /* @__PURE__ */ jsxs3("label", { className: "lib-xplat-field-label", htmlFor, children: [
|
|
149
|
+
label,
|
|
150
|
+
required && /* @__PURE__ */ jsx4("span", { className: "required", "aria-hidden": "true", children: "*" })
|
|
151
|
+
] }),
|
|
147
152
|
children,
|
|
148
|
-
/* @__PURE__ */ jsx4(FieldMessage, { validations })
|
|
153
|
+
hasMessages && /* @__PURE__ */ jsx4(FieldMessage, { validations })
|
|
149
154
|
] });
|
|
150
155
|
};
|
|
151
156
|
Field.displayName = "Field";
|
|
@@ -244,8 +249,12 @@ var Input = React.forwardRef((props, ref) => {
|
|
|
244
249
|
suffix,
|
|
245
250
|
disabled,
|
|
246
251
|
validations,
|
|
252
|
+
label,
|
|
253
|
+
required,
|
|
247
254
|
...inputProps
|
|
248
255
|
} = props;
|
|
256
|
+
const autoId = React.useId();
|
|
257
|
+
const fieldId = inputProps.id ?? autoId;
|
|
249
258
|
const localValue = formatValue(type, value);
|
|
250
259
|
const handleChange = (e) => {
|
|
251
260
|
let val = e.target.value;
|
|
@@ -261,7 +270,7 @@ var Input = React.forwardRef((props, ref) => {
|
|
|
261
270
|
onChange(event);
|
|
262
271
|
}
|
|
263
272
|
};
|
|
264
|
-
return /* @__PURE__ */ jsxs4("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
|
|
273
|
+
return /* @__PURE__ */ jsx5(Field, { label, required, htmlFor: fieldId, children: /* @__PURE__ */ jsxs4("div", { className: clsx_default("lib-xplat-input-wrap", className), children: [
|
|
265
274
|
/* @__PURE__ */ jsxs4(
|
|
266
275
|
"div",
|
|
267
276
|
{
|
|
@@ -272,6 +281,7 @@ var Input = React.forwardRef((props, ref) => {
|
|
|
272
281
|
{
|
|
273
282
|
...inputProps,
|
|
274
283
|
ref,
|
|
284
|
+
id: fieldId,
|
|
275
285
|
disabled,
|
|
276
286
|
type: type === "number" ? "text" : type,
|
|
277
287
|
value: localValue,
|
|
@@ -284,7 +294,7 @@ var Input = React.forwardRef((props, ref) => {
|
|
|
284
294
|
}
|
|
285
295
|
),
|
|
286
296
|
/* @__PURE__ */ jsx5(FieldMessage_default, { validations })
|
|
287
|
-
] });
|
|
297
|
+
] }) });
|
|
288
298
|
});
|
|
289
299
|
Input.displayName = "Input";
|
|
290
300
|
var Input_default = Input;
|
|
@@ -35,9 +35,84 @@ __export(Modal_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(Modal_exports);
|
|
36
36
|
|
|
37
37
|
// src/components/Modal/Modal.tsx
|
|
38
|
-
var
|
|
38
|
+
var import_react2 = __toESM(require("react"), 1);
|
|
39
39
|
var import_react_dom = require("react-dom");
|
|
40
40
|
|
|
41
|
+
// src/tokens/hooks/useOverlayKeyboard.ts
|
|
42
|
+
var import_react = __toESM(require("react"), 1);
|
|
43
|
+
var FOCUSABLE = [
|
|
44
|
+
"a[href]",
|
|
45
|
+
"button:not([disabled])",
|
|
46
|
+
"input:not([disabled]):not([type='hidden'])",
|
|
47
|
+
"select:not([disabled])",
|
|
48
|
+
"textarea:not([disabled])",
|
|
49
|
+
"[tabindex]:not([tabindex='-1'])"
|
|
50
|
+
].join(",");
|
|
51
|
+
var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
|
|
52
|
+
// 화면에 없는 것은 제외 (display:none 등)
|
|
53
|
+
(n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
|
|
54
|
+
);
|
|
55
|
+
var useEscapeKey = (enabled, onEscape) => {
|
|
56
|
+
import_react.default.useEffect(() => {
|
|
57
|
+
if (!enabled) return;
|
|
58
|
+
const onKey = (e) => {
|
|
59
|
+
if (e.key !== "Escape") return;
|
|
60
|
+
if (e.defaultPrevented) return;
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
onEscape();
|
|
63
|
+
};
|
|
64
|
+
document.addEventListener("keydown", onKey);
|
|
65
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
66
|
+
}, [enabled, onEscape]);
|
|
67
|
+
};
|
|
68
|
+
var useFocusTrap = (containerRef, enabled, options = {}) => {
|
|
69
|
+
const { trap = false, initialFocus } = options;
|
|
70
|
+
const restoreRef = import_react.default.useRef(null);
|
|
71
|
+
import_react.default.useEffect(() => {
|
|
72
|
+
if (!enabled) return;
|
|
73
|
+
restoreRef.current = document.activeElement;
|
|
74
|
+
const raf = requestAnimationFrame(() => {
|
|
75
|
+
const el = containerRef.current;
|
|
76
|
+
if (!el) return;
|
|
77
|
+
const target = initialFocus?.current ?? focusableIn(el)[0] ?? el;
|
|
78
|
+
if (!target.hasAttribute("tabindex") && !focusableIn(el).includes(target)) {
|
|
79
|
+
target.setAttribute("tabindex", "-1");
|
|
80
|
+
}
|
|
81
|
+
target.focus({ preventScroll: true });
|
|
82
|
+
});
|
|
83
|
+
return () => {
|
|
84
|
+
cancelAnimationFrame(raf);
|
|
85
|
+
const prev = restoreRef.current;
|
|
86
|
+
if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
|
|
87
|
+
};
|
|
88
|
+
}, [enabled, containerRef, initialFocus]);
|
|
89
|
+
import_react.default.useEffect(() => {
|
|
90
|
+
if (!enabled || !trap) return;
|
|
91
|
+
const onKey = (e) => {
|
|
92
|
+
if (e.key !== "Tab") return;
|
|
93
|
+
const el = containerRef.current;
|
|
94
|
+
if (!el) return;
|
|
95
|
+
const items = focusableIn(el);
|
|
96
|
+
if (items.length === 0) {
|
|
97
|
+
e.preventDefault();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const first = items[0];
|
|
101
|
+
const last = items[items.length - 1];
|
|
102
|
+
const active = document.activeElement;
|
|
103
|
+
if (e.shiftKey && (active === first || !el.contains(active))) {
|
|
104
|
+
e.preventDefault();
|
|
105
|
+
last.focus();
|
|
106
|
+
} else if (!e.shiftKey && (active === last || !el.contains(active))) {
|
|
107
|
+
e.preventDefault();
|
|
108
|
+
first.focus();
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
document.addEventListener("keydown", onKey);
|
|
112
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
113
|
+
}, [enabled, trap, containerRef]);
|
|
114
|
+
};
|
|
115
|
+
|
|
41
116
|
// ../../node_modules/clsx/dist/clsx.mjs
|
|
42
117
|
function r(e) {
|
|
43
118
|
var t, f, n = "";
|
|
@@ -59,10 +134,13 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
59
134
|
var ANIMATION_DURATION_MS = 200;
|
|
60
135
|
var Modal = (props) => {
|
|
61
136
|
const { isOpen, onClose, children } = props;
|
|
62
|
-
const [mounted, setMounted] =
|
|
63
|
-
const [visible, setVisible] =
|
|
64
|
-
const [settled, setSettled] =
|
|
65
|
-
|
|
137
|
+
const [mounted, setMounted] = import_react2.default.useState(false);
|
|
138
|
+
const [visible, setVisible] = import_react2.default.useState(false);
|
|
139
|
+
const [settled, setSettled] = import_react2.default.useState(false);
|
|
140
|
+
const boxRef = import_react2.default.useRef(null);
|
|
141
|
+
useEscapeKey(isOpen, onClose);
|
|
142
|
+
useFocusTrap(boxRef, isOpen && mounted, { trap: true });
|
|
143
|
+
import_react2.default.useEffect(() => {
|
|
66
144
|
if (isOpen) {
|
|
67
145
|
setMounted(true);
|
|
68
146
|
const show = setTimeout(() => setVisible(true), 1);
|
|
@@ -89,6 +167,7 @@ var Modal = (props) => {
|
|
|
89
167
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
90
168
|
"div",
|
|
91
169
|
{
|
|
170
|
+
ref: boxRef,
|
|
92
171
|
className: clsx_default("lib-xplat-modal", "modal-box", stateClass, settled && "settled"),
|
|
93
172
|
role: "dialog",
|
|
94
173
|
"aria-modal": "true",
|
|
@@ -1,7 +1,82 @@
|
|
|
1
1
|
// src/components/Modal/Modal.tsx
|
|
2
|
-
import
|
|
2
|
+
import React2 from "react";
|
|
3
3
|
import { createPortal } from "react-dom";
|
|
4
4
|
|
|
5
|
+
// src/tokens/hooks/useOverlayKeyboard.ts
|
|
6
|
+
import React from "react";
|
|
7
|
+
var FOCUSABLE = [
|
|
8
|
+
"a[href]",
|
|
9
|
+
"button:not([disabled])",
|
|
10
|
+
"input:not([disabled]):not([type='hidden'])",
|
|
11
|
+
"select:not([disabled])",
|
|
12
|
+
"textarea:not([disabled])",
|
|
13
|
+
"[tabindex]:not([tabindex='-1'])"
|
|
14
|
+
].join(",");
|
|
15
|
+
var focusableIn = (el) => Array.from(el.querySelectorAll(FOCUSABLE)).filter(
|
|
16
|
+
// 화면에 없는 것은 제외 (display:none 등)
|
|
17
|
+
(n) => n.offsetWidth > 0 || n.offsetHeight > 0 || n === document.activeElement
|
|
18
|
+
);
|
|
19
|
+
var useEscapeKey = (enabled, onEscape) => {
|
|
20
|
+
React.useEffect(() => {
|
|
21
|
+
if (!enabled) return;
|
|
22
|
+
const onKey = (e) => {
|
|
23
|
+
if (e.key !== "Escape") return;
|
|
24
|
+
if (e.defaultPrevented) return;
|
|
25
|
+
e.preventDefault();
|
|
26
|
+
onEscape();
|
|
27
|
+
};
|
|
28
|
+
document.addEventListener("keydown", onKey);
|
|
29
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
30
|
+
}, [enabled, onEscape]);
|
|
31
|
+
};
|
|
32
|
+
var useFocusTrap = (containerRef, enabled, options = {}) => {
|
|
33
|
+
const { trap = false, initialFocus } = options;
|
|
34
|
+
const restoreRef = React.useRef(null);
|
|
35
|
+
React.useEffect(() => {
|
|
36
|
+
if (!enabled) return;
|
|
37
|
+
restoreRef.current = document.activeElement;
|
|
38
|
+
const raf = requestAnimationFrame(() => {
|
|
39
|
+
const el = containerRef.current;
|
|
40
|
+
if (!el) return;
|
|
41
|
+
const target = initialFocus?.current ?? focusableIn(el)[0] ?? el;
|
|
42
|
+
if (!target.hasAttribute("tabindex") && !focusableIn(el).includes(target)) {
|
|
43
|
+
target.setAttribute("tabindex", "-1");
|
|
44
|
+
}
|
|
45
|
+
target.focus({ preventScroll: true });
|
|
46
|
+
});
|
|
47
|
+
return () => {
|
|
48
|
+
cancelAnimationFrame(raf);
|
|
49
|
+
const prev = restoreRef.current;
|
|
50
|
+
if (prev && document.contains(prev)) prev.focus({ preventScroll: true });
|
|
51
|
+
};
|
|
52
|
+
}, [enabled, containerRef, initialFocus]);
|
|
53
|
+
React.useEffect(() => {
|
|
54
|
+
if (!enabled || !trap) return;
|
|
55
|
+
const onKey = (e) => {
|
|
56
|
+
if (e.key !== "Tab") return;
|
|
57
|
+
const el = containerRef.current;
|
|
58
|
+
if (!el) return;
|
|
59
|
+
const items = focusableIn(el);
|
|
60
|
+
if (items.length === 0) {
|
|
61
|
+
e.preventDefault();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const first = items[0];
|
|
65
|
+
const last = items[items.length - 1];
|
|
66
|
+
const active = document.activeElement;
|
|
67
|
+
if (e.shiftKey && (active === first || !el.contains(active))) {
|
|
68
|
+
e.preventDefault();
|
|
69
|
+
last.focus();
|
|
70
|
+
} else if (!e.shiftKey && (active === last || !el.contains(active))) {
|
|
71
|
+
e.preventDefault();
|
|
72
|
+
first.focus();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
document.addEventListener("keydown", onKey);
|
|
76
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
77
|
+
}, [enabled, trap, containerRef]);
|
|
78
|
+
};
|
|
79
|
+
|
|
5
80
|
// ../../node_modules/clsx/dist/clsx.mjs
|
|
6
81
|
function r(e) {
|
|
7
82
|
var t, f, n = "";
|
|
@@ -23,10 +98,13 @@ import { jsx } from "react/jsx-runtime";
|
|
|
23
98
|
var ANIMATION_DURATION_MS = 200;
|
|
24
99
|
var Modal = (props) => {
|
|
25
100
|
const { isOpen, onClose, children } = props;
|
|
26
|
-
const [mounted, setMounted] =
|
|
27
|
-
const [visible, setVisible] =
|
|
28
|
-
const [settled, setSettled] =
|
|
29
|
-
|
|
101
|
+
const [mounted, setMounted] = React2.useState(false);
|
|
102
|
+
const [visible, setVisible] = React2.useState(false);
|
|
103
|
+
const [settled, setSettled] = React2.useState(false);
|
|
104
|
+
const boxRef = React2.useRef(null);
|
|
105
|
+
useEscapeKey(isOpen, onClose);
|
|
106
|
+
useFocusTrap(boxRef, isOpen && mounted, { trap: true });
|
|
107
|
+
React2.useEffect(() => {
|
|
30
108
|
if (isOpen) {
|
|
31
109
|
setMounted(true);
|
|
32
110
|
const show = setTimeout(() => setVisible(true), 1);
|
|
@@ -53,6 +131,7 @@ var Modal = (props) => {
|
|
|
53
131
|
children: /* @__PURE__ */ jsx(
|
|
54
132
|
"div",
|
|
55
133
|
{
|
|
134
|
+
ref: boxRef,
|
|
56
135
|
className: clsx_default("lib-xplat-modal", "modal-box", stateClass, settled && "settled"),
|
|
57
136
|
role: "dialog",
|
|
58
137
|
"aria-modal": "true",
|
|
@@ -25,6 +25,9 @@ __export(NotificationBadge_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(NotificationBadge_exports);
|
|
27
27
|
|
|
28
|
+
// src/tokens/interface/status.ts
|
|
29
|
+
var normalizeStatus = (value) => value === "brand" ? "primary" : value;
|
|
30
|
+
|
|
28
31
|
// ../../node_modules/clsx/dist/clsx.mjs
|
|
29
32
|
function r(e) {
|
|
30
33
|
var t, f, n = "";
|
|
@@ -52,11 +55,12 @@ var NotificationBadge = (props) => {
|
|
|
52
55
|
dot = false,
|
|
53
56
|
size = "md"
|
|
54
57
|
} = props;
|
|
58
|
+
const statusType = normalizeStatus(type);
|
|
55
59
|
const showBadge = dot || count !== void 0 && count > 0;
|
|
56
60
|
const displayCount = count !== void 0 && count > maxCount ? `${maxCount}+` : count;
|
|
57
61
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: clsx_default("lib-xplat-notification-badge", size), children: [
|
|
58
62
|
children,
|
|
59
|
-
showBadge && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: clsx_default("badge-indicator",
|
|
63
|
+
showBadge && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: clsx_default("badge-indicator", statusType, { dot }), children: !dot && displayCount })
|
|
60
64
|
] });
|
|
61
65
|
};
|
|
62
66
|
NotificationBadge.displayName = "NotificationBadge";
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
.lib-xplat-notification-badge .badge-indicator.info {
|
|
71
71
|
background-color: var(--semantic-surface-info-default);
|
|
72
72
|
}
|
|
73
|
+
.lib-xplat-notification-badge .badge-indicator.primary,
|
|
73
74
|
.lib-xplat-notification-badge .badge-indicator.brand {
|
|
74
75
|
background-color: var(--semantic-surface-brand-default);
|
|
75
76
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { L as LegacyStatusType } from '../../status-njWqQWFV.cjs';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
/** NotificationBadge 의 상태 색 */
|
|
6
|
+
type NotificationBadgeType = "primary" | "success" | "error" | "warning" | "info";
|
|
7
|
+
/** 입력으로는 예전 이름 `brand` 도 받는다 (= `primary`) */
|
|
8
|
+
type NotificationBadgeTypeInput = NotificationBadgeType | LegacyStatusType;
|
|
5
9
|
type NotificationBadgeSize = "sm" | "md" | "lg";
|
|
6
10
|
/**
|
|
7
11
|
* 알림 뱃지 — 다른 요소의 **우상단 모서리에 얹히는** 작은 원.
|
|
@@ -33,7 +37,7 @@ interface NotificationBadgeProps {
|
|
|
33
37
|
/** 개수 대신 점만 표시한다. `count` 없이 "새 항목 있음" 만 알릴 때 쓴다 */
|
|
34
38
|
dot?: boolean;
|
|
35
39
|
/** 뱃지 색. 뱃지가 렌더될 때만 의미가 있다 */
|
|
36
|
-
type?:
|
|
40
|
+
type?: NotificationBadgeTypeInput;
|
|
37
41
|
/** `count` 가 이 값을 넘으면 `99+` 처럼 표시한다 */
|
|
38
42
|
maxCount?: number;
|
|
39
43
|
/** 뱃지 크기. 대상의 크기가 아니다 */
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import React from 'react';
|
|
3
|
+
import { L as LegacyStatusType } from '../../status-njWqQWFV.js';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
/** NotificationBadge 의 상태 색 */
|
|
6
|
+
type NotificationBadgeType = "primary" | "success" | "error" | "warning" | "info";
|
|
7
|
+
/** 입력으로는 예전 이름 `brand` 도 받는다 (= `primary`) */
|
|
8
|
+
type NotificationBadgeTypeInput = NotificationBadgeType | LegacyStatusType;
|
|
5
9
|
type NotificationBadgeSize = "sm" | "md" | "lg";
|
|
6
10
|
/**
|
|
7
11
|
* 알림 뱃지 — 다른 요소의 **우상단 모서리에 얹히는** 작은 원.
|
|
@@ -33,7 +37,7 @@ interface NotificationBadgeProps {
|
|
|
33
37
|
/** 개수 대신 점만 표시한다. `count` 없이 "새 항목 있음" 만 알릴 때 쓴다 */
|
|
34
38
|
dot?: boolean;
|
|
35
39
|
/** 뱃지 색. 뱃지가 렌더될 때만 의미가 있다 */
|
|
36
|
-
type?:
|
|
40
|
+
type?: NotificationBadgeTypeInput;
|
|
37
41
|
/** `count` 가 이 값을 넘으면 `99+` 처럼 표시한다 */
|
|
38
42
|
maxCount?: number;
|
|
39
43
|
/** 뱃지 크기. 대상의 크기가 아니다 */
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/tokens/interface/status.ts
|
|
2
|
+
var normalizeStatus = (value) => value === "brand" ? "primary" : value;
|
|
3
|
+
|
|
1
4
|
// ../../node_modules/clsx/dist/clsx.mjs
|
|
2
5
|
function r(e) {
|
|
3
6
|
var t, f, n = "";
|
|
@@ -25,11 +28,12 @@ var NotificationBadge = (props) => {
|
|
|
25
28
|
dot = false,
|
|
26
29
|
size = "md"
|
|
27
30
|
} = props;
|
|
31
|
+
const statusType = normalizeStatus(type);
|
|
28
32
|
const showBadge = dot || count !== void 0 && count > 0;
|
|
29
33
|
const displayCount = count !== void 0 && count > maxCount ? `${maxCount}+` : count;
|
|
30
34
|
return /* @__PURE__ */ jsxs("div", { className: clsx_default("lib-xplat-notification-badge", size), children: [
|
|
31
35
|
children,
|
|
32
|
-
showBadge && /* @__PURE__ */ jsx("span", { className: clsx_default("badge-indicator",
|
|
36
|
+
showBadge && /* @__PURE__ */ jsx("span", { className: clsx_default("badge-indicator", statusType, { dot }), children: !dot && displayCount })
|
|
33
37
|
] });
|
|
34
38
|
};
|
|
35
39
|
NotificationBadge.displayName = "NotificationBadge";
|
|
@@ -24,6 +24,9 @@ __export(Pagination_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(Pagination_exports);
|
|
26
26
|
|
|
27
|
+
// src/tokens/interface/status.ts
|
|
28
|
+
var normalizeStatus = (value) => value === "brand" ? "primary" : value;
|
|
29
|
+
|
|
27
30
|
// src/tokens/svg/action/CopyIcon.tsx
|
|
28
31
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
29
32
|
|
|
@@ -981,8 +984,9 @@ var Pagination = (props) => {
|
|
|
981
984
|
siblingCount = 1,
|
|
982
985
|
onChange,
|
|
983
986
|
size = "md",
|
|
984
|
-
type = "
|
|
987
|
+
type = "primary"
|
|
985
988
|
} = props;
|
|
989
|
+
const statusType = normalizeStatus(type);
|
|
986
990
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
987
991
|
const pages = getPageRange(current, totalPages, siblingCount);
|
|
988
992
|
const handleClick = (page) => {
|
|
@@ -990,7 +994,7 @@ var Pagination = (props) => {
|
|
|
990
994
|
onChange?.(page);
|
|
991
995
|
}
|
|
992
996
|
};
|
|
993
|
-
return /* @__PURE__ */ (0, import_jsx_runtime295.jsxs)("nav", { className: clsx_default("lib-xplat-pagination", size,
|
|
997
|
+
return /* @__PURE__ */ (0, import_jsx_runtime295.jsxs)("nav", { className: clsx_default("lib-xplat-pagination", size, statusType), "aria-label": "\uD398\uC774\uC9C0 \uB124\uBE44\uAC8C\uC774\uC158", children: [
|
|
994
998
|
/* @__PURE__ */ (0, import_jsx_runtime295.jsx)(
|
|
995
999
|
"button",
|
|
996
1000
|
{
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
.lib-xplat-pagination .page-btn svg {
|
|
94
94
|
font-size: var(--semantic-typo-label-2-m-size);
|
|
95
95
|
}
|
|
96
|
+
.lib-xplat-pagination.primary .page-btn.active,
|
|
96
97
|
.lib-xplat-pagination.brand .page-btn.active {
|
|
97
98
|
background-color: var(--semantic-surface-brand-default);
|
|
98
99
|
}
|
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { L as LegacyStatusType } from '../../status-njWqQWFV.cjs';
|
|
2
3
|
|
|
3
4
|
type PaginationSize = "sm" | "md" | "lg";
|
|
4
|
-
|
|
5
|
+
/** Pagination 의 상태 색 */
|
|
6
|
+
type PaginationType = "primary" | "success" | "error" | "warning" | "info";
|
|
7
|
+
/** 입력으로는 예전 이름 `brand` 도 받는다 (= `primary`) */
|
|
8
|
+
type PaginationTypeInput = PaginationType | LegacyStatusType;
|
|
5
9
|
interface PaginationProps {
|
|
10
|
+
/** 현재 페이지 (1부터 시작) */
|
|
6
11
|
current: number;
|
|
12
|
+
/** **전체 아이템 수**. 페이지 수가 아니다 */
|
|
7
13
|
total: number;
|
|
14
|
+
/** 한 페이지에 담기는 아이템 수. total 과 함께 페이지 수를 계산한다 */
|
|
8
15
|
pageSize?: number;
|
|
16
|
+
/** 현재 페이지 좌우로 보여줄 번호 개수 */
|
|
9
17
|
siblingCount?: number;
|
|
18
|
+
/** 페이지를 누르면 새 페이지 번호를 준다 */
|
|
10
19
|
onChange?: (page: number) => void;
|
|
20
|
+
/** 버튼 크기 */
|
|
11
21
|
size?: PaginationSize;
|
|
12
|
-
|
|
22
|
+
/** 활성 페이지 색 */
|
|
23
|
+
type?: PaginationTypeInput;
|
|
13
24
|
}
|
|
14
25
|
declare const Pagination: {
|
|
15
26
|
(props: PaginationProps): react_jsx_runtime.JSX.Element;
|
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { L as LegacyStatusType } from '../../status-njWqQWFV.js';
|
|
2
3
|
|
|
3
4
|
type PaginationSize = "sm" | "md" | "lg";
|
|
4
|
-
|
|
5
|
+
/** Pagination 의 상태 색 */
|
|
6
|
+
type PaginationType = "primary" | "success" | "error" | "warning" | "info";
|
|
7
|
+
/** 입력으로는 예전 이름 `brand` 도 받는다 (= `primary`) */
|
|
8
|
+
type PaginationTypeInput = PaginationType | LegacyStatusType;
|
|
5
9
|
interface PaginationProps {
|
|
10
|
+
/** 현재 페이지 (1부터 시작) */
|
|
6
11
|
current: number;
|
|
12
|
+
/** **전체 아이템 수**. 페이지 수가 아니다 */
|
|
7
13
|
total: number;
|
|
14
|
+
/** 한 페이지에 담기는 아이템 수. total 과 함께 페이지 수를 계산한다 */
|
|
8
15
|
pageSize?: number;
|
|
16
|
+
/** 현재 페이지 좌우로 보여줄 번호 개수 */
|
|
9
17
|
siblingCount?: number;
|
|
18
|
+
/** 페이지를 누르면 새 페이지 번호를 준다 */
|
|
10
19
|
onChange?: (page: number) => void;
|
|
20
|
+
/** 버튼 크기 */
|
|
11
21
|
size?: PaginationSize;
|
|
12
|
-
|
|
22
|
+
/** 활성 페이지 색 */
|
|
23
|
+
type?: PaginationTypeInput;
|
|
13
24
|
}
|
|
14
25
|
declare const Pagination: {
|
|
15
26
|
(props: PaginationProps): react_jsx_runtime.JSX.Element;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/tokens/interface/status.ts
|
|
2
|
+
var normalizeStatus = (value) => value === "brand" ? "primary" : value;
|
|
3
|
+
|
|
1
4
|
// src/tokens/svg/action/CopyIcon.tsx
|
|
2
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
6
|
|
|
@@ -955,8 +958,9 @@ var Pagination = (props) => {
|
|
|
955
958
|
siblingCount = 1,
|
|
956
959
|
onChange,
|
|
957
960
|
size = "md",
|
|
958
|
-
type = "
|
|
961
|
+
type = "primary"
|
|
959
962
|
} = props;
|
|
963
|
+
const statusType = normalizeStatus(type);
|
|
960
964
|
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
961
965
|
const pages = getPageRange(current, totalPages, siblingCount);
|
|
962
966
|
const handleClick = (page) => {
|
|
@@ -964,7 +968,7 @@ var Pagination = (props) => {
|
|
|
964
968
|
onChange?.(page);
|
|
965
969
|
}
|
|
966
970
|
};
|
|
967
|
-
return /* @__PURE__ */ jsxs189("nav", { className: clsx_default("lib-xplat-pagination", size,
|
|
971
|
+
return /* @__PURE__ */ jsxs189("nav", { className: clsx_default("lib-xplat-pagination", size, statusType), "aria-label": "\uD398\uC774\uC9C0 \uB124\uBE44\uAC8C\uC774\uC158", children: [
|
|
968
972
|
/* @__PURE__ */ jsx295(
|
|
969
973
|
"button",
|
|
970
974
|
{
|