@pylerai/design-system 1.2.4 → 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.
Files changed (49) hide show
  1. package/README.md +169 -316
  2. package/dist/components/ui/badge.d.ts +2 -1
  3. package/dist/components/ui/badge.js +49 -0
  4. package/dist/components/ui/body.js +52 -0
  5. package/dist/components/ui/button.d.ts +2 -1
  6. package/dist/components/ui/button.js +172 -0
  7. package/dist/components/ui/calendar.js +275 -0
  8. package/dist/components/ui/checkbox.d.ts +7 -0
  9. package/dist/components/ui/checkbox.js +45 -0
  10. package/dist/components/ui/chip.d.ts +4 -3
  11. package/dist/components/ui/chip.js +66 -0
  12. package/dist/components/ui/dropdown.d.ts +8 -2
  13. package/dist/components/ui/dropdown.js +256 -0
  14. package/dist/components/ui/headline.js +50 -0
  15. package/dist/components/ui/input.d.ts +3 -2
  16. package/dist/components/ui/input.js +129 -0
  17. package/dist/components/ui/label.js +43 -0
  18. package/dist/components/ui/loading-bar.d.ts +2 -1
  19. package/dist/components/ui/loading-bar.js +64 -0
  20. package/dist/components/ui/modal.d.ts +3 -2
  21. package/dist/components/ui/modal.js +170 -0
  22. package/dist/components/ui/pagination.js +106 -0
  23. package/dist/components/ui/radio.d.ts +7 -0
  24. package/dist/components/ui/radio.js +42 -0
  25. package/dist/components/ui/search-field.d.ts +3 -2
  26. package/dist/components/ui/search-field.js +98 -0
  27. package/dist/components/ui/table.js +206 -0
  28. package/dist/components/ui/tabs.js +149 -0
  29. package/dist/components/ui/tag.d.ts +2 -1
  30. package/dist/components/ui/tag.js +31 -0
  31. package/dist/components/ui/tips.d.ts +2 -1
  32. package/dist/components/ui/tips.js +25 -0
  33. package/dist/components/ui/toast.js +70 -0
  34. package/dist/components/ui/toggle.d.ts +1 -2
  35. package/dist/components/ui/toggle.js +41 -0
  36. package/dist/components/ui/use-modal.js +94 -0
  37. package/dist/index.d.ts +1 -0
  38. package/dist/index.js +75 -5779
  39. package/dist/lib/icons.js +225 -0
  40. package/dist/lib/size.d.ts +8 -0
  41. package/dist/lib/use-dialog-a11y.d.ts +2 -0
  42. package/dist/lib/use-dialog-a11y.js +50 -0
  43. package/dist/lib/utils.js +16 -0
  44. package/dist/style.css +1 -1
  45. package/dist/tokens/pyler-light.js +134 -0
  46. package/dist/tokens/typography.js +84 -0
  47. package/package.json +14 -1
  48. package/pyler-tailwind-colors.cjs +4 -0
  49. 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
+ };
@@ -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
- /** 크기. 기본값: "large" */
10
- size?: "large" | "medium" | "small";
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
+ };