@pylerai/design-system 2.2.0 → 2.3.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.
@@ -1,9 +1,9 @@
1
1
  "use client";
2
- import { jsxs as u, jsx as r } from "react/jsx-runtime";
3
- import { DropdownArrowIcon as _, SelectCheckIcon as C, CheckboxCheckedIcon as V, CheckboxUncheckedIcon as ee, RadioCheckedIcon as te, RadioUncheckedIcon as re } from "../../lib/icons.js";
4
- import { cn as m } from "../../lib/utils.js";
5
- import * as l from "react";
6
- import { Button as q } from "./button.js";
2
+ import { jsxs as u, jsx as t } from "react/jsx-runtime";
3
+ import { DropdownArrowIcon as V, SelectCheckIcon as ee, CheckboxCheckedIcon as re, CheckboxUncheckedIcon as te, RadioCheckedIcon as ne, RadioUncheckedIcon as se } from "../../lib/icons.js";
4
+ import { cn as f } from "../../lib/utils.js";
5
+ import * as s from "react";
6
+ import { Button as U } from "./button.js";
7
7
  const k = {
8
8
  lg: {
9
9
  trigger: "h-11 pl-3 pr-2 gap-1.5",
@@ -20,150 +20,151 @@ const k = {
20
20
  option: "h-8 pl-3 pr-2",
21
21
  text: "text-body-3-r"
22
22
  }
23
- }, se = l.forwardRef(
23
+ }, ae = s.forwardRef(
24
24
  ({
25
- type: i = "default",
26
- options: o,
27
- value: A,
28
- onValueChange: w,
29
- values: n,
30
- onValuesChange: N,
31
- placeholder: L = "선택해주세요",
25
+ type: c = "default",
26
+ options: i,
27
+ value: R,
28
+ onValueChange: K,
29
+ values: m,
30
+ onValuesChange: T,
31
+ placeholder: D = "선택해주세요",
32
32
  label: h,
33
33
  showLabel: v = !0,
34
- require: M,
34
+ require: E,
35
35
  size: g = "lg",
36
36
  disabled: x,
37
- readOnly: y,
37
+ readOnly: w,
38
38
  error: b,
39
- hint: I,
40
- leftIcon: O,
41
- showButtons: z,
42
- cancelLabel: B = "취소",
43
- confirmLabel: H = "확인",
44
- onCancel: R,
45
- onConfirm: S,
46
- wrapperClassName: F,
47
- className: G,
48
- "aria-label": J
49
- }, P) => {
50
- const [s, d] = l.useState(!1), [c, D] = l.useState(-1), E = l.useRef(null), U = l.useRef(null), K = l.useRef(null), f = l.useId(), j = (e) => `${f}-option-${e}`;
51
- l.useEffect(() => {
52
- const e = (t) => {
53
- E.current && !E.current.contains(t.target) && d(!1);
39
+ hint: N,
40
+ leftIcon: j,
41
+ showButtons: q,
42
+ cancelLabel: z = "취소",
43
+ confirmLabel: B = "확인",
44
+ onCancel: H,
45
+ onConfirm: F,
46
+ wrapperClassName: G,
47
+ className: J,
48
+ "aria-label": P
49
+ }, Q) => {
50
+ const [n, l] = s.useState(!1), [a, p] = s.useState(-1), [$, A] = s.useState("keyboard"), y = s.useRef(null), L = s.useRef(null), M = s.useRef(null), d = s.useId(), I = (e) => `${d}-option-${e}`;
51
+ s.useEffect(() => {
52
+ const e = (r) => {
53
+ y.current && !y.current.contains(r.target) && l(!1);
54
54
  };
55
55
  return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
56
- }, []), l.useEffect(() => {
57
- s || D(-1);
58
- }, [s]), l.useEffect(() => {
59
- var e, t;
60
- !s || c < 0 || (t = (e = U.current) == null ? void 0 : e.querySelector(`#${CSS.escape(j(c))}`)) == null || t.scrollIntoView({ block: "nearest" });
61
- }, [s, c]);
62
- const Q = (e) => i === "checkbox" ? (n == null ? void 0 : n.includes(e)) ?? !1 : e === A, $ = o.find((e) => e.value === A), W = () => i === "checkbox" ? !n || n.length === 0 ? L : o.filter((t) => n.includes(t.value)).map((t) => t.label).join(", ") : $ ? $.label : L, X = () => {
63
- x || y || d((e) => !e);
64
- }, T = (e) => {
65
- if (i === "checkbox") {
66
- const t = n ?? [], a = t.includes(e) ? t.filter((p) => p !== e) : [...t, e];
67
- N == null || N(a);
56
+ }, []), s.useEffect(() => {
57
+ n || p(-1);
58
+ }, [n]), s.useEffect(() => {
59
+ !n || a < 0 || L.current?.querySelector(`#${CSS.escape(I(a))}`)?.scrollIntoView({ block: "nearest" });
60
+ }, [n, a]);
61
+ const W = (e) => c === "checkbox" ? m?.includes(e) ?? !1 : e === R, C = i.find((e) => e.value === R), X = () => c === "checkbox" ? !m || m.length === 0 ? D : i.filter((r) => m.includes(r.value)).map((r) => r.label).join(", ") : C ? C.label : D, Y = () => {
62
+ x || w || l((e) => !e);
63
+ }, O = (e) => {
64
+ if (c === "checkbox") {
65
+ const r = m ?? [], o = r.includes(e) ? r.filter((S) => S !== e) : [...r, e];
66
+ T?.(o);
68
67
  } else
69
- w == null || w(e), d(!1);
70
- }, Y = i === "checkbox" ? ((n == null ? void 0 : n.length) ?? 0) > 0 : !!$, Z = (e) => {
71
- var a;
72
- if (x || y) return;
73
- const t = (p) => {
74
- e.preventDefault(), s || d(!0), D(p);
68
+ K?.(e), l(!1);
69
+ }, Z = c === "checkbox" ? (m?.length ?? 0) > 0 : !!C, _ = (e) => {
70
+ if (x || w) return;
71
+ const r = (o) => {
72
+ e.preventDefault(), n || l(!0), A("keyboard"), p(o);
75
73
  };
76
74
  switch (e.key) {
77
75
  case "ArrowDown":
78
- return t(s ? Math.min(c + 1, o.length - 1) : 0);
76
+ return r(n ? Math.min(a + 1, i.length - 1) : 0);
79
77
  case "ArrowUp":
80
- return t(s ? Math.max(c - 1, 0) : o.length - 1);
78
+ return r(n ? Math.max(a - 1, 0) : i.length - 1);
81
79
  case "Home":
82
- return s ? t(0) : void 0;
80
+ return n ? r(0) : void 0;
83
81
  case "End":
84
- return s ? t(o.length - 1) : void 0;
82
+ return n ? r(i.length - 1) : void 0;
85
83
  case "Enter":
86
84
  case " ":
87
- e.preventDefault(), s ? c >= 0 && T(o[c].value) : d(!0);
85
+ e.preventDefault(), n ? a >= 0 && O(i[a].value) : l(!0);
88
86
  return;
89
87
  case "Escape":
90
- s && (e.preventDefault(), d(!1), (a = K.current) == null || a.focus());
88
+ n && (e.preventDefault(), l(!1), M.current?.focus());
91
89
  return;
92
90
  case "Tab":
93
- d(!1);
91
+ l(!1);
94
92
  return;
95
93
  default:
96
94
  return;
97
95
  }
98
96
  };
99
- return /* @__PURE__ */ u("div", { ref: P, className: m("flex flex-col gap-2", F), children: [
97
+ return /* @__PURE__ */ u("div", { ref: Q, className: f("flex flex-col gap-2", G), children: [
100
98
  v && h && /* @__PURE__ */ u("div", { className: "flex items-start gap-0.5 whitespace-nowrap", children: [
101
- /* @__PURE__ */ r("span", { id: `${f}-label`, className: "text-body-2-r text-ds-text-strong", children: h }),
102
- M && /* @__PURE__ */ r("span", { "aria-hidden": "true", className: "text-body-2-r text-ds-primary-red-normal", children: "*" })
99
+ /* @__PURE__ */ t("span", { id: `${d}-label`, className: "text-body-2-r text-ds-text-strong", children: h }),
100
+ E && /* @__PURE__ */ t("span", { "aria-hidden": "true", className: "text-body-2-r text-ds-primary-red-normal", children: "*" })
103
101
  ] }),
104
- /* @__PURE__ */ u("div", { ref: E, className: "relative", children: [
102
+ /* @__PURE__ */ u("div", { ref: y, className: "relative", children: [
105
103
  /* @__PURE__ */ u(
106
104
  "button",
107
105
  {
108
- ref: K,
106
+ ref: M,
109
107
  type: "button",
110
108
  role: "combobox",
111
- "aria-expanded": s,
109
+ "aria-expanded": n,
112
110
  "aria-haspopup": "listbox",
113
- "aria-controls": s ? f : void 0,
114
- "aria-activedescendant": s && c >= 0 ? j(c) : void 0,
115
- "aria-labelledby": v && h ? `${f}-label` : void 0,
116
- "aria-label": v && h ? void 0 : J,
111
+ "aria-controls": n ? d : void 0,
112
+ "aria-activedescendant": n && a >= 0 ? I(a) : void 0,
113
+ "aria-labelledby": v && h ? `${d}-label` : void 0,
114
+ "aria-label": v && h ? void 0 : P,
117
115
  "aria-invalid": b ? !0 : void 0,
118
- "aria-describedby": b || I ? `${f}-description` : void 0,
119
- "aria-required": M || void 0,
116
+ "aria-describedby": b || N ? `${d}-description` : void 0,
117
+ "aria-required": E || void 0,
120
118
  disabled: x,
121
- onClick: X,
122
- onKeyDown: Z,
123
- className: m(
119
+ onClick: Y,
120
+ onKeyDown: _,
121
+ className: f(
124
122
  "flex items-center w-full rounded-ds-md border transition-colors",
125
- x ? "bg-ds-surface-strong border-ds-line-normal cursor-not-allowed" : y ? "bg-ds-surface-normal border-ds-line-normal cursor-default" : b ? "bg-ds-background-default border-ds-primary-red-normal hover:bg-ds-surface-normal" : s ? "bg-ds-background-default border-ds-primary-blue-normal" : "bg-ds-background-default border-ds-line-normal hover:bg-ds-surface-normal hover:border-ds-line-strong",
123
+ x ? "bg-ds-surface-strong border-ds-line-normal cursor-not-allowed" : w ? "bg-ds-surface-normal border-ds-line-normal cursor-default" : b ? "bg-ds-background-default border-ds-primary-red-normal hover:bg-ds-surface-normal" : n ? "bg-ds-background-default border-ds-primary-blue-normal" : "bg-ds-background-default border-ds-line-normal hover:bg-ds-surface-normal hover:border-ds-primary-blue-normal",
126
124
  k[g].trigger,
127
- G
125
+ J
128
126
  ),
129
127
  children: [
130
- O && /* @__PURE__ */ r("span", { className: "shrink-0 flex items-center justify-center text-ds-icon-normal", children: O }),
131
- /* @__PURE__ */ r(
128
+ j && /* @__PURE__ */ t("span", { className: "shrink-0 flex items-center justify-center text-ds-icon-normal", children: j }),
129
+ /* @__PURE__ */ t(
132
130
  "span",
133
131
  {
134
- className: m(
132
+ className: f(
135
133
  "flex-1 min-w-0 text-left truncate font-sans",
136
134
  k[g].text,
137
- Y ? "text-ds-text-strong" : x ? "text-ds-text-disabled" : "text-ds-text-normal"
135
+ Z ? "text-ds-text-strong" : x ? "text-ds-text-disabled" : "text-ds-text-normal"
138
136
  ),
139
- children: W()
137
+ children: X()
140
138
  }
141
139
  ),
142
- /* @__PURE__ */ r(
140
+ /* @__PURE__ */ t(
143
141
  "span",
144
142
  {
145
- className: m(
143
+ className: f(
146
144
  "shrink-0 flex items-center justify-center transition-transform",
147
- s && "rotate-180",
148
- x ? "text-ds-text-disabled" : "text-ds-text-normal"
145
+ n && "rotate-180",
146
+ x ? "text-ds-text-disabled" : "text-ds-icon-strong"
149
147
  ),
150
- children: /* @__PURE__ */ r(_, {})
148
+ children: /* @__PURE__ */ t(V, {})
151
149
  }
152
150
  )
153
151
  ]
154
152
  }
155
153
  ),
156
- s && /* @__PURE__ */ u(
154
+ n && /* @__PURE__ */ u(
157
155
  "ul",
158
156
  {
159
- ref: U,
160
- id: f,
157
+ ref: L,
158
+ id: d,
161
159
  role: "listbox",
162
- "aria-multiselectable": i === "checkbox" ? !0 : void 0,
160
+ "aria-multiselectable": c === "checkbox" ? !0 : void 0,
163
161
  className: "absolute top-full left-0 z-50 mt-1 min-w-full w-max max-w-sm bg-ds-background-default border border-ds-line-normal rounded-ds-md p-1 shadow-ds-default",
162
+ onMouseLeave: () => {
163
+ $ === "mouse" && p(-1);
164
+ },
164
165
  children: [
165
- o.map((e, t) => {
166
- const a = Q(e.value), p = t === c;
166
+ i.map((e, r) => {
167
+ const o = W(e.value), S = r === a;
167
168
  return (
168
169
  // 키보드 조작은 aria-activedescendant 패턴에 따라 combobox 트리거의
169
170
  // onKeyDown이 전담한다(옵션은 포커스를 받지 않는 것이 WAI-ARIA 권고).
@@ -172,23 +173,25 @@ const k = {
172
173
  /* @__PURE__ */ u(
173
174
  "li",
174
175
  {
175
- id: j(t),
176
+ id: I(r),
176
177
  role: "option",
177
- "aria-selected": a,
178
- onClick: () => T(e.value),
179
- onMouseEnter: () => D(t),
180
- className: m(
178
+ "aria-selected": o,
179
+ onClick: () => O(e.value),
180
+ onMouseEnter: () => {
181
+ A("mouse"), p(r);
182
+ },
183
+ className: f(
181
184
  "flex items-center rounded-ds-md cursor-pointer gap-1.5 transition-colors",
182
185
  k[g].option,
183
- a ? "bg-ds-surface-normal" : "bg-ds-background-default hover:bg-ds-surface-normal",
184
- // 키보드 이동 위치 표시 (마우스 hover와 구분되도록 링으로)
185
- p && "ring-1 ring-inset ring-ds-primary-blue-normal"
186
+ o ? "bg-ds-surface-normal" : "bg-ds-background-default hover:bg-ds-surface-normal",
187
+ // 키보드 이동 위치 표시 (마우스 hover와 구분되도록 링으로, 키보드 이동에만)
188
+ S && $ === "keyboard" && "ring-1 ring-inset ring-ds-primary-blue-normal"
186
189
  ),
187
190
  children: [
188
- /* @__PURE__ */ r(
191
+ /* @__PURE__ */ t(
189
192
  "span",
190
193
  {
191
- className: m(
194
+ className: f(
192
195
  "flex-1 min-w-0 truncate font-sans",
193
196
  k[g].text,
194
197
  "text-ds-text-strong"
@@ -196,39 +199,39 @@ const k = {
196
199
  children: e.label
197
200
  }
198
201
  ),
199
- i === "default" && a && /* @__PURE__ */ r("span", { className: "shrink-0 flex items-center justify-center text-ds-text-strong", children: /* @__PURE__ */ r(C, {}) }),
200
- i === "checkbox" && /* @__PURE__ */ r("span", { className: "shrink-0 flex items-center justify-center", children: a ? /* @__PURE__ */ r(V, {}) : /* @__PURE__ */ r(ee, {}) }),
201
- i === "radio" && /* @__PURE__ */ r("span", { className: "shrink-0 flex items-center justify-center", children: a ? /* @__PURE__ */ r(te, {}) : /* @__PURE__ */ r(re, {}) })
202
+ c === "default" && o && /* @__PURE__ */ t("span", { className: "shrink-0 flex items-center justify-center text-ds-text-strong", children: /* @__PURE__ */ t(ee, {}) }),
203
+ c === "checkbox" && /* @__PURE__ */ t("span", { className: "shrink-0 flex items-center justify-center", children: o ? /* @__PURE__ */ t(re, {}) : /* @__PURE__ */ t(te, {}) }),
204
+ c === "radio" && /* @__PURE__ */ t("span", { className: "shrink-0 flex items-center justify-center", children: o ? /* @__PURE__ */ t(ne, {}) : /* @__PURE__ */ t(se, {}) })
202
205
  ]
203
206
  },
204
207
  e.value
205
208
  )
206
209
  );
207
210
  }),
208
- z && /* @__PURE__ */ u("li", { className: "flex gap-2 pt-1", children: [
209
- /* @__PURE__ */ r(
210
- q,
211
+ q && /* @__PURE__ */ u("li", { className: "flex gap-2 pt-1", children: [
212
+ /* @__PURE__ */ t(
213
+ U,
211
214
  {
212
215
  variant: "outlined",
213
216
  size: "lg",
214
217
  className: "flex-1",
215
218
  onClick: () => {
216
- R == null || R(), d(!1);
219
+ H?.(), l(!1);
217
220
  },
218
- children: B
221
+ children: z
219
222
  }
220
223
  ),
221
- /* @__PURE__ */ r(
222
- q,
224
+ /* @__PURE__ */ t(
225
+ U,
223
226
  {
224
227
  variant: "filled",
225
228
  color: "blue",
226
229
  size: "lg",
227
230
  className: "flex-1",
228
231
  onClick: () => {
229
- S == null || S(), d(!1);
232
+ F?.(), l(!1);
230
233
  },
231
- children: H
234
+ children: B
232
235
  }
233
236
  )
234
237
  ] })
@@ -236,21 +239,21 @@ const k = {
236
239
  }
237
240
  )
238
241
  ] }),
239
- (b || I) && /* @__PURE__ */ r(
242
+ (b || N) && /* @__PURE__ */ t(
240
243
  "p",
241
244
  {
242
- id: `${f}-description`,
243
- className: m(
245
+ id: `${d}-description`,
246
+ className: f(
244
247
  "text-body-4-r",
245
248
  b ? "text-ds-primary-red-normal" : "text-ds-text-normal"
246
249
  ),
247
- children: b ?? I
250
+ children: b ?? N
248
251
  }
249
252
  )
250
253
  ] });
251
254
  }
252
255
  );
253
- se.displayName = "Dropdown";
256
+ ae.displayName = "Dropdown";
254
257
  export {
255
- se as Dropdown
258
+ ae as Dropdown
256
259
  };
@@ -8,9 +8,11 @@ export interface InformationModalProps {
8
8
  confirmLabel?: string;
9
9
  onConfirm?: () => void;
10
10
  onClose: () => void;
11
+ /** 배경 딤 표시 여부. 기본값: true */
12
+ dim?: boolean;
11
13
  className?: string;
12
14
  }
13
- declare function InformationModal({ open, title, description, confirmLabel, onConfirm, onClose, className, }: InformationModalProps): React.ReactPortal | null;
15
+ declare function InformationModal({ open, title, description, confirmLabel, onConfirm, onClose, dim, className, }: InformationModalProps): React.ReactPortal | null;
14
16
  export interface ActionModalProps {
15
17
  open: boolean;
16
18
  title: React.ReactNode;
@@ -22,9 +24,11 @@ export interface ActionModalProps {
22
24
  onCancel?: () => void;
23
25
  onConfirm?: () => void;
24
26
  onClose: () => void;
27
+ /** 배경 딤 표시 여부. 기본값: true */
28
+ dim?: boolean;
25
29
  className?: string;
26
30
  }
27
- declare function ActionModal({ open, title, description, cancelLabel, confirmLabel, onCancel, onConfirm, onClose, className, }: ActionModalProps): React.ReactPortal | null;
31
+ declare function ActionModal({ open, title, description, cancelLabel, confirmLabel, onCancel, onConfirm, onClose, dim, className, }: ActionModalProps): React.ReactPortal | null;
28
32
  export type ContentModalSize = Extract<DsSize, "lg" | "md" | "sm">;
29
33
  export interface ContentModalProps {
30
34
  open: boolean;
@@ -40,7 +44,9 @@ export interface ContentModalProps {
40
44
  onConfirm?: () => void;
41
45
  onClose: () => void;
42
46
  children?: React.ReactNode;
47
+ /** 배경 딤 표시 여부. 기본값: true */
48
+ dim?: boolean;
43
49
  className?: string;
44
50
  }
45
- declare function ContentModal({ open, title, description, size, cancelLabel, confirmLabel, onCancel, onConfirm, onClose, children, className, }: ContentModalProps): React.ReactPortal | null;
51
+ declare function ContentModal({ open, title, description, size, cancelLabel, confirmLabel, onCancel, onConfirm, onClose, children, dim, className, }: ContentModalProps): React.ReactPortal | null;
46
52
  export { InformationModal, ActionModal, ContentModal };