@petnow/ui 5.4.0 → 6.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/CHANGELOG.md +30 -0
- package/dist/combobox.js +166 -152
- package/dist/combobox.js.map +1 -1
- package/dist/{fieldStyles-DyZu__hI.js → fieldStyles-DXyDrzxD.js} +5 -6
- package/dist/fieldStyles-DXyDrzxD.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.es.js +17 -17
- package/dist/mergeRefs-CsNeQOZ6.js +39 -0
- package/dist/mergeRefs-CsNeQOZ6.js.map +1 -0
- package/dist/select.js +86 -66
- package/dist/select.js.map +1 -1
- package/dist/src/components/combobox/Combobox.d.ts +1 -0
- package/dist/src/components/select/Select.d.ts +13 -6
- package/dist/src/components/text-field/TextField.d.ts +1 -20
- package/dist/src/components/ui/listbox.d.ts +1 -0
- package/dist/src/components/ui/listboxStyles.d.ts +8 -0
- package/dist/text-field.js +50 -114
- package/dist/text-field.js.map +1 -1
- package/dist/v1/text-field.js +1 -1
- package/docs/migration/v5-to-v6.md +59 -0
- package/package.json +1 -1
- package/dist/fieldStyles-DyZu__hI.js.map +0 -1
- package/dist/mergeRefs-BHwdBwNQ.js +0 -27
- package/dist/mergeRefs-BHwdBwNQ.js.map +0 -1
package/dist/text-field.js
CHANGED
|
@@ -2,37 +2,35 @@
|
|
|
2
2
|
import { t as e } from "./TailwindUtil-DiNvXuNl.js";
|
|
3
3
|
import { CTAButton as t } from "./cta-button.js";
|
|
4
4
|
import { CancelFilledIcon as n } from "./icons/action/cancel-filled.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import * as c from "react";
|
|
9
|
-
import { cva as l } from "class-variance-authority";
|
|
5
|
+
import { r, t as i } from "./fieldStyles-DXyDrzxD.js";
|
|
6
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
7
|
+
import * as s from "react";
|
|
10
8
|
//#region src/components/text-field/TextField.tsx
|
|
11
|
-
var
|
|
12
|
-
let S = !!d, C =
|
|
13
|
-
|
|
14
|
-
let w =
|
|
9
|
+
var c = s.forwardRef(({ onChange: t, subtitle: c, isRequired: l = !1, assistiveText: u, errorText: d, disabled: f = !1, multiLine: p = !1, className: m, rightElement: h, showCounter: g = !1, value: _, maxLength: v, size: y = "large", ...b }, x) => {
|
|
10
|
+
let S = !!d, C = s.useRef(null);
|
|
11
|
+
s.useImperativeHandle(x, () => C.current);
|
|
12
|
+
let w = s.useCallback(() => {
|
|
15
13
|
C.current?.focus();
|
|
16
14
|
}, []), T = (typeof _ == "string" ? _ : "").length, E = b, D = b, O = y === "large" ? "text-title-20-regular" : "text-body-16-regular", k = y === "large" ? "text-title-18-bold" : "text-title-14-bold", A = y === "large" ? "text-body-16-regular" : "text-caption-12-medium";
|
|
17
|
-
return /* @__PURE__ */
|
|
15
|
+
return /* @__PURE__ */ o("div", {
|
|
18
16
|
className: e("flex flex-col gap-2", m),
|
|
19
17
|
children: [
|
|
20
|
-
|
|
18
|
+
c && /* @__PURE__ */ o("span", {
|
|
21
19
|
className: e(k, "text-text-base-neutral-5"),
|
|
22
|
-
children: [
|
|
20
|
+
children: [c, l && /* @__PURE__ */ a("span", {
|
|
23
21
|
className: "text-text-prominent-accent-1",
|
|
24
22
|
children: "*"
|
|
25
23
|
})]
|
|
26
24
|
}),
|
|
27
|
-
/* @__PURE__ */
|
|
25
|
+
/* @__PURE__ */ o("div", {
|
|
28
26
|
onClick: f ? void 0 : w,
|
|
29
|
-
className: e("group overflow-hidden",
|
|
27
|
+
className: e("group overflow-hidden", i({
|
|
30
28
|
size: y,
|
|
31
29
|
disabled: f,
|
|
32
30
|
hasError: S
|
|
33
31
|
}), !f && !S && "focus-within:border-border-base-neutral-4", p && "h-[120px] items-start"),
|
|
34
32
|
children: [
|
|
35
|
-
p ? /* @__PURE__ */
|
|
33
|
+
p ? /* @__PURE__ */ a("textarea", {
|
|
36
34
|
...D,
|
|
37
35
|
onChange: t,
|
|
38
36
|
ref: C,
|
|
@@ -40,7 +38,7 @@ var u = c.forwardRef(({ onChange: t, subtitle: r, isRequired: l = !1, assistiveT
|
|
|
40
38
|
maxLength: v,
|
|
41
39
|
disabled: f,
|
|
42
40
|
className: e("text-text-base-neutral-5 placeholder:text-text-base-neutral-2 h-full min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none", O, "resize-none overflow-y-auto")
|
|
43
|
-
}) : /* @__PURE__ */
|
|
41
|
+
}) : /* @__PURE__ */ a("input", {
|
|
44
42
|
...E,
|
|
45
43
|
onChange: t,
|
|
46
44
|
ref: C,
|
|
@@ -49,11 +47,11 @@ var u = c.forwardRef(({ onChange: t, subtitle: r, isRequired: l = !1, assistiveT
|
|
|
49
47
|
disabled: f,
|
|
50
48
|
className: e("text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none", O, "overflow-hidden text-ellipsis whitespace-nowrap")
|
|
51
49
|
}),
|
|
52
|
-
h && /* @__PURE__ */
|
|
50
|
+
h && /* @__PURE__ */ a("div", {
|
|
53
51
|
className: "shrink-0",
|
|
54
52
|
children: h
|
|
55
53
|
}),
|
|
56
|
-
/* @__PURE__ */
|
|
54
|
+
/* @__PURE__ */ a("button", {
|
|
57
55
|
type: "button",
|
|
58
56
|
onClick: () => t && t({ target: { value: "" } }),
|
|
59
57
|
tabIndex: -1,
|
|
@@ -62,20 +60,20 @@ var u = c.forwardRef(({ onChange: t, subtitle: r, isRequired: l = !1, assistiveT
|
|
|
62
60
|
flex: S,
|
|
63
61
|
"group-focus-within:flex": !f && T > 0
|
|
64
62
|
}),
|
|
65
|
-
children: /* @__PURE__ */
|
|
63
|
+
children: /* @__PURE__ */ a(n, { className: "text-icon-base-neutral-3 h-6 w-6 shrink-0 cursor-pointer" })
|
|
66
64
|
})
|
|
67
65
|
]
|
|
68
66
|
}),
|
|
69
|
-
(u || d || v && g) && /* @__PURE__ */
|
|
67
|
+
(u || d || v && g) && /* @__PURE__ */ o("div", {
|
|
70
68
|
className: "flex items-center justify-between gap-2",
|
|
71
|
-
children: [(u || d) && /* @__PURE__ */
|
|
72
|
-
className: e(A,
|
|
69
|
+
children: [(u || d) && /* @__PURE__ */ a("span", {
|
|
70
|
+
className: e(A, r({
|
|
73
71
|
size: y,
|
|
74
72
|
hasError: S
|
|
75
73
|
})),
|
|
76
74
|
children: d || u
|
|
77
|
-
}), v && g && /* @__PURE__ */
|
|
78
|
-
className: e("ml-auto", A,
|
|
75
|
+
}), v && g && /* @__PURE__ */ o("span", {
|
|
76
|
+
className: e("ml-auto", A, r({
|
|
79
77
|
size: y,
|
|
80
78
|
hasError: S
|
|
81
79
|
})),
|
|
@@ -89,131 +87,69 @@ var u = c.forwardRef(({ onChange: t, subtitle: r, isRequired: l = !1, assistiveT
|
|
|
89
87
|
]
|
|
90
88
|
});
|
|
91
89
|
});
|
|
92
|
-
|
|
93
|
-
var
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
small: "gap-3 p-[11px] min-h-[48px]"
|
|
98
|
-
},
|
|
99
|
-
hasError: {
|
|
100
|
-
true: "border-border-prominent-error",
|
|
101
|
-
false: "border-transparent"
|
|
102
|
-
},
|
|
103
|
-
disabled: {
|
|
104
|
-
true: "opacity-50",
|
|
105
|
-
false: ""
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
defaultVariants: { size: "large" }
|
|
109
|
-
}), f = ({ label: t, placeholder: n, value: a, isRequired: c = !1, disabled: l = !1, assistiveText: u, errorText: f, onPress: p, className: m, size: h = "large" }) => {
|
|
110
|
-
let g = !!f, _ = h === "large" ? "text-title-18-bold" : "text-title-14-bold", v = h === "large" ? "text-title-20-regular" : "text-body-16-regular";
|
|
111
|
-
return /* @__PURE__ */ s("div", {
|
|
112
|
-
className: e("flex w-full flex-col gap-2", m),
|
|
113
|
-
children: [
|
|
114
|
-
t && /* @__PURE__ */ s("div", {
|
|
115
|
-
className: "flex items-start",
|
|
116
|
-
children: [/* @__PURE__ */ o("span", {
|
|
117
|
-
className: e(_, "text-text-base-neutral-5"),
|
|
118
|
-
children: t
|
|
119
|
-
}), c && /* @__PURE__ */ o("span", {
|
|
120
|
-
className: e(_, "text-text-prominent-accent-1"),
|
|
121
|
-
children: "*"
|
|
122
|
-
})]
|
|
123
|
-
}),
|
|
124
|
-
/* @__PURE__ */ s("button", {
|
|
125
|
-
type: "button",
|
|
126
|
-
className: d({
|
|
127
|
-
size: h,
|
|
128
|
-
hasError: g,
|
|
129
|
-
disabled: l
|
|
130
|
-
}),
|
|
131
|
-
onClick: p,
|
|
132
|
-
disabled: l,
|
|
133
|
-
children: [/* @__PURE__ */ o("span", {
|
|
134
|
-
className: e(v, "flex-1", a ? "text-text-base-neutral-5" : "text-text-base-neutral-2"),
|
|
135
|
-
style: {
|
|
136
|
-
textAlign: "left",
|
|
137
|
-
overflow: "hidden",
|
|
138
|
-
textOverflow: "ellipsis"
|
|
139
|
-
},
|
|
140
|
-
children: a || n
|
|
141
|
-
}), /* @__PURE__ */ o(r, { className: "text-icon-base-neutral-3 rotate-270" })]
|
|
142
|
-
}),
|
|
143
|
-
(u || f) && /* @__PURE__ */ o("div", {
|
|
144
|
-
className: "flex items-start gap-2",
|
|
145
|
-
children: /* @__PURE__ */ o("span", {
|
|
146
|
-
className: i({
|
|
147
|
-
size: h,
|
|
148
|
-
hasError: g
|
|
149
|
-
}),
|
|
150
|
-
children: f || u
|
|
151
|
-
})
|
|
152
|
-
})
|
|
153
|
-
]
|
|
154
|
-
});
|
|
155
|
-
}, p = c.forwardRef(({ onChange: r, subtitle: l, isRequired: u = !1, assistiveText: d, errorText: f, disabled: p = !1, multiLine: m = !1, className: h, showCounter: g = !1, value: _, maxLength: v, size: y = "large", fieldRightElement: b, buttonText: x, onButtonClick: S, buttonDisabled: C = !1, ...w }, T) => {
|
|
156
|
-
let E = !!f, D = c.useRef(null);
|
|
157
|
-
c.useImperativeHandle(T, () => D.current);
|
|
158
|
-
let O = c.useCallback(() => {
|
|
90
|
+
c.displayName = "TextFieldNormal";
|
|
91
|
+
var l = s.forwardRef(({ onChange: c, subtitle: l, isRequired: u = !1, assistiveText: d, errorText: f, disabled: p = !1, multiLine: m = !1, className: h, showCounter: g = !1, value: _, maxLength: v, size: y = "large", fieldRightElement: b, buttonText: x, onButtonClick: S, buttonDisabled: C = !1, ...w }, T) => {
|
|
92
|
+
let E = !!f, D = s.useRef(null);
|
|
93
|
+
s.useImperativeHandle(T, () => D.current);
|
|
94
|
+
let O = s.useCallback(() => {
|
|
159
95
|
D.current?.focus();
|
|
160
96
|
}, []), k = (typeof _ == "string" ? _ : "").length, A = w, j = w, M = y === "large" ? "text-title-20-regular" : "text-body-16-regular", N = y === "large" ? "text-title-18-bold" : "text-title-14-bold", P = y === "large" ? "text-body-16-regular" : "text-caption-12-medium";
|
|
161
|
-
return /* @__PURE__ */
|
|
97
|
+
return /* @__PURE__ */ o("div", {
|
|
162
98
|
className: e("flex flex-col gap-2", h),
|
|
163
99
|
children: [
|
|
164
|
-
l && /* @__PURE__ */
|
|
100
|
+
l && /* @__PURE__ */ o("span", {
|
|
165
101
|
className: e(N, "text-text-base-neutral-5"),
|
|
166
|
-
children: [l, u && /* @__PURE__ */
|
|
102
|
+
children: [l, u && /* @__PURE__ */ a("span", {
|
|
167
103
|
className: "text-text-prominent-accent-1",
|
|
168
104
|
children: "*"
|
|
169
105
|
})]
|
|
170
106
|
}),
|
|
171
|
-
/* @__PURE__ */
|
|
107
|
+
/* @__PURE__ */ o("div", {
|
|
172
108
|
className: "flex items-center gap-2",
|
|
173
|
-
children: [/* @__PURE__ */
|
|
109
|
+
children: [/* @__PURE__ */ o("div", {
|
|
174
110
|
onClick: p ? void 0 : O,
|
|
175
|
-
className: e("group flex-1 overflow-hidden",
|
|
111
|
+
className: e("group flex-1 overflow-hidden", i({
|
|
176
112
|
size: y,
|
|
177
113
|
disabled: p,
|
|
178
114
|
hasError: E
|
|
179
115
|
}), !p && !E && "focus-within:border-border-base-neutral-4", m && "h-[120px] items-start"),
|
|
180
116
|
children: [
|
|
181
|
-
m ? /* @__PURE__ */
|
|
117
|
+
m ? /* @__PURE__ */ a("textarea", {
|
|
182
118
|
...j,
|
|
183
|
-
onChange:
|
|
119
|
+
onChange: c,
|
|
184
120
|
ref: D,
|
|
185
121
|
value: _,
|
|
186
122
|
maxLength: v,
|
|
187
123
|
disabled: p,
|
|
188
124
|
className: e("text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none", M, "resize-none overflow-y-auto")
|
|
189
|
-
}) : /* @__PURE__ */
|
|
125
|
+
}) : /* @__PURE__ */ a("input", {
|
|
190
126
|
...A,
|
|
191
|
-
onChange:
|
|
127
|
+
onChange: c,
|
|
192
128
|
ref: D,
|
|
193
129
|
value: _,
|
|
194
130
|
maxLength: v,
|
|
195
131
|
disabled: p,
|
|
196
132
|
className: e("text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none", M, "overflow-hidden text-ellipsis whitespace-nowrap")
|
|
197
133
|
}),
|
|
198
|
-
b && /* @__PURE__ */
|
|
134
|
+
b && /* @__PURE__ */ a("div", {
|
|
199
135
|
className: "shrink-0",
|
|
200
136
|
children: b
|
|
201
137
|
}),
|
|
202
|
-
/* @__PURE__ */
|
|
138
|
+
/* @__PURE__ */ a("button", {
|
|
203
139
|
type: "button",
|
|
204
|
-
onClick: () =>
|
|
140
|
+
onClick: () => c && c({ target: { value: "" } }),
|
|
205
141
|
tabIndex: -1,
|
|
206
142
|
disabled: p,
|
|
207
143
|
className: e("hidden shrink-0", {
|
|
208
144
|
flex: E,
|
|
209
145
|
"group-focus-within:flex": !p && k > 0
|
|
210
146
|
}),
|
|
211
|
-
children: /* @__PURE__ */
|
|
147
|
+
children: /* @__PURE__ */ a(n, { className: "text-icon-base-neutral-3 h-6 w-6 shrink-0 cursor-pointer" })
|
|
212
148
|
})
|
|
213
149
|
]
|
|
214
|
-
}), /* @__PURE__ */
|
|
150
|
+
}), /* @__PURE__ */ a("div", {
|
|
215
151
|
className: "shrink-0",
|
|
216
|
-
children: /* @__PURE__ */
|
|
152
|
+
children: /* @__PURE__ */ a(t, {
|
|
217
153
|
label: x,
|
|
218
154
|
onClick: S,
|
|
219
155
|
size: "medium",
|
|
@@ -222,16 +158,16 @@ var d = l("flex items-center justify-between rounded-[4px] bg-surface-base-neutr
|
|
|
222
158
|
})
|
|
223
159
|
})]
|
|
224
160
|
}),
|
|
225
|
-
(d || f || v && g) && /* @__PURE__ */
|
|
161
|
+
(d || f || v && g) && /* @__PURE__ */ o("div", {
|
|
226
162
|
className: "flex items-center justify-between gap-2",
|
|
227
|
-
children: [(d || f) && /* @__PURE__ */
|
|
228
|
-
className: e(P,
|
|
163
|
+
children: [(d || f) && /* @__PURE__ */ a("span", {
|
|
164
|
+
className: e(P, r({
|
|
229
165
|
size: y,
|
|
230
166
|
hasError: E
|
|
231
167
|
})),
|
|
232
168
|
children: f || d
|
|
233
|
-
}), v && g && /* @__PURE__ */
|
|
234
|
-
className: e("ml-auto", P,
|
|
169
|
+
}), v && g && /* @__PURE__ */ o("span", {
|
|
170
|
+
className: e("ml-auto", P, r({
|
|
235
171
|
size: y,
|
|
236
172
|
hasError: E
|
|
237
173
|
})),
|
|
@@ -245,8 +181,8 @@ var d = l("flex items-center justify-between rounded-[4px] bg-surface-base-neutr
|
|
|
245
181
|
]
|
|
246
182
|
});
|
|
247
183
|
});
|
|
248
|
-
|
|
184
|
+
l.displayName = "TextFieldWithButton";
|
|
249
185
|
//#endregion
|
|
250
|
-
export {
|
|
186
|
+
export { c as TextFieldNormal, l as TextFieldWithButton };
|
|
251
187
|
|
|
252
188
|
//# sourceMappingURL=text-field.js.map
|
package/dist/text-field.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-field.js","names":[],"sources":["../src/components/text-field/TextField.tsx"],"sourcesContent":["\"use client\";\n\nimport { cva, VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { CTAButton } from \"../cta-button/CTAButton\";\nimport { CancelFilledIcon } from \"../icons/action/CancelFilledIcon\";\nimport { ChevronLeftIcon } from \"../icons/action/ChevronLeftIcon\";\n\nimport {\n fieldContainerVariants as textFieldNormalContainerVariants,\n fieldMessageVariants as textFieldAssistiveAreaVariants,\n} from \"@/components/ui/fieldStyles\";\nimport { cn } from \"@/utils/TailwindUtil\";\n\ninterface TextFieldNormalProps extends Omit<React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>, \"size\"> {\n subtitle?: string;\n isRequired?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n disabled?: boolean;\n multiLine?: boolean;\n className?: string;\n rightElement?: React.ReactNode;\n showCounter?: boolean;\n size?: \"large\" | \"small\";\n}\n\nconst TextFieldNormal = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, TextFieldNormalProps>(\n (\n {\n onChange,\n subtitle,\n isRequired = false,\n assistiveText,\n errorText,\n disabled = false,\n multiLine = false,\n className,\n rightElement,\n showCounter = false,\n value,\n maxLength,\n size = \"large\",\n ...inputProps\n },\n ref,\n ) => {\n const hasError = !!errorText;\n const inputRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement | HTMLTextAreaElement);\n\n const handleContainerClick = React.useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n const stringValue = typeof value === \"string\" ? value : \"\";\n const currentLength = stringValue.length;\n\n const inputPropsForInput = inputProps as React.ComponentPropsWithoutRef<\"input\">;\n const inputPropsForTextarea = inputProps as React.ComponentPropsWithoutRef<\"textarea\">;\n\n // 사이즈별 폰트 크기\n const inputFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n const subtitleFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const assistiveFontSize = size === \"large\" ? \"text-body-16-regular\" : \"text-caption-12-medium\";\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {subtitle && (\n <span className={cn(subtitleFontSize, \"text-text-base-neutral-5\")}>\n {subtitle}\n {isRequired && <span className=\"text-text-prominent-accent-1\">*</span>}\n </span>\n )}\n\n <div\n onClick={disabled ? undefined : handleContainerClick}\n className={cn(\n \"group overflow-hidden\",\n textFieldNormalContainerVariants({ size, disabled, hasError }),\n !disabled && !hasError && \"focus-within:border-border-base-neutral-4\",\n multiLine && \"h-[120px] items-start\",\n )}\n >\n {multiLine ? (\n <textarea\n {...inputPropsForTextarea}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLTextAreaElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 h-full min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"resize-none overflow-y-auto\",\n )}\n />\n ) : (\n <input\n {...inputPropsForInput}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLInputElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"overflow-hidden text-ellipsis whitespace-nowrap\",\n )}\n />\n )}\n\n {rightElement && <div className=\"shrink-0\">{rightElement}</div>}\n\n <button\n type=\"button\"\n onClick={() =>\n onChange &&\n onChange({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>)\n }\n tabIndex={-1}\n disabled={disabled}\n className={cn(\"hidden shrink-0\", {\n flex: hasError,\n \"group-focus-within:flex\": !disabled && currentLength > 0,\n })}\n >\n <CancelFilledIcon className=\"text-icon-base-neutral-3 h-6 w-6 shrink-0 cursor-pointer\" />\n </button>\n </div>\n\n {(assistiveText || errorText || (maxLength && showCounter)) && (\n <div className=\"flex items-center justify-between gap-2\">\n {(assistiveText || errorText) && (\n <span className={cn(assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {errorText || assistiveText}\n </span>\n )}\n {maxLength && showCounter && (\n <span className={cn(\"ml-auto\", assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {currentLength}/{maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n );\n },\n);\nTextFieldNormal.displayName = \"TextFieldNormal\";\n\n// TextField Select 컴포넌트\nconst textFieldSelectVariants = cva(\n \"flex items-center justify-between rounded-[4px] bg-surface-base-neutral-2 border transition-colors duration-200\",\n {\n variants: {\n size: {\n large: \"gap-2 p-[15px] min-h-[56px]\",\n small: \"gap-3 p-[11px] min-h-[48px]\",\n },\n hasError: {\n true: \"border-border-prominent-error\",\n false: \"border-transparent\",\n },\n disabled: {\n true: \"opacity-50\",\n false: \"\",\n },\n },\n defaultVariants: {\n size: \"large\",\n },\n },\n);\n\ninterface TextFieldSelectProps extends VariantProps<typeof textFieldSelectVariants> {\n label?: string;\n placeholder: string;\n value?: string;\n isRequired?: boolean;\n disabled?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n onPress?: () => void;\n className?: string;\n size?: \"large\" | \"small\";\n}\n\nconst TextFieldSelect = ({\n label,\n placeholder,\n value,\n isRequired = false,\n disabled = false,\n assistiveText,\n errorText,\n onPress,\n className,\n size = \"large\",\n}: TextFieldSelectProps) => {\n const hasError = !!errorText;\n\n // 사이즈별 폰트 크기\n const labelFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const valueFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n\n return (\n <div className={cn(\"flex w-full flex-col gap-2\", className)}>\n {/* Label with optional asterisk */}\n {label && (\n <div className=\"flex items-start\">\n <span className={cn(labelFontSize, \"text-text-base-neutral-5\")}>{label}</span>\n {isRequired && <span className={cn(labelFontSize, \"text-text-prominent-accent-1\")}>*</span>}\n </div>\n )}\n {/* Select Field */}\n <button\n type=\"button\"\n className={textFieldSelectVariants({ size, hasError, disabled })}\n onClick={onPress}\n disabled={disabled}\n >\n <span\n className={cn(valueFontSize, \"flex-1\", value ? \"text-text-base-neutral-5\" : \"text-text-base-neutral-2\")}\n style={{ textAlign: \"left\", overflow: \"hidden\", textOverflow: \"ellipsis\" }}\n >\n {value || placeholder}\n </span>\n <ChevronLeftIcon className=\"text-icon-base-neutral-3 rotate-270\" />\n </button>\n {/* Assistive/Error Text */}\n {(assistiveText || errorText) && (\n <div className=\"flex items-start gap-2\">\n <span className={textFieldAssistiveAreaVariants({ size, hasError })}>{errorText || assistiveText}</span>\n </div>\n )}\n </div>\n );\n};\n\n// TextField With Button 컴포넌트\ninterface TextFieldWithButtonProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>, \"size\"> {\n subtitle?: string;\n isRequired?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n disabled?: boolean;\n multiLine?: boolean;\n className?: string;\n showCounter?: boolean;\n size?: \"large\" | \"small\";\n fieldRightElement?: React.ReactNode;\n buttonText: string;\n onButtonClick: () => void;\n buttonDisabled?: boolean;\n}\n\nconst TextFieldWithButton = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, TextFieldWithButtonProps>(\n (\n {\n onChange,\n subtitle,\n isRequired = false,\n assistiveText,\n errorText,\n disabled = false,\n multiLine = false,\n className,\n showCounter = false,\n value,\n maxLength,\n size = \"large\",\n fieldRightElement,\n buttonText,\n onButtonClick,\n buttonDisabled = false,\n ...inputProps\n },\n ref,\n ) => {\n const hasError = !!errorText;\n const inputRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement | HTMLTextAreaElement);\n\n const handleContainerClick = React.useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n const stringValue = typeof value === \"string\" ? value : \"\";\n const currentLength = stringValue.length;\n\n const inputPropsForInput = inputProps as React.ComponentPropsWithoutRef<\"input\">;\n const inputPropsForTextarea = inputProps as React.ComponentPropsWithoutRef<\"textarea\">;\n\n // 사이즈별 폰트 크기\n const inputFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n const subtitleFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const assistiveFontSize = size === \"large\" ? \"text-body-16-regular\" : \"text-caption-12-medium\";\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {subtitle && (\n <span className={cn(subtitleFontSize, \"text-text-base-neutral-5\")}>\n {subtitle}\n {isRequired && <span className=\"text-text-prominent-accent-1\">*</span>}\n </span>\n )}\n\n <div className=\"flex items-center gap-2\">\n <div\n onClick={disabled ? undefined : handleContainerClick}\n className={cn(\n \"group flex-1 overflow-hidden\",\n textFieldNormalContainerVariants({ size, disabled, hasError }),\n !disabled && !hasError && \"focus-within:border-border-base-neutral-4\",\n multiLine && \"h-[120px] items-start\",\n )}\n >\n {multiLine ? (\n <textarea\n {...inputPropsForTextarea}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLTextAreaElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"resize-none overflow-y-auto\",\n )}\n />\n ) : (\n <input\n {...inputPropsForInput}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLInputElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"overflow-hidden text-ellipsis whitespace-nowrap\",\n )}\n />\n )}\n\n {fieldRightElement && <div className=\"shrink-0\">{fieldRightElement}</div>}\n\n <button\n type=\"button\"\n onClick={() =>\n onChange &&\n onChange({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>)\n }\n tabIndex={-1}\n disabled={disabled}\n className={cn(\"hidden shrink-0\", {\n flex: hasError,\n \"group-focus-within:flex\": !disabled && currentLength > 0,\n })}\n >\n <CancelFilledIcon className=\"text-icon-base-neutral-3 h-6 w-6 shrink-0 cursor-pointer\" />\n </button>\n </div>\n\n <div className=\"shrink-0\">\n <CTAButton\n label={buttonText}\n onClick={onButtonClick}\n size=\"medium\"\n hierarchy=\"tertiary\"\n disabled={buttonDisabled || disabled}\n />\n </div>\n </div>\n\n {(assistiveText || errorText || (maxLength && showCounter)) && (\n <div className=\"flex items-center justify-between gap-2\">\n {(assistiveText || errorText) && (\n <span className={cn(assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {errorText || assistiveText}\n </span>\n )}\n {maxLength && showCounter && (\n <span className={cn(\"ml-auto\", assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {currentLength}/{maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n );\n },\n);\nTextFieldWithButton.displayName = \"TextFieldWithButton\";\n\nexport { TextFieldNormal, TextFieldSelect, TextFieldWithButton };\n"],"mappings":";;;;;;;;;;AA4BA,IAAM,IAAkB,EAAM,YAE1B,EACE,aACA,aACA,gBAAa,IACb,kBACA,cACA,cAAW,IACX,eAAY,IACZ,cACA,iBACA,iBAAc,IACd,UACA,cACA,UAAO,SACP,GAAG,KAEL,MACG;CACH,IAAM,IAAW,CAAC,CAAC,GACb,IAAW,EAAM,OAA+C,IAAI;CAE1E,EAAM,oBAAoB,SAAW,EAAS,OAAiD;CAE/F,IAAM,IAAuB,EAAM,kBAAkB;EACnD,EAAS,SAAS,MAAM;CAC1B,GAAG,CAAC,CAAC,GAGC,KADc,OAAO,KAAU,WAAW,IAAQ,GAAA,CACtB,QAE5B,IAAqB,GACrB,IAAwB,GAGxB,IAAgB,MAAS,UAAU,0BAA0B,wBAC7D,IAAmB,MAAS,UAAU,uBAAuB,sBAC7D,IAAoB,MAAS,UAAU,yBAAyB;CAEtE,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,uBAAuB,CAAS;YAAnD;GACG,KACC,kBAAC,QAAD;IAAM,WAAW,EAAG,GAAkB,0BAA0B;cAAhE,CACG,GACA,KAAc,kBAAC,QAAD;KAAM,WAAU;eAA+B;IAAO,CAAA,CACjE;;GAGR,kBAAC,OAAD;IACE,SAAS,IAAW,KAAA,IAAY;IAChC,WAAW,EACT,yBACA,EAAiC;KAAE;KAAM;KAAU;IAAS,CAAC,GAC7D,CAAC,KAAY,CAAC,KAAY,6CAC1B,KAAa,uBACf;cAPF;KASG,IACC,kBAAC,YAAD;MACE,GAAI;MACM;MACV,KAAK;MACE;MACI;MACD;MACV,WAAW,EACT,iJACA,GACA,6BACF;KACD,CAAA,IAED,kBAAC,SAAD;MACE,GAAI;MACM;MACV,KAAK;MACE;MACI;MACD;MACV,WAAW,EACT,0IACA,GACA,iDACF;KACD,CAAA;KAGF,KAAgB,kBAAC,OAAD;MAAK,WAAU;gBAAY;KAAkB,CAAA;KAE9D,kBAAC,UAAD;MACE,MAAK;MACL,eACE,KACA,EAAS,EAAE,QAAQ,EAAE,OAAO,GAAG,EAAE,CAA8D;MAEjG,UAAU;MACA;MACV,WAAW,EAAG,mBAAmB;OAC/B,MAAM;OACN,2BAA2B,CAAC,KAAY,IAAgB;MAC1D,CAAC;gBAED,kBAAC,GAAD,EAAkB,WAAU,2DAA4D,CAAA;KAClF,CAAA;IACL;;IAEH,KAAiB,KAAc,KAAa,MAC5C,kBAAC,OAAD;IAAK,WAAU;cAAf,EACI,KAAiB,MACjB,kBAAC,QAAD;KAAM,WAAW,EAAG,GAAmB,EAA+B;MAAE;MAAM;KAAS,CAAC,CAAC;eACtF,KAAa;IACV,CAAA,GAEP,KAAa,KACZ,kBAAC,QAAD;KAAM,WAAW,EAAG,WAAW,GAAmB,EAA+B;MAAE;MAAM;KAAS,CAAC,CAAC;eAApG;MACG;MAAc;MAAE;KACb;MAEL;;EAEJ;;AAET,CACF;AACA,EAAgB,cAAc;AAG9B,IAAM,IAA0B,EAC9B,mHACA;CACE,UAAU;EACR,MAAM;GACJ,OAAO;GACP,OAAO;EACT;EACA,UAAU;GACR,MAAM;GACN,OAAO;EACT;EACA,UAAU;GACR,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB,EACf,MAAM,QACR;AACF,CACF,GAeM,KAAmB,EACvB,UACA,gBACA,UACA,gBAAa,IACb,cAAW,IACX,kBACA,cACA,YACA,cACA,UAAO,cACmB;CAC1B,IAAM,IAAW,CAAC,CAAC,GAGb,IAAgB,MAAS,UAAU,uBAAuB,sBAC1D,IAAgB,MAAS,UAAU,0BAA0B;CAEnE,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,8BAA8B,CAAS;YAA1D;GAEG,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,QAAD;KAAM,WAAW,EAAG,GAAe,0BAA0B;eAAI;IAAY,CAAA,GAC5E,KAAc,kBAAC,QAAD;KAAM,WAAW,EAAG,GAAe,8BAA8B;eAAG;IAAO,CAAA,CACvF;;GAGP,kBAAC,UAAD;IACE,MAAK;IACL,WAAW,EAAwB;KAAE;KAAM;KAAU;IAAS,CAAC;IAC/D,SAAS;IACC;cAJZ,CAME,kBAAC,QAAD;KACE,WAAW,EAAG,GAAe,UAAU,IAAQ,6BAA6B,0BAA0B;KACtG,OAAO;MAAE,WAAW;MAAQ,UAAU;MAAU,cAAc;KAAW;eAExE,KAAS;IACN,CAAA,GACN,kBAAC,GAAD,EAAiB,WAAU,sCAAuC,CAAA,CAC5D;;IAEN,KAAiB,MACjB,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,QAAD;KAAM,WAAW,EAA+B;MAAE;MAAM;KAAS,CAAC;eAAI,KAAa;IAAoB,CAAA;GACpG,CAAA;EAEJ;;AAET,GAoBM,IAAsB,EAAM,YAE9B,EACE,aACA,aACA,gBAAa,IACb,kBACA,cACA,cAAW,IACX,eAAY,IACZ,cACA,iBAAc,IACd,UACA,cACA,UAAO,SACP,sBACA,eACA,kBACA,oBAAiB,IACjB,GAAG,KAEL,MACG;CACH,IAAM,IAAW,CAAC,CAAC,GACb,IAAW,EAAM,OAA+C,IAAI;CAE1E,EAAM,oBAAoB,SAAW,EAAS,OAAiD;CAE/F,IAAM,IAAuB,EAAM,kBAAkB;EACnD,EAAS,SAAS,MAAM;CAC1B,GAAG,CAAC,CAAC,GAGC,KADc,OAAO,KAAU,WAAW,IAAQ,GAAA,CACtB,QAE5B,IAAqB,GACrB,IAAwB,GAGxB,IAAgB,MAAS,UAAU,0BAA0B,wBAC7D,IAAmB,MAAS,UAAU,uBAAuB,sBAC7D,IAAoB,MAAS,UAAU,yBAAyB;CAEtE,OACE,kBAAC,OAAD;EAAK,WAAW,EAAG,uBAAuB,CAAS;YAAnD;GACG,KACC,kBAAC,QAAD;IAAM,WAAW,EAAG,GAAkB,0BAA0B;cAAhE,CACG,GACA,KAAc,kBAAC,QAAD;KAAM,WAAU;eAA+B;IAAO,CAAA,CACjE;;GAGR,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KACE,SAAS,IAAW,KAAA,IAAY;KAChC,WAAW,EACT,gCACA,EAAiC;MAAE;MAAM;MAAU;KAAS,CAAC,GAC7D,CAAC,KAAY,CAAC,KAAY,6CAC1B,KAAa,uBACf;eAPF;MASG,IACC,kBAAC,YAAD;OACE,GAAI;OACM;OACV,KAAK;OACE;OACI;OACD;OACV,WAAW,EACT,0IACA,GACA,6BACF;MACD,CAAA,IAED,kBAAC,SAAD;OACE,GAAI;OACM;OACV,KAAK;OACE;OACI;OACD;OACV,WAAW,EACT,0IACA,GACA,iDACF;MACD,CAAA;MAGF,KAAqB,kBAAC,OAAD;OAAK,WAAU;iBAAY;MAAuB,CAAA;MAExE,kBAAC,UAAD;OACE,MAAK;OACL,eACE,KACA,EAAS,EAAE,QAAQ,EAAE,OAAO,GAAG,EAAE,CAA8D;OAEjG,UAAU;OACA;OACV,WAAW,EAAG,mBAAmB;QAC/B,MAAM;QACN,2BAA2B,CAAC,KAAY,IAAgB;OAC1D,CAAC;iBAED,kBAAC,GAAD,EAAkB,WAAU,2DAA4D,CAAA;MAClF,CAAA;KACL;QAEL,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD;MACE,OAAO;MACP,SAAS;MACT,MAAK;MACL,WAAU;MACV,UAAU,KAAkB;KAC7B,CAAA;IACE,CAAA,CACF;;IAEH,KAAiB,KAAc,KAAa,MAC5C,kBAAC,OAAD;IAAK,WAAU;cAAf,EACI,KAAiB,MACjB,kBAAC,QAAD;KAAM,WAAW,EAAG,GAAmB,EAA+B;MAAE;MAAM;KAAS,CAAC,CAAC;eACtF,KAAa;IACV,CAAA,GAEP,KAAa,KACZ,kBAAC,QAAD;KAAM,WAAW,EAAG,WAAW,GAAmB,EAA+B;MAAE;MAAM;KAAS,CAAC,CAAC;eAApG;MACG;MAAc;MAAE;KACb;MAEL;;EAEJ;;AAET,CACF;AACA,EAAoB,cAAc"}
|
|
1
|
+
{"version":3,"file":"text-field.js","names":[],"sources":["../src/components/text-field/TextField.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\n\nimport { CTAButton } from \"../cta-button/CTAButton\";\nimport { CancelFilledIcon } from \"../icons/action/CancelFilledIcon\";\n\nimport {\n fieldContainerVariants as textFieldNormalContainerVariants,\n fieldMessageVariants as textFieldAssistiveAreaVariants,\n} from \"@/components/ui/fieldStyles\";\nimport { cn } from \"@/utils/TailwindUtil\";\n\ninterface TextFieldNormalProps extends Omit<React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>, \"size\"> {\n subtitle?: string;\n isRequired?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n disabled?: boolean;\n multiLine?: boolean;\n className?: string;\n rightElement?: React.ReactNode;\n showCounter?: boolean;\n size?: \"large\" | \"small\";\n}\n\nconst TextFieldNormal = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, TextFieldNormalProps>(\n (\n {\n onChange,\n subtitle,\n isRequired = false,\n assistiveText,\n errorText,\n disabled = false,\n multiLine = false,\n className,\n rightElement,\n showCounter = false,\n value,\n maxLength,\n size = \"large\",\n ...inputProps\n },\n ref,\n ) => {\n const hasError = !!errorText;\n const inputRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement | HTMLTextAreaElement);\n\n const handleContainerClick = React.useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n const stringValue = typeof value === \"string\" ? value : \"\";\n const currentLength = stringValue.length;\n\n const inputPropsForInput = inputProps as React.ComponentPropsWithoutRef<\"input\">;\n const inputPropsForTextarea = inputProps as React.ComponentPropsWithoutRef<\"textarea\">;\n\n // 사이즈별 폰트 크기\n const inputFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n const subtitleFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const assistiveFontSize = size === \"large\" ? \"text-body-16-regular\" : \"text-caption-12-medium\";\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {subtitle && (\n <span className={cn(subtitleFontSize, \"text-text-base-neutral-5\")}>\n {subtitle}\n {isRequired && <span className=\"text-text-prominent-accent-1\">*</span>}\n </span>\n )}\n\n <div\n onClick={disabled ? undefined : handleContainerClick}\n className={cn(\n \"group overflow-hidden\",\n textFieldNormalContainerVariants({ size, disabled, hasError }),\n !disabled && !hasError && \"focus-within:border-border-base-neutral-4\",\n multiLine && \"h-[120px] items-start\",\n )}\n >\n {multiLine ? (\n <textarea\n {...inputPropsForTextarea}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLTextAreaElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 h-full min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"resize-none overflow-y-auto\",\n )}\n />\n ) : (\n <input\n {...inputPropsForInput}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLInputElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"overflow-hidden text-ellipsis whitespace-nowrap\",\n )}\n />\n )}\n\n {rightElement && <div className=\"shrink-0\">{rightElement}</div>}\n\n <button\n type=\"button\"\n onClick={() =>\n onChange &&\n onChange({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>)\n }\n tabIndex={-1}\n disabled={disabled}\n className={cn(\"hidden shrink-0\", {\n flex: hasError,\n \"group-focus-within:flex\": !disabled && currentLength > 0,\n })}\n >\n <CancelFilledIcon className=\"text-icon-base-neutral-3 h-6 w-6 shrink-0 cursor-pointer\" />\n </button>\n </div>\n\n {(assistiveText || errorText || (maxLength && showCounter)) && (\n <div className=\"flex items-center justify-between gap-2\">\n {(assistiveText || errorText) && (\n <span className={cn(assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {errorText || assistiveText}\n </span>\n )}\n {maxLength && showCounter && (\n <span className={cn(\"ml-auto\", assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {currentLength}/{maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n );\n },\n);\nTextFieldNormal.displayName = \"TextFieldNormal\";\n\n// TextField With Button 컴포넌트\ninterface TextFieldWithButtonProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>, \"size\"> {\n subtitle?: string;\n isRequired?: boolean;\n assistiveText?: string | React.ReactNode;\n errorText?: string;\n disabled?: boolean;\n multiLine?: boolean;\n className?: string;\n showCounter?: boolean;\n size?: \"large\" | \"small\";\n fieldRightElement?: React.ReactNode;\n buttonText: string;\n onButtonClick: () => void;\n buttonDisabled?: boolean;\n}\n\nconst TextFieldWithButton = React.forwardRef<HTMLInputElement | HTMLTextAreaElement, TextFieldWithButtonProps>(\n (\n {\n onChange,\n subtitle,\n isRequired = false,\n assistiveText,\n errorText,\n disabled = false,\n multiLine = false,\n className,\n showCounter = false,\n value,\n maxLength,\n size = \"large\",\n fieldRightElement,\n buttonText,\n onButtonClick,\n buttonDisabled = false,\n ...inputProps\n },\n ref,\n ) => {\n const hasError = !!errorText;\n const inputRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n\n React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement | HTMLTextAreaElement);\n\n const handleContainerClick = React.useCallback(() => {\n inputRef.current?.focus();\n }, []);\n\n const stringValue = typeof value === \"string\" ? value : \"\";\n const currentLength = stringValue.length;\n\n const inputPropsForInput = inputProps as React.ComponentPropsWithoutRef<\"input\">;\n const inputPropsForTextarea = inputProps as React.ComponentPropsWithoutRef<\"textarea\">;\n\n // 사이즈별 폰트 크기\n const inputFontSize = size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n const subtitleFontSize = size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\";\n const assistiveFontSize = size === \"large\" ? \"text-body-16-regular\" : \"text-caption-12-medium\";\n\n return (\n <div className={cn(\"flex flex-col gap-2\", className)}>\n {subtitle && (\n <span className={cn(subtitleFontSize, \"text-text-base-neutral-5\")}>\n {subtitle}\n {isRequired && <span className=\"text-text-prominent-accent-1\">*</span>}\n </span>\n )}\n\n <div className=\"flex items-center gap-2\">\n <div\n onClick={disabled ? undefined : handleContainerClick}\n className={cn(\n \"group flex-1 overflow-hidden\",\n textFieldNormalContainerVariants({ size, disabled, hasError }),\n !disabled && !hasError && \"focus-within:border-border-base-neutral-4\",\n multiLine && \"h-[120px] items-start\",\n )}\n >\n {multiLine ? (\n <textarea\n {...inputPropsForTextarea}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLTextAreaElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"resize-none overflow-y-auto\",\n )}\n />\n ) : (\n <input\n {...inputPropsForInput}\n onChange={onChange}\n ref={inputRef as React.Ref<HTMLInputElement>}\n value={value}\n maxLength={maxLength}\n disabled={disabled}\n className={cn(\n \"text-text-base-neutral-5 placeholder:text-text-base-neutral-2 min-h-[24px] min-w-0 flex-1 border-none bg-transparent py-0 outline-none\",\n inputFontSize,\n \"overflow-hidden text-ellipsis whitespace-nowrap\",\n )}\n />\n )}\n\n {fieldRightElement && <div className=\"shrink-0\">{fieldRightElement}</div>}\n\n <button\n type=\"button\"\n onClick={() =>\n onChange &&\n onChange({ target: { value: \"\" } } as React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>)\n }\n tabIndex={-1}\n disabled={disabled}\n className={cn(\"hidden shrink-0\", {\n flex: hasError,\n \"group-focus-within:flex\": !disabled && currentLength > 0,\n })}\n >\n <CancelFilledIcon className=\"text-icon-base-neutral-3 h-6 w-6 shrink-0 cursor-pointer\" />\n </button>\n </div>\n\n <div className=\"shrink-0\">\n <CTAButton\n label={buttonText}\n onClick={onButtonClick}\n size=\"medium\"\n hierarchy=\"tertiary\"\n disabled={buttonDisabled || disabled}\n />\n </div>\n </div>\n\n {(assistiveText || errorText || (maxLength && showCounter)) && (\n <div className=\"flex items-center justify-between gap-2\">\n {(assistiveText || errorText) && (\n <span className={cn(assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {errorText || assistiveText}\n </span>\n )}\n {maxLength && showCounter && (\n <span className={cn(\"ml-auto\", assistiveFontSize, textFieldAssistiveAreaVariants({ size, hasError }))}>\n {currentLength}/{maxLength}\n </span>\n )}\n </div>\n )}\n </div>\n );\n },\n);\nTextFieldWithButton.displayName = \"TextFieldWithButton\";\n\nexport { TextFieldNormal, TextFieldWithButton };\n"],"mappings":"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"}
|
package/dist/v1/text-field.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { TextFieldNormal,
|
|
1
|
+
export { TextFieldNormal, TextFieldWithButton } from "../text-field.js";
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# 5.x → 6.0 마이그레이션 가이드
|
|
2
|
+
|
|
3
|
+
6.0은 `Select`를 petify-admin-console과 같은 드롭다운(Radix Select)으로 바꾸고, 목록 없이 버튼만 있던
|
|
4
|
+
`TextFieldSelect`를 지운 릴리스다. 바뀐 항목 전체는 [CHANGELOG](../../CHANGELOG.md)를 본다.
|
|
5
|
+
|
|
6
|
+
## 1. `TextFieldSelect` → `Select`
|
|
7
|
+
|
|
8
|
+
`TextFieldSelect`는 값과 셰브런을 보이는 버튼이었고, 목록은 소비 레포가 `onPress`로 직접 띄웠다. 6.0에서는
|
|
9
|
+
`Select`가 목록까지 그린다.
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
// 5.x
|
|
13
|
+
<TextFieldSelect
|
|
14
|
+
label="품종"
|
|
15
|
+
placeholder="품종을 선택해 주세요"
|
|
16
|
+
value={breed}
|
|
17
|
+
isRequired
|
|
18
|
+
onPress={() => openBreedSheet()}
|
|
19
|
+
/>
|
|
20
|
+
|
|
21
|
+
// 6.0
|
|
22
|
+
<Select
|
|
23
|
+
label="품종"
|
|
24
|
+
placeholder="품종을 선택해 주세요"
|
|
25
|
+
options={BREEDS}
|
|
26
|
+
value={breed}
|
|
27
|
+
onChange={setBreed}
|
|
28
|
+
required
|
|
29
|
+
/>
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
| 5.x `TextFieldSelect` | 6.0 `Select` |
|
|
33
|
+
| ------------------------------------------------------------------------------------- | -------------------------------------------------------- |
|
|
34
|
+
| `isRequired` | `required` |
|
|
35
|
+
| `onPress` + 직접 띄운 목록 | `options` + `onChange(value)` |
|
|
36
|
+
| `value`(보이는 글자) | `value`(고른 옵션의 값), 표시 이름은 `options`의 `label` |
|
|
37
|
+
| `errorText`, `assistiveText`, `size`, `disabled`, `className`, `placeholder`, `label` | 같음 |
|
|
38
|
+
|
|
39
|
+
옵션이 많아 검색이 필요하면 `Combobox`를 쓴다. 바텀시트 같은 자체 선택 화면을 계속 써야 하면 그 레포에
|
|
40
|
+
버튼을 두고 `@petnow/ui`의 `TextFieldSelect`에 기대지 않는다.
|
|
41
|
+
|
|
42
|
+
## 2. `Select`의 ref와 속성
|
|
43
|
+
|
|
44
|
+
- `ref`는 `<select>`가 아니라 트리거 `<button>`(`HTMLButtonElement`)을 가리킨다. `ref.current.value`로 값을
|
|
45
|
+
읽던 코드는 `value`/`onChange`를 쓴다.
|
|
46
|
+
- 나머지 속성은 `<button>` 속성으로 넘어간다. `name`, `form`, `required`는 그대로 동작한다. 폼 안에서는 Radix가
|
|
47
|
+
숨은 `<select>`를 그려 `FormData`와 브라우저 검증에 값이 들어간다.
|
|
48
|
+
- 옵션 값으로 `""`를 쓸 수 없다. `""`는 고르지 않은 상태이고 `placeholder`를 보이며, 값이 `""`인 옵션은
|
|
49
|
+
그리지 않는다.
|
|
50
|
+
- 한 번 고른 뒤 사용자가 "고르지 않음"으로 되돌릴 수 없다. 네이티브 `<select>`는 placeholder 옵션을 다시 고를
|
|
51
|
+
수 있었다. 되돌려야 하는 폼은 코드에서 `value`를 `""`로 바꾼다.
|
|
52
|
+
- 폼 `reset`이면 화면 값과 숨은 `<select>`가 `defaultValue`(없으면 고르지 않음)로 돌아간다. 제어 컴포넌트는
|
|
53
|
+
`onChange`로 그 값을 받는다.
|
|
54
|
+
- 모바일 브라우저에서도 시스템 피커 대신 같은 패널이 열린다.
|
|
55
|
+
|
|
56
|
+
## 3. 확인
|
|
57
|
+
|
|
58
|
+
- 목록이 트리거 아래(공간이 없으면 위)에 열리고, 고른 옵션 앞에 체크가 보이는지.
|
|
59
|
+
- 폼을 제출하는 화면이면 `FormData`나 서버로 넘어가는 값이 그대로인지.
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fieldStyles-DyZu__hI.js","names":[],"sources":["../src/components/ui/fieldStyles.ts"],"sourcesContent":["import { cva } from \"class-variance-authority\";\n\n// TextField, Select, Combobox가 함께 쓰는 입력 칸 스타일\n// 입력 칸과 목록 팝업이 같은 모서리를 쓴다. 소비 레포의 --radius-* 설정과 무관하게 4px로 고정한다.\nexport const FIELD_RADIUS = \"rounded-[4px]\";\n\nexport const fieldContainerVariants = cva(\n `flex items-center ${FIELD_RADIUS} bg-surface-base-neutral-2 border transition-colors duration-200`,\n {\n variants: {\n size: {\n large: \"gap-2 p-[15px] min-h-[56px]\",\n small: \"gap-3 p-[11px] min-h-[48px]\",\n },\n hasError: {\n true: \"border-border-prominent-error\",\n false: \"border-transparent\",\n },\n disabled: {\n true: \"opacity-50\",\n false: \"\",\n },\n },\n defaultVariants: {\n size: \"large\",\n disabled: false,\n hasError: false,\n },\n },\n);\n\nexport const fieldMessageVariants = cva(\"\", {\n variants: {\n size: {\n large: \"text-body-16-regular\",\n small: \"text-caption-12-medium\",\n },\n hasError: {\n true: \"text-text-prominent-error\",\n false: \"text-text-base-neutral-2\",\n },\n },\n defaultVariants: {\n size: \"large\",\n hasError: false,\n },\n});\n\nexport type FieldSize = \"large\" | \"small\";\n\nexport const fieldLabelFontSize = (size: FieldSize) => (size === \"large\" ? \"text-title-18-bold\" : \"text-title-14-bold\");\nexport const fieldValueFontSize = (size: FieldSize) =>\n size === \"large\" ? \"text-title-20-regular\" : \"text-body-16-regular\";\n\n// 소비 레포가 넘긴 aria-describedby와 필드 메시지 id를 합친다.\nexport const joinIds = (...ids: (string | false | undefined)[]) => ids.filter(Boolean).join(\" \") || undefined;\n"],"mappings":";;AAIA,IAAa,IAAe,iBAEf,IAAyB,EACpC,qBAAqB,EAAa,mEAClC;CACE,UAAU;EACR,MAAM;GACJ,OAAO;GACP,OAAO;EACT;EACA,UAAU;GACR,MAAM;GACN,OAAO;EACT;EACA,UAAU;GACR,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB;EACf,MAAM;EACN,UAAU;EACV,UAAU;CACZ;AACF,CACF,GAEa,IAAuB,EAAI,IAAI;CAC1C,UAAU;EACR,MAAM;GACJ,OAAO;GACP,OAAO;EACT;EACA,UAAU;GACR,MAAM;GACN,OAAO;EACT;CACF;CACA,iBAAiB;EACf,MAAM;EACN,UAAU;CACZ;AACF,CAAC,GAIY,KAAsB,MAAqB,MAAS,UAAU,uBAAuB,sBACrF,KAAsB,MACjC,MAAS,UAAU,0BAA0B,wBAGlC,KAAW,GAAG,MAAwC,EAAI,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,KAAK,KAAA"}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { t as e } from "./TailwindUtil-DiNvXuNl.js";
|
|
2
|
-
import { i as t, r as n } from "./fieldStyles-DyZu__hI.js";
|
|
3
|
-
import { jsx as r, jsxs as i } from "react/jsx-runtime";
|
|
4
|
-
//#region src/components/ui/field.tsx
|
|
5
|
-
var a = ({ id: t, htmlFor: a, size: o, required: s, children: c }) => /* @__PURE__ */ i("label", {
|
|
6
|
-
id: t,
|
|
7
|
-
htmlFor: a,
|
|
8
|
-
className: e(n(o), "text-text-base-neutral-5"),
|
|
9
|
-
children: [c, s && /* @__PURE__ */ r("span", {
|
|
10
|
-
className: "text-text-prominent-accent-1",
|
|
11
|
-
"aria-hidden": "true",
|
|
12
|
-
children: "*"
|
|
13
|
-
})]
|
|
14
|
-
}), o = ({ id: e, size: n, errorText: i, assistiveText: a }) => !i && !a ? null : /* @__PURE__ */ r("span", {
|
|
15
|
-
id: e,
|
|
16
|
-
className: t({
|
|
17
|
-
size: n,
|
|
18
|
-
hasError: !!i
|
|
19
|
-
}),
|
|
20
|
-
children: i || a
|
|
21
|
-
}), s = (...e) => (t) => {
|
|
22
|
-
for (let n of e) typeof n == "function" ? n(t) : n && (n.current = t);
|
|
23
|
-
};
|
|
24
|
-
//#endregion
|
|
25
|
-
export { a as n, o as r, s as t };
|
|
26
|
-
|
|
27
|
-
//# sourceMappingURL=mergeRefs-BHwdBwNQ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mergeRefs-BHwdBwNQ.js","names":[],"sources":["../src/components/ui/field.tsx","../src/utils/mergeRefs.ts"],"sourcesContent":["import { fieldLabelFontSize, fieldMessageVariants, type FieldSize } from \"./fieldStyles\";\n\nimport type { ReactNode } from \"react\";\n\nimport { cn } from \"@/utils/TailwindUtil\";\n\nexport const FieldLabel = ({\n id,\n htmlFor,\n size,\n required,\n children,\n}: {\n id?: string;\n htmlFor: string;\n size: FieldSize;\n required?: boolean;\n children: ReactNode;\n}) => (\n <label id={id} htmlFor={htmlFor} className={cn(fieldLabelFontSize(size), \"text-text-base-neutral-5\")}>\n {children}\n {required && (\n <span className=\"text-text-prominent-accent-1\" aria-hidden=\"true\">\n *\n </span>\n )}\n </label>\n);\n\nexport const FieldMessage = ({\n id,\n size,\n errorText,\n assistiveText,\n}: {\n id: string;\n size: FieldSize;\n errorText?: string;\n assistiveText?: ReactNode;\n}) => {\n if (!errorText && !assistiveText) return null;\n return (\n <span id={id} className={fieldMessageVariants({ size, hasError: Boolean(errorText) })}>\n {errorText || assistiveText}\n </span>\n );\n};\n","import type { Ref, RefCallback } from \"react\";\n\n// 내부 ref와 소비 레포가 넘긴 ref(React 19 ref prop)를 함께 연결한다.\nexport const mergeRefs =\n <T>(...refs: (Ref<T> | undefined)[]): RefCallback<T> =>\n (node) => {\n for (const ref of refs) {\n if (typeof ref === \"function\") ref(node);\n else if (ref) ref.current = node;\n }\n };\n"],"mappings":";;;;AAMA,IAAa,KAAc,EACzB,OACA,YACA,SACA,aACA,kBAQA,kBAAC,SAAD;CAAW;CAAa;CAAS,WAAW,EAAG,EAAmB,CAAI,GAAG,0BAA0B;WAAnG,CACG,GACA,KACC,kBAAC,QAAD;EAAM,WAAU;EAA+B,eAAY;YAAO;CAE5D,CAAA,CAEH;IAGI,KAAgB,EAC3B,OACA,SACA,cACA,uBAOI,CAAC,KAAa,CAAC,IAAsB,OAEvC,kBAAC,QAAD;CAAU;CAAI,WAAW,EAAqB;EAAE;EAAM,UAAU,EAAQ;CAAW,CAAC;WACjF,KAAa;AACV,CAAA,GCzCG,KACP,GAAG,OACN,MAAS;CACR,KAAK,IAAM,KAAO,GAChB,AAAI,OAAO,KAAQ,aAAY,EAAI,CAAI,IAC9B,MAAK,EAAI,UAAU;AAEhC"}
|