@pylerai/design-system 1.2.3 → 2.0.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/README.md +169 -316
- package/dist/components/ui/badge.d.ts +2 -1
- package/dist/components/ui/badge.js +49 -0
- package/dist/components/ui/body.js +52 -0
- package/dist/components/ui/button.d.ts +2 -1
- package/dist/components/ui/button.js +172 -0
- package/dist/components/ui/calendar.js +275 -0
- package/dist/components/ui/checkbox.d.ts +7 -0
- package/dist/components/ui/checkbox.js +45 -0
- package/dist/components/ui/chip.d.ts +4 -3
- package/dist/components/ui/chip.js +66 -0
- package/dist/components/ui/dropdown.d.ts +8 -2
- package/dist/components/ui/dropdown.js +256 -0
- package/dist/components/ui/headline.js +50 -0
- package/dist/components/ui/input.d.ts +3 -2
- package/dist/components/ui/input.js +129 -0
- package/dist/components/ui/label.js +43 -0
- package/dist/components/ui/loading-bar.d.ts +2 -1
- package/dist/components/ui/loading-bar.js +64 -0
- package/dist/components/ui/modal.d.ts +3 -2
- package/dist/components/ui/modal.js +170 -0
- package/dist/components/ui/pagination.d.ts +2 -0
- package/dist/components/ui/pagination.js +106 -0
- package/dist/components/ui/radio.d.ts +7 -0
- package/dist/components/ui/radio.js +42 -0
- package/dist/components/ui/search-field.d.ts +3 -2
- package/dist/components/ui/search-field.js +98 -0
- package/dist/components/ui/table.js +206 -0
- package/dist/components/ui/tabs.js +149 -0
- package/dist/components/ui/tag.d.ts +2 -1
- package/dist/components/ui/tag.js +31 -0
- package/dist/components/ui/tips.d.ts +2 -1
- package/dist/components/ui/tips.js +25 -0
- package/dist/components/ui/toast.js +70 -0
- package/dist/components/ui/toggle.d.ts +1 -2
- package/dist/components/ui/toggle.js +41 -0
- package/dist/components/ui/use-modal.js +94 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +75 -5769
- package/dist/lib/icons.js +225 -0
- package/dist/lib/size.d.ts +8 -0
- package/dist/lib/use-dialog-a11y.d.ts +2 -0
- package/dist/lib/use-dialog-a11y.js +50 -0
- package/dist/lib/utils.js +16 -0
- package/dist/style.css +1 -1
- package/dist/tokens/pyler-light.js +134 -0
- package/dist/tokens/typography.js +84 -0
- package/package.json +14 -1
- package/pyler-tailwind-colors.cjs +4 -0
- package/dist/index.css.d.ts +0 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as e, jsxs as a } from "react/jsx-runtime";
|
|
3
|
+
import { XIcon as z } from "../../lib/icons.js";
|
|
4
|
+
import { useDialogA11y as p } from "../../lib/use-dialog-a11y.js";
|
|
5
|
+
import { cn as g } from "../../lib/utils.js";
|
|
6
|
+
import * as b from "react";
|
|
7
|
+
import { createPortal as v } from "react-dom";
|
|
8
|
+
import { Button as h } from "./button.js";
|
|
9
|
+
function y({ onClick: l }) {
|
|
10
|
+
return /* @__PURE__ */ e(
|
|
11
|
+
"button",
|
|
12
|
+
{
|
|
13
|
+
type: "button",
|
|
14
|
+
onClick: l,
|
|
15
|
+
"aria-label": "닫기",
|
|
16
|
+
className: "inline-flex items-center justify-center size-5 shrink-0 text-ds-text-normal hover:text-ds-text-strong transition-colors focus-visible:outline-none",
|
|
17
|
+
children: /* @__PURE__ */ e(z, { className: "size-5" })
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
function w({ children: l }) {
|
|
22
|
+
return /* @__PURE__ */ a("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-5", children: [
|
|
23
|
+
/* @__PURE__ */ e("div", { className: "absolute inset-0 bg-ds-dim-default" }),
|
|
24
|
+
/* @__PURE__ */ e("div", { className: "relative z-10 flex items-center justify-center w-full h-full", children: l })
|
|
25
|
+
] });
|
|
26
|
+
}
|
|
27
|
+
const N = "bg-ds-background-default border border-ds-line-normal rounded-ds-lg p-5 flex flex-col gap-6 shadow-ds-modal focus:outline-none", k = "flex-1 min-w-0 text-body-2-sb text-ds-text-strong";
|
|
28
|
+
function S({
|
|
29
|
+
open: l,
|
|
30
|
+
title: f,
|
|
31
|
+
description: i,
|
|
32
|
+
confirmLabel: o = "확인",
|
|
33
|
+
onConfirm: c,
|
|
34
|
+
onClose: s,
|
|
35
|
+
className: d
|
|
36
|
+
}) {
|
|
37
|
+
const t = b.useId(), n = p(l, s);
|
|
38
|
+
if (!l) return null;
|
|
39
|
+
const r = () => {
|
|
40
|
+
c == null || c(), s();
|
|
41
|
+
};
|
|
42
|
+
return v(
|
|
43
|
+
/* @__PURE__ */ e(w, { children: /* @__PURE__ */ a(
|
|
44
|
+
"div",
|
|
45
|
+
{
|
|
46
|
+
ref: n,
|
|
47
|
+
role: "dialog",
|
|
48
|
+
"aria-modal": "true",
|
|
49
|
+
"aria-labelledby": `${t}-title`,
|
|
50
|
+
"aria-describedby": i ? `${t}-description` : void 0,
|
|
51
|
+
tabIndex: -1,
|
|
52
|
+
className: g(N, "w-[360px]", d),
|
|
53
|
+
children: [
|
|
54
|
+
/* @__PURE__ */ a("div", { className: "flex items-start justify-between w-full gap-2", children: [
|
|
55
|
+
/* @__PURE__ */ e("p", { id: `${t}-title`, className: k, children: f }),
|
|
56
|
+
/* @__PURE__ */ e(y, { onClick: s })
|
|
57
|
+
] }),
|
|
58
|
+
i && /* @__PURE__ */ e("p", { id: `${t}-description`, className: "text-body-3-r text-ds-text-strong w-full", children: i }),
|
|
59
|
+
o && /* @__PURE__ */ e("div", { className: "flex items-center justify-end w-full", children: /* @__PURE__ */ e(h, { variant: "filled", color: "blue", size: "lg", onClick: r, children: o }) })
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
) }),
|
|
63
|
+
document.body
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
function X({
|
|
67
|
+
open: l,
|
|
68
|
+
title: f,
|
|
69
|
+
description: i,
|
|
70
|
+
cancelLabel: o = "닫기",
|
|
71
|
+
confirmLabel: c = "확인",
|
|
72
|
+
onCancel: s,
|
|
73
|
+
onConfirm: d,
|
|
74
|
+
onClose: t,
|
|
75
|
+
className: n
|
|
76
|
+
}) {
|
|
77
|
+
const r = b.useId(), m = b.useCallback(() => {
|
|
78
|
+
s == null || s(), t();
|
|
79
|
+
}, [s, t]), u = p(l, m);
|
|
80
|
+
if (!l) return null;
|
|
81
|
+
const x = () => {
|
|
82
|
+
d == null || d(), t();
|
|
83
|
+
};
|
|
84
|
+
return v(
|
|
85
|
+
/* @__PURE__ */ e(w, { children: /* @__PURE__ */ a(
|
|
86
|
+
"div",
|
|
87
|
+
{
|
|
88
|
+
ref: u,
|
|
89
|
+
role: "dialog",
|
|
90
|
+
"aria-modal": "true",
|
|
91
|
+
"aria-labelledby": `${r}-title`,
|
|
92
|
+
"aria-describedby": i ? `${r}-description` : void 0,
|
|
93
|
+
tabIndex: -1,
|
|
94
|
+
className: g(N, "w-[360px]", n),
|
|
95
|
+
children: [
|
|
96
|
+
/* @__PURE__ */ a("div", { className: "flex items-center justify-between w-full gap-2", children: [
|
|
97
|
+
/* @__PURE__ */ e("p", { id: `${r}-title`, className: k, children: f }),
|
|
98
|
+
/* @__PURE__ */ e(y, { onClick: m })
|
|
99
|
+
] }),
|
|
100
|
+
i && /* @__PURE__ */ e("p", { id: `${r}-description`, className: "text-body-3-r text-ds-text-strong w-full", children: i }),
|
|
101
|
+
/* @__PURE__ */ a("div", { className: "flex items-center justify-end gap-2 w-full", children: [
|
|
102
|
+
/* @__PURE__ */ e(h, { variant: "outlined", color: "blue", size: "lg", onClick: m, children: o }),
|
|
103
|
+
/* @__PURE__ */ e(h, { variant: "filled", color: "blue", size: "lg", onClick: x, children: c })
|
|
104
|
+
] })
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
) }),
|
|
108
|
+
document.body
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
const I = {
|
|
112
|
+
lg: "w-[1000px] h-[437px]",
|
|
113
|
+
md: "w-[800px] h-[437px]",
|
|
114
|
+
sm: "w-[360px] h-[370px]"
|
|
115
|
+
};
|
|
116
|
+
function q({
|
|
117
|
+
open: l,
|
|
118
|
+
title: f,
|
|
119
|
+
description: i,
|
|
120
|
+
size: o = "sm",
|
|
121
|
+
cancelLabel: c = "닫기",
|
|
122
|
+
confirmLabel: s = "확인",
|
|
123
|
+
onCancel: d,
|
|
124
|
+
onConfirm: t,
|
|
125
|
+
onClose: n,
|
|
126
|
+
children: r,
|
|
127
|
+
className: m
|
|
128
|
+
}) {
|
|
129
|
+
const u = b.useId(), x = b.useCallback(() => {
|
|
130
|
+
d == null || d(), n();
|
|
131
|
+
}, [d, n]), $ = p(l, x);
|
|
132
|
+
if (!l) return null;
|
|
133
|
+
const j = () => {
|
|
134
|
+
t == null || t(), n();
|
|
135
|
+
};
|
|
136
|
+
return v(
|
|
137
|
+
/* @__PURE__ */ e(w, { children: /* @__PURE__ */ a(
|
|
138
|
+
"div",
|
|
139
|
+
{
|
|
140
|
+
ref: $,
|
|
141
|
+
role: "dialog",
|
|
142
|
+
"aria-modal": "true",
|
|
143
|
+
"aria-labelledby": `${u}-title`,
|
|
144
|
+
"aria-describedby": i ? `${u}-description` : void 0,
|
|
145
|
+
tabIndex: -1,
|
|
146
|
+
className: g(N, I[o], m),
|
|
147
|
+
children: [
|
|
148
|
+
/* @__PURE__ */ a("div", { className: "flex flex-col gap-3 w-full shrink-0", children: [
|
|
149
|
+
/* @__PURE__ */ a("div", { className: "flex items-center justify-between w-full gap-2", children: [
|
|
150
|
+
/* @__PURE__ */ e("p", { id: `${u}-title`, className: k, children: f }),
|
|
151
|
+
/* @__PURE__ */ e(y, { onClick: x })
|
|
152
|
+
] }),
|
|
153
|
+
i && /* @__PURE__ */ e("p", { id: `${u}-description`, className: "text-body-3-r text-ds-text-strong w-full", children: i })
|
|
154
|
+
] }),
|
|
155
|
+
/* @__PURE__ */ e("div", { className: "flex-1 min-h-0 bg-ds-surface-normal rounded-ds-md w-full overflow-y-auto", children: r }),
|
|
156
|
+
/* @__PURE__ */ a("div", { className: "flex items-center justify-end gap-2 w-full shrink-0", children: [
|
|
157
|
+
/* @__PURE__ */ e(h, { variant: "outlined", color: "blue", size: "lg", onClick: x, children: c }),
|
|
158
|
+
/* @__PURE__ */ e(h, { variant: "filled", color: "blue", size: "lg", onClick: j, children: s })
|
|
159
|
+
] })
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
) }),
|
|
163
|
+
document.body
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
export {
|
|
167
|
+
X as ActionModal,
|
|
168
|
+
q as ContentModal,
|
|
169
|
+
S as InformationModal
|
|
170
|
+
};
|
|
@@ -10,6 +10,8 @@ export interface PaginationProps {
|
|
|
10
10
|
showTopButton?: boolean;
|
|
11
11
|
/** TOP 버튼 클릭 핸들러 */
|
|
12
12
|
onTopClick?: () => void;
|
|
13
|
+
/** 테두리 표시 여부. 기본값: true */
|
|
14
|
+
bordered?: boolean;
|
|
13
15
|
className?: string;
|
|
14
16
|
}
|
|
15
17
|
declare const Pagination: React.ForwardRefExoticComponent<PaginationProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as b, jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import { DoubleArrowLeftIcon as v, ArrowLeftIcon as N, ArrowRightIcon as p, DoubleArrowRightIcon as w } from "../../lib/icons.js";
|
|
4
|
+
import { cn as c } from "../../lib/utils.js";
|
|
5
|
+
import * as j from "react";
|
|
6
|
+
const A = j.forwardRef(
|
|
7
|
+
({
|
|
8
|
+
page: e,
|
|
9
|
+
totalPages: a,
|
|
10
|
+
onPageChange: r,
|
|
11
|
+
showTopButton: u = !1,
|
|
12
|
+
onTopClick: m,
|
|
13
|
+
bordered: f = !0,
|
|
14
|
+
className: x
|
|
15
|
+
}, h) => {
|
|
16
|
+
const o = e <= 1, i = e >= a, d = Math.floor((e - 1) / 5) * 5 + 1, y = Array.from(
|
|
17
|
+
{ length: Math.min(5, a - d + 1) },
|
|
18
|
+
(n, k) => d + k
|
|
19
|
+
), s = "inline-flex items-center justify-center text-ds-text-normal transition-colors focus-visible:outline-none", l = "inline-flex items-center justify-center text-ds-text-disabled cursor-not-allowed";
|
|
20
|
+
return /* @__PURE__ */ b("div", { ref: h, className: c("flex items-center gap-3", x), children: [
|
|
21
|
+
/* @__PURE__ */ t(
|
|
22
|
+
"div",
|
|
23
|
+
{
|
|
24
|
+
className: c(
|
|
25
|
+
"flex h-9 items-center overflow-hidden px-4 rounded-lg bg-ds-background-default",
|
|
26
|
+
f && "border border-ds-line-normal"
|
|
27
|
+
),
|
|
28
|
+
children: /* @__PURE__ */ b("div", { className: "flex items-center gap-2", children: [
|
|
29
|
+
/* @__PURE__ */ t(
|
|
30
|
+
"button",
|
|
31
|
+
{
|
|
32
|
+
type: "button",
|
|
33
|
+
"aria-label": "첫 페이지",
|
|
34
|
+
disabled: o,
|
|
35
|
+
onClick: () => !o && r(1),
|
|
36
|
+
className: o ? l : s,
|
|
37
|
+
children: /* @__PURE__ */ t(v, {})
|
|
38
|
+
}
|
|
39
|
+
),
|
|
40
|
+
/* @__PURE__ */ t(
|
|
41
|
+
"button",
|
|
42
|
+
{
|
|
43
|
+
type: "button",
|
|
44
|
+
"aria-label": "이전 페이지",
|
|
45
|
+
disabled: o,
|
|
46
|
+
onClick: () => !o && r(e - 1),
|
|
47
|
+
className: o ? l : s,
|
|
48
|
+
children: /* @__PURE__ */ t(N, {})
|
|
49
|
+
}
|
|
50
|
+
),
|
|
51
|
+
y.map((n) => /* @__PURE__ */ t(
|
|
52
|
+
"button",
|
|
53
|
+
{
|
|
54
|
+
type: "button",
|
|
55
|
+
"aria-label": `${n} 페이지`,
|
|
56
|
+
"aria-current": n === e ? "page" : void 0,
|
|
57
|
+
onClick: () => r(n),
|
|
58
|
+
className: c(
|
|
59
|
+
"size-6 rounded-full inline-flex items-center justify-center shrink-0 text-body-3-m transition-colors focus-visible:outline-none",
|
|
60
|
+
n === e ? "text-ds-text-strong" : "text-ds-text-disabled"
|
|
61
|
+
),
|
|
62
|
+
children: n
|
|
63
|
+
},
|
|
64
|
+
n
|
|
65
|
+
)),
|
|
66
|
+
/* @__PURE__ */ t(
|
|
67
|
+
"button",
|
|
68
|
+
{
|
|
69
|
+
type: "button",
|
|
70
|
+
"aria-label": "다음 페이지",
|
|
71
|
+
disabled: i,
|
|
72
|
+
onClick: () => !i && r(e + 1),
|
|
73
|
+
className: i ? l : s,
|
|
74
|
+
children: /* @__PURE__ */ t(p, {})
|
|
75
|
+
}
|
|
76
|
+
),
|
|
77
|
+
/* @__PURE__ */ t(
|
|
78
|
+
"button",
|
|
79
|
+
{
|
|
80
|
+
type: "button",
|
|
81
|
+
"aria-label": "마지막 페이지",
|
|
82
|
+
disabled: i,
|
|
83
|
+
onClick: () => !i && r(a),
|
|
84
|
+
className: i ? l : s,
|
|
85
|
+
children: /* @__PURE__ */ t(w, {})
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
] })
|
|
89
|
+
}
|
|
90
|
+
),
|
|
91
|
+
u && /* @__PURE__ */ t(
|
|
92
|
+
"button",
|
|
93
|
+
{
|
|
94
|
+
type: "button",
|
|
95
|
+
onClick: m,
|
|
96
|
+
className: "h-9 px-3.5 rounded-lg border border-ds-line-normal bg-ds-background-default text-body-2-m text-ds-text-strong shrink-0 transition-colors focus-visible:outline-none",
|
|
97
|
+
children: "TOP으로"
|
|
98
|
+
}
|
|
99
|
+
)
|
|
100
|
+
] });
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
A.displayName = "Pagination";
|
|
104
|
+
export {
|
|
105
|
+
A as Pagination
|
|
106
|
+
};
|
|
@@ -2,6 +2,13 @@ import * as React from "react";
|
|
|
2
2
|
export interface RadioProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "onChange"> {
|
|
3
3
|
/** 선택 시 value를 전달하는 핸들러 */
|
|
4
4
|
onChange?: (value: string) => void;
|
|
5
|
+
/**
|
|
6
|
+
* 라디오 옆에 표시할 라벨 텍스트.
|
|
7
|
+
* 이 컴포넌트는 자체적으로 `<label>`을 렌더하므로, 밖에서 `<label>`로 감싸면
|
|
8
|
+
* label이 중첩되어 연결이 깨진다. 텍스트는 반드시 여기로 넘긴다.
|
|
9
|
+
* (텍스트 없이 쓸 때는 `aria-label`을 지정할 것)
|
|
10
|
+
*/
|
|
11
|
+
children?: React.ReactNode;
|
|
5
12
|
}
|
|
6
13
|
declare const Radio: React.ForwardRefExoticComponent<RadioProps & React.RefAttributes<HTMLInputElement>>;
|
|
7
14
|
export { Radio };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as d, jsx as e } from "react/jsx-runtime";
|
|
3
|
+
import { RadioCheckedDisabledIcon as p, RadioUncheckedDisabledIcon as f, RadioCheckedIcon as R, RadioUncheckedIcon as k } from "../../lib/icons.js";
|
|
4
|
+
import { cn as x } from "../../lib/utils.js";
|
|
5
|
+
import * as u from "react";
|
|
6
|
+
const I = u.forwardRef(
|
|
7
|
+
({ className: a, checked: o, disabled: r, onChange: i, value: c, children: s, ...n }, t) => {
|
|
8
|
+
const l = r ? o ? /* @__PURE__ */ e(p, {}) : /* @__PURE__ */ e(f, {}) : o ? /* @__PURE__ */ e(R, {}) : /* @__PURE__ */ e(k, {});
|
|
9
|
+
return /* @__PURE__ */ d(
|
|
10
|
+
"label",
|
|
11
|
+
{
|
|
12
|
+
className: x(
|
|
13
|
+
"relative inline-flex items-center gap-1",
|
|
14
|
+
s ? "" : "shrink-0",
|
|
15
|
+
r ? "cursor-not-allowed" : "cursor-pointer",
|
|
16
|
+
a
|
|
17
|
+
),
|
|
18
|
+
children: [
|
|
19
|
+
/* @__PURE__ */ e(
|
|
20
|
+
"input",
|
|
21
|
+
{
|
|
22
|
+
type: "radio",
|
|
23
|
+
ref: t,
|
|
24
|
+
checked: o,
|
|
25
|
+
disabled: r,
|
|
26
|
+
value: c,
|
|
27
|
+
onChange: (m) => m.target.checked && (i == null ? void 0 : i(String(c ?? ""))),
|
|
28
|
+
className: "sr-only",
|
|
29
|
+
...n
|
|
30
|
+
}
|
|
31
|
+
),
|
|
32
|
+
/* @__PURE__ */ e("span", { className: "shrink-0 inline-flex", children: l }),
|
|
33
|
+
s
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
I.displayName = "Radio";
|
|
40
|
+
export {
|
|
41
|
+
I as Radio
|
|
42
|
+
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { DsSize } from '../../lib/size';
|
|
1
2
|
import * as React from "react";
|
|
2
3
|
export interface SearchFieldProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> {
|
|
3
4
|
/** 라벨 텍스트 */
|
|
@@ -6,8 +7,8 @@ export interface SearchFieldProps extends Omit<React.InputHTMLAttributes<HTMLInp
|
|
|
6
7
|
showLabel?: boolean;
|
|
7
8
|
/** 검색 아이콘 표시 여부. 기본값: true */
|
|
8
9
|
showIcon?: boolean;
|
|
9
|
-
/** 크기. 기본값: "
|
|
10
|
-
size?: "
|
|
10
|
+
/** 크기. 기본값: "lg" */
|
|
11
|
+
size?: Extract<DsSize, "lg" | "md" | "sm">;
|
|
11
12
|
/** 에러 메시지. 표시 시 필드에 빨간 테두리 적용 */
|
|
12
13
|
error?: string;
|
|
13
14
|
/** 필드 하단 힌트 텍스트 */
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as p, jsx as t } from "react/jsx-runtime";
|
|
3
|
+
import { SearchIcon as v, CloseIcon as w } from "../../lib/icons.js";
|
|
4
|
+
import { cn as r } from "../../lib/utils.js";
|
|
5
|
+
import * as b from "react";
|
|
6
|
+
const f = {
|
|
7
|
+
lg: {
|
|
8
|
+
container: "h-11 px-3 gap-1.5",
|
|
9
|
+
text: "text-body-2-r"
|
|
10
|
+
},
|
|
11
|
+
md: {
|
|
12
|
+
container: "h-9 px-3 gap-1.5",
|
|
13
|
+
text: "text-body-3-r"
|
|
14
|
+
},
|
|
15
|
+
sm: {
|
|
16
|
+
container: "h-8 px-3 gap-1.5",
|
|
17
|
+
text: "text-body-3-r"
|
|
18
|
+
}
|
|
19
|
+
}, k = b.forwardRef(
|
|
20
|
+
({
|
|
21
|
+
label: a,
|
|
22
|
+
showLabel: h = !0,
|
|
23
|
+
showIcon: u = !0,
|
|
24
|
+
size: d = "lg",
|
|
25
|
+
error: e,
|
|
26
|
+
hint: s,
|
|
27
|
+
onClear: o,
|
|
28
|
+
wrapperClassName: g,
|
|
29
|
+
className: y,
|
|
30
|
+
disabled: n,
|
|
31
|
+
value: i,
|
|
32
|
+
...l
|
|
33
|
+
}, N) => {
|
|
34
|
+
const I = !n && !!o && !!i, c = b.useId(), x = l.id ?? c, m = `${c}-description`;
|
|
35
|
+
return /* @__PURE__ */ p("div", { className: r("flex flex-col gap-2", g), children: [
|
|
36
|
+
h && a && /* @__PURE__ */ t("label", { htmlFor: x, className: "text-body-2-r text-ds-text-strong", children: a }),
|
|
37
|
+
/* @__PURE__ */ p(
|
|
38
|
+
"div",
|
|
39
|
+
{
|
|
40
|
+
className: r(
|
|
41
|
+
"flex items-center overflow-hidden bg-ds-background-default border rounded-lg transition-colors",
|
|
42
|
+
e ? "border-ds-primary-red-normal" : "border-ds-line-normal hover:border-ds-line-strong focus-within:border-ds-primary-blue-normal",
|
|
43
|
+
n && "bg-ds-surface-normal",
|
|
44
|
+
f[d].container
|
|
45
|
+
),
|
|
46
|
+
children: [
|
|
47
|
+
u && /* @__PURE__ */ t(v, { className: "shrink-0 text-ds-text-normal" }),
|
|
48
|
+
/* @__PURE__ */ t(
|
|
49
|
+
"input",
|
|
50
|
+
{
|
|
51
|
+
ref: N,
|
|
52
|
+
id: x,
|
|
53
|
+
value: i,
|
|
54
|
+
"aria-invalid": e ? !0 : void 0,
|
|
55
|
+
"aria-describedby": e || s ? m : void 0,
|
|
56
|
+
className: r(
|
|
57
|
+
"flex-1 min-w-0 bg-transparent outline-none font-sans",
|
|
58
|
+
"text-ds-text-strong placeholder:text-ds-text-normal",
|
|
59
|
+
"disabled:text-ds-text-disabled",
|
|
60
|
+
f[d].text,
|
|
61
|
+
y
|
|
62
|
+
),
|
|
63
|
+
disabled: n,
|
|
64
|
+
...l
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
I && /* @__PURE__ */ t(
|
|
68
|
+
"button",
|
|
69
|
+
{
|
|
70
|
+
type: "button",
|
|
71
|
+
onClick: o,
|
|
72
|
+
"aria-label": "검색어 지우기",
|
|
73
|
+
className: "flex items-center justify-center",
|
|
74
|
+
tabIndex: -1,
|
|
75
|
+
children: /* @__PURE__ */ t(w, { className: "shrink-0 text-ds-text-normal" })
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
(e || s) && /* @__PURE__ */ t(
|
|
82
|
+
"p",
|
|
83
|
+
{
|
|
84
|
+
id: m,
|
|
85
|
+
className: r(
|
|
86
|
+
"text-body-4-r",
|
|
87
|
+
e ? "text-ds-primary-red-normal" : "text-ds-text-normal"
|
|
88
|
+
),
|
|
89
|
+
children: e ?? s
|
|
90
|
+
}
|
|
91
|
+
)
|
|
92
|
+
] });
|
|
93
|
+
}
|
|
94
|
+
);
|
|
95
|
+
k.displayName = "SearchField";
|
|
96
|
+
export {
|
|
97
|
+
k as SearchField
|
|
98
|
+
};
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs as x, jsx as i } from "react/jsx-runtime";
|
|
3
|
+
import { InfoIcon as F, SortArrowIcon as P } from "../../lib/icons.js";
|
|
4
|
+
import { cn as g } from "../../lib/utils.js";
|
|
5
|
+
import * as h from "react";
|
|
6
|
+
import { Checkbox as j } from "./checkbox.js";
|
|
7
|
+
const L = {
|
|
8
|
+
borderRight: "3px solid var(--ds-line-normal)"
|
|
9
|
+
}, w = h.forwardRef(
|
|
10
|
+
({ className: s, ...r }, a) => /* @__PURE__ */ i(
|
|
11
|
+
"div",
|
|
12
|
+
{
|
|
13
|
+
ref: a,
|
|
14
|
+
role: "table",
|
|
15
|
+
className: g("w-full overflow-x-auto", s),
|
|
16
|
+
...r
|
|
17
|
+
}
|
|
18
|
+
)
|
|
19
|
+
);
|
|
20
|
+
w.displayName = "TableRoot";
|
|
21
|
+
const E = h.forwardRef(
|
|
22
|
+
(s, r) => /* @__PURE__ */ i("div", { ref: r, role: "rowgroup", ...s })
|
|
23
|
+
);
|
|
24
|
+
E.displayName = "TableHead";
|
|
25
|
+
const H = h.forwardRef(
|
|
26
|
+
(s, r) => /* @__PURE__ */ i("div", { ref: r, role: "rowgroup", ...s })
|
|
27
|
+
);
|
|
28
|
+
H.displayName = "TableBody";
|
|
29
|
+
const N = h.forwardRef(
|
|
30
|
+
({ className: s, hoverable: r = !0, selected: a, ...n }, l) => /* @__PURE__ */ i(
|
|
31
|
+
"div",
|
|
32
|
+
{
|
|
33
|
+
ref: l,
|
|
34
|
+
role: "row",
|
|
35
|
+
"aria-selected": a,
|
|
36
|
+
className: g(
|
|
37
|
+
"flex items-stretch w-full",
|
|
38
|
+
r && "hover:bg-ds-surface-strong",
|
|
39
|
+
a && "bg-ds-surface-normal",
|
|
40
|
+
s
|
|
41
|
+
),
|
|
42
|
+
...n
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
N.displayName = "TableRow";
|
|
47
|
+
const k = h.forwardRef(
|
|
48
|
+
({
|
|
49
|
+
className: s,
|
|
50
|
+
children: r,
|
|
51
|
+
sortable: a,
|
|
52
|
+
sortDirection: n,
|
|
53
|
+
onSort: l,
|
|
54
|
+
info: d,
|
|
55
|
+
fixedLine: c,
|
|
56
|
+
align: f = "left",
|
|
57
|
+
width: p,
|
|
58
|
+
style: b,
|
|
59
|
+
...y
|
|
60
|
+
}, m) => {
|
|
61
|
+
const v = a && n != null;
|
|
62
|
+
return /* @__PURE__ */ x(
|
|
63
|
+
"div",
|
|
64
|
+
{
|
|
65
|
+
ref: m,
|
|
66
|
+
role: "columnheader",
|
|
67
|
+
tabIndex: a ? 0 : void 0,
|
|
68
|
+
"aria-sort": a ? n === "asc" ? "ascending" : n === "desc" ? "descending" : "none" : void 0,
|
|
69
|
+
className: g(
|
|
70
|
+
"flex h-10 items-center gap-1 border-t border-ds-line-normal bg-ds-surface-normal px-3 py-2.5",
|
|
71
|
+
p ? "shrink-0" : "flex-1 min-w-0",
|
|
72
|
+
f === "right" && "justify-end",
|
|
73
|
+
a && "cursor-pointer select-none focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ds-primary-blue-normal",
|
|
74
|
+
s
|
|
75
|
+
),
|
|
76
|
+
style: { width: p, ...c ? L : {}, ...b },
|
|
77
|
+
onClick: a ? l : void 0,
|
|
78
|
+
onKeyDown: a ? (u) => {
|
|
79
|
+
(u.key === "Enter" || u.key === " ") && (u.preventDefault(), l == null || l());
|
|
80
|
+
} : void 0,
|
|
81
|
+
...y,
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ i("span", { className: "text-body-3-r text-ds-text-strong whitespace-nowrap", children: r }),
|
|
84
|
+
d && /* @__PURE__ */ i(F, { className: "shrink-0 text-ds-text-disabled" }),
|
|
85
|
+
a && /* @__PURE__ */ i(
|
|
86
|
+
P,
|
|
87
|
+
{
|
|
88
|
+
className: g(
|
|
89
|
+
"shrink-0 transition-transform duration-150",
|
|
90
|
+
v ? "text-ds-text-strong" : "text-ds-text-disabled",
|
|
91
|
+
n === "asc" && "rotate-180"
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
k.displayName = "TableHeaderCell";
|
|
101
|
+
const T = h.forwardRef(
|
|
102
|
+
({ className: s, align: r = "left", fixedLine: a, width: n, style: l, children: d, ...c }, f) => /* @__PURE__ */ i(
|
|
103
|
+
"div",
|
|
104
|
+
{
|
|
105
|
+
ref: f,
|
|
106
|
+
role: "cell",
|
|
107
|
+
className: g(
|
|
108
|
+
"flex items-center border-b border-ds-line-normal px-3 py-2",
|
|
109
|
+
n ? "shrink-0" : "flex-1 min-w-0",
|
|
110
|
+
r === "right" && "justify-end",
|
|
111
|
+
s
|
|
112
|
+
),
|
|
113
|
+
style: { width: n, ...a ? L : {}, ...l },
|
|
114
|
+
...c,
|
|
115
|
+
children: d
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
);
|
|
119
|
+
T.displayName = "TableCell";
|
|
120
|
+
function q({
|
|
121
|
+
columns: s,
|
|
122
|
+
data: r,
|
|
123
|
+
sortKey: a,
|
|
124
|
+
sortDirection: n,
|
|
125
|
+
onSort: l,
|
|
126
|
+
selectedRows: d,
|
|
127
|
+
onRowSelect: c,
|
|
128
|
+
onSelectAll: f,
|
|
129
|
+
getRowKey: p,
|
|
130
|
+
onRowClick: b,
|
|
131
|
+
className: y
|
|
132
|
+
}) {
|
|
133
|
+
const m = d !== void 0, v = m && r.length > 0 && d.length === r.length, u = m && d.length > 0 && d.length < r.length, B = (e) => {
|
|
134
|
+
if (!l) return;
|
|
135
|
+
l(e, a === e && n === "asc" ? "desc" : "asc");
|
|
136
|
+
};
|
|
137
|
+
return /* @__PURE__ */ x(w, { className: y, children: [
|
|
138
|
+
/* @__PURE__ */ i(E, { children: /* @__PURE__ */ x(N, { hoverable: !1, children: [
|
|
139
|
+
m && /* @__PURE__ */ i(k, { width: 40, className: "justify-center px-1.5", children: /* @__PURE__ */ i(
|
|
140
|
+
j,
|
|
141
|
+
{
|
|
142
|
+
"aria-label": "전체 선택",
|
|
143
|
+
checked: v,
|
|
144
|
+
indeterminate: u,
|
|
145
|
+
onChange: (e) => f == null ? void 0 : f(e)
|
|
146
|
+
}
|
|
147
|
+
) }),
|
|
148
|
+
s.map((e) => /* @__PURE__ */ i(
|
|
149
|
+
k,
|
|
150
|
+
{
|
|
151
|
+
sortable: e.sortable,
|
|
152
|
+
sortDirection: e.sortable && a === e.key ? n ?? null : null,
|
|
153
|
+
onSort: () => B(e.key),
|
|
154
|
+
info: e.info,
|
|
155
|
+
fixedLine: e.fixedLine,
|
|
156
|
+
align: e.align,
|
|
157
|
+
width: e.width,
|
|
158
|
+
children: e.header
|
|
159
|
+
},
|
|
160
|
+
e.key
|
|
161
|
+
))
|
|
162
|
+
] }) }),
|
|
163
|
+
/* @__PURE__ */ i(H, { children: r.map((e, o) => {
|
|
164
|
+
const _ = p ? p(e, o) : o, C = m && d.includes(o);
|
|
165
|
+
return /* @__PURE__ */ x(
|
|
166
|
+
N,
|
|
167
|
+
{
|
|
168
|
+
selected: C,
|
|
169
|
+
onClick: b ? () => b(e, o) : void 0,
|
|
170
|
+
className: b ? "cursor-pointer" : void 0,
|
|
171
|
+
children: [
|
|
172
|
+
m && /* @__PURE__ */ i(T, { width: 40, className: "justify-center px-1.5", children: /* @__PURE__ */ i(
|
|
173
|
+
j,
|
|
174
|
+
{
|
|
175
|
+
"aria-label": `${o + 1}번째 행 선택`,
|
|
176
|
+
checked: C,
|
|
177
|
+
onChange: (t) => c == null ? void 0 : c(o, t),
|
|
178
|
+
onClick: (t) => t.stopPropagation()
|
|
179
|
+
}
|
|
180
|
+
) }),
|
|
181
|
+
s.map((t) => /* @__PURE__ */ i(
|
|
182
|
+
T,
|
|
183
|
+
{
|
|
184
|
+
align: t.align,
|
|
185
|
+
fixedLine: t.fixedLine,
|
|
186
|
+
width: t.width,
|
|
187
|
+
children: /* @__PURE__ */ i("span", { className: "text-body-3-r text-ds-text-strong w-full", children: t.cell ? t.cell(e, o) : String(e[t.key] ?? "") })
|
|
188
|
+
},
|
|
189
|
+
t.key
|
|
190
|
+
))
|
|
191
|
+
]
|
|
192
|
+
},
|
|
193
|
+
_
|
|
194
|
+
);
|
|
195
|
+
}) })
|
|
196
|
+
] });
|
|
197
|
+
}
|
|
198
|
+
export {
|
|
199
|
+
q as Table,
|
|
200
|
+
H as TableBody,
|
|
201
|
+
T as TableCell,
|
|
202
|
+
E as TableHead,
|
|
203
|
+
k as TableHeaderCell,
|
|
204
|
+
w as TableRoot,
|
|
205
|
+
N as TableRow
|
|
206
|
+
};
|