@uniai-fe/uds-primitives 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/styles.css +99 -7
- package/package.json +5 -3
- package/src/components/button/index.tsx +0 -2
- package/src/components/button/markup/Base.tsx +22 -1
- package/src/components/button/styles/button.scss +24 -2
- package/src/components/button/styles/variables.scss +4 -0
- package/src/components/button/types/index.ts +7 -0
- package/src/components/checkbox/markup/Checkbox.tsx +31 -25
- package/src/components/dropdown/markup/index.tsx +10 -1
- package/src/components/input/hooks/index.ts +1 -0
- package/src/components/input/hooks/useAddress.ts +247 -0
- package/src/components/input/index.scss +5 -1
- package/src/components/input/markup/address/Button.tsx +65 -0
- package/src/components/input/markup/address/Template.tsx +135 -0
- package/src/components/input/markup/address/index.ts +9 -0
- package/src/components/input/markup/foundation/Input.tsx +20 -1
- package/src/components/input/markup/index.tsx +2 -0
- package/src/components/input/styles/address.scss +24 -0
- package/src/components/input/styles/foundation.scss +28 -2
- package/src/components/input/styles/variables.scss +4 -0
- package/src/components/input/types/address.ts +249 -0
- package/src/components/input/types/foundation.ts +6 -0
- package/src/components/input/types/index.ts +1 -0
- package/src/components/input/utils/address.ts +165 -0
- package/src/components/input/utils/index.tsx +1 -0
- package/src/components/radio/markup/Radio.tsx +10 -2
- package/src/components/radio/markup/RadioCard.tsx +6 -1
- package/src/components/radio/markup/RadioCardGroup.tsx +6 -1
- package/src/components/select/markup/Default.tsx +2 -0
- package/src/components/select/markup/foundation/Container.tsx +23 -0
- package/src/components/select/markup/multiple/Multiple.tsx +2 -0
- package/src/components/select/styles/select.scss +25 -2
- package/src/components/select/styles/variables.scss +4 -0
- package/src/components/select/types/props.ts +24 -5
- package/src/components/input/styles/index.scss +0 -4
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
|
|
5
|
+
import { Button } from "../../../button";
|
|
6
|
+
import type { AddressFindButtonProps } from "../../types/address";
|
|
7
|
+
import { useAddress } from "../../hooks/useAddress";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 주소 찾기 버튼; react-daum-postcode 팝업을 열고 결과를 RHF와 콜백에 전달한다.
|
|
11
|
+
* @component
|
|
12
|
+
* @param {AddressFindButtonProps} props 버튼 props
|
|
13
|
+
* @param {React.ReactNode} [props.label] 버튼 라벨 텍스트
|
|
14
|
+
* @param {string} [props.className] 커스텀 className
|
|
15
|
+
* @param {"primary"|"secondary"|"tertiary"} [props.priority="secondary"] 버튼 priority
|
|
16
|
+
* @param {"solid"|"outlined"} [props.fill="solid"] 버튼 fill 타입
|
|
17
|
+
* @param {"xlarge"|"large"|"medium"|"small"} [props.size="xlarge"] 버튼 size
|
|
18
|
+
* @param {"button"|"submit"|"reset"} [props.type="button"] native type
|
|
19
|
+
* @param {boolean} [props.disabled] disabled 상태
|
|
20
|
+
* @param {string} [props.addressFieldName] react-hook-form 주소 필드 이름
|
|
21
|
+
* @param {string} [props.detailFieldName] react-hook-form 상세 주소 필드 이름
|
|
22
|
+
* @param {string} [props.zipCodeFieldName] react-hook-form 우편번호 필드 이름
|
|
23
|
+
* @param {boolean} [props.triggerValidation=true] setValue 이후 trigger 실행 여부
|
|
24
|
+
* @param {boolean} [props.resetDetailOnSelect=true] 새 주소 선택 시 상세 주소 초기화 여부
|
|
25
|
+
* @param {(payload:AddressSearchResult)=>void} [props.onSelect] 주소 선택 콜백
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* <Input.Address.Button
|
|
29
|
+
* label="검색"
|
|
30
|
+
* addressFieldName="farm.address"
|
|
31
|
+
* zipCodeFieldName="farm.zipCode"
|
|
32
|
+
* onSelect={(payload) => console.log(payload.address)}
|
|
33
|
+
* />
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export default function AddressFindButton({
|
|
37
|
+
label,
|
|
38
|
+
className,
|
|
39
|
+
priority = "secondary",
|
|
40
|
+
fill = "solid",
|
|
41
|
+
size = "xlarge",
|
|
42
|
+
type = "button",
|
|
43
|
+
disabled,
|
|
44
|
+
...selectionOptions
|
|
45
|
+
}: AddressFindButtonProps) {
|
|
46
|
+
// RHF + react-daum-postcode 연결을 위한 팝업 핸들러
|
|
47
|
+
const { openPopup } = useAddress(selectionOptions);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Button.Default
|
|
51
|
+
priority={priority}
|
|
52
|
+
fill={fill}
|
|
53
|
+
size={size}
|
|
54
|
+
type={type}
|
|
55
|
+
onClick={openPopup}
|
|
56
|
+
disabled={disabled}
|
|
57
|
+
className={clsx("input-address-button", className)}
|
|
58
|
+
>
|
|
59
|
+
{/* 비어 있는 라벨일 때 기본 문구를 강제로 노출 */}
|
|
60
|
+
{["string", "number"].includes(typeof label) && label !== ""
|
|
61
|
+
? String(label)
|
|
62
|
+
: (label ?? "검색")}
|
|
63
|
+
</Button.Default>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import clsx from "clsx";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
import { useFormContext, type FieldValues, type Path } from "react-hook-form";
|
|
6
|
+
|
|
7
|
+
import InputBase from "../foundation/Input";
|
|
8
|
+
import type { AddressTemplateProps } from "../../types/address";
|
|
9
|
+
import AddressFindButton from "./Button";
|
|
10
|
+
import { resolveAddressValue } from "../../utils/address";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 주소 입력 템플릿; 주소/상세 입력 필드와 검색 버튼을 조합한다.
|
|
14
|
+
* @component
|
|
15
|
+
* @param {AddressTemplateProps} props 템플릿 props
|
|
16
|
+
* @param {string} [props.className] container className
|
|
17
|
+
* @param {AddressSharedInputStyleProps} [props.inputStyle] 공유 input 스타일 옵션
|
|
18
|
+
* @param {InputProps} props.addressInput 주소 입력 필드 props
|
|
19
|
+
* @param {InputProps} [props.detailInput] 상세 주소 입력 필드 props
|
|
20
|
+
* @param {AddressTemplateButtonOptions} [props.buttonProps] 검색 버튼 옵션
|
|
21
|
+
* @param {boolean} [props.disabled] 템플릿 disabled 상태
|
|
22
|
+
* @param {string} [props.addressFieldName] RHF 주소 필드 네임
|
|
23
|
+
* @param {string} [props.zipCodeFieldName] RHF 우편번호 필드 네임
|
|
24
|
+
* @param {boolean} [props.triggerValidation=true] setValue 이후 trigger 실행 여부
|
|
25
|
+
* @param {(payload:AddressSearchResult)=>void} [props.onSelect] 주소 선택 콜백
|
|
26
|
+
* @example
|
|
27
|
+
* ```tsx
|
|
28
|
+
* <FormProvider {...methods}>
|
|
29
|
+
* <Input.Address.Template
|
|
30
|
+
* addressFieldName="farm.address"
|
|
31
|
+
* zipCodeFieldName="farm.zipCode"
|
|
32
|
+
* addressInput={{ placeholder: "주소 검색" }}
|
|
33
|
+
* detailInput={{ placeholder: "상세 주소 입력" }}
|
|
34
|
+
* buttonProps={{ label: "검색" }}
|
|
35
|
+
* />
|
|
36
|
+
* </FormProvider>
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export default function AddressFieldTemplate({
|
|
40
|
+
className,
|
|
41
|
+
addressInput,
|
|
42
|
+
detailInput,
|
|
43
|
+
inputStyle,
|
|
44
|
+
buttonProps,
|
|
45
|
+
disabled,
|
|
46
|
+
addressFieldName,
|
|
47
|
+
detailFieldName,
|
|
48
|
+
zipCodeFieldName,
|
|
49
|
+
triggerValidation,
|
|
50
|
+
resetDetailOnSelect = true,
|
|
51
|
+
onSelect,
|
|
52
|
+
}: AddressTemplateProps) {
|
|
53
|
+
const formContext = useFormContext<FieldValues>();
|
|
54
|
+
const inputSize = inputStyle?.size ?? "medium";
|
|
55
|
+
|
|
56
|
+
const resolvedAddressFieldName = addressFieldName
|
|
57
|
+
? (addressFieldName as Path<FieldValues>)
|
|
58
|
+
: undefined;
|
|
59
|
+
const resolvedZipFieldName = zipCodeFieldName
|
|
60
|
+
? (zipCodeFieldName as Path<FieldValues>)
|
|
61
|
+
: undefined;
|
|
62
|
+
const resolvedDetailFieldName = detailFieldName
|
|
63
|
+
? (detailFieldName as Path<FieldValues>)
|
|
64
|
+
: detailInput?.name
|
|
65
|
+
? (detailInput.name as Path<FieldValues>)
|
|
66
|
+
: undefined;
|
|
67
|
+
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
if (resolvedAddressFieldName)
|
|
70
|
+
formContext.register(resolvedAddressFieldName);
|
|
71
|
+
if (resolvedZipFieldName) formContext.register(resolvedZipFieldName);
|
|
72
|
+
}, [formContext, resolvedAddressFieldName, resolvedZipFieldName]);
|
|
73
|
+
|
|
74
|
+
const watchedAddress = resolvedAddressFieldName
|
|
75
|
+
? formContext.watch(resolvedAddressFieldName)
|
|
76
|
+
: undefined;
|
|
77
|
+
// addressInput.value가 지정되면 RHF watch보다 우선 적용해 강제 값 주입을 허용한다.
|
|
78
|
+
const addressValueSource =
|
|
79
|
+
addressInput?.value !== undefined ? addressInput.value : watchedAddress;
|
|
80
|
+
const resolvedAddress = resolveAddressValue(addressValueSource);
|
|
81
|
+
// detailFieldName 지정 시 RHF register를 자동으로 연결한다.
|
|
82
|
+
const detailRegister = resolvedDetailFieldName
|
|
83
|
+
? formContext.register(resolvedDetailFieldName)
|
|
84
|
+
: detailInput?.register;
|
|
85
|
+
const detailName =
|
|
86
|
+
detailInput?.name ?? detailFieldName ?? resolvedDetailFieldName;
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<div className={clsx("input-address-container", className)}>
|
|
90
|
+
<div className="input-address-row input-address-upper">
|
|
91
|
+
<InputBase
|
|
92
|
+
{...inputStyle}
|
|
93
|
+
{...addressInput}
|
|
94
|
+
size={inputSize}
|
|
95
|
+
value={resolvedAddress.text}
|
|
96
|
+
width="fill"
|
|
97
|
+
readOnly
|
|
98
|
+
disabled
|
|
99
|
+
className="input-address-field input-address-field-base"
|
|
100
|
+
/>
|
|
101
|
+
<AddressFindButton
|
|
102
|
+
{...buttonProps}
|
|
103
|
+
addressFieldName={addressFieldName}
|
|
104
|
+
detailFieldName={detailFieldName ?? detailInput?.name}
|
|
105
|
+
zipCodeFieldName={zipCodeFieldName}
|
|
106
|
+
triggerValidation={triggerValidation}
|
|
107
|
+
resetDetailOnSelect={resetDetailOnSelect}
|
|
108
|
+
onSelect={onSelect}
|
|
109
|
+
className="input-address-button"
|
|
110
|
+
size={
|
|
111
|
+
buttonProps?.size ??
|
|
112
|
+
(inputSize === "large"
|
|
113
|
+
? "xlarge"
|
|
114
|
+
: inputSize === "medium"
|
|
115
|
+
? "large"
|
|
116
|
+
: "medium")
|
|
117
|
+
}
|
|
118
|
+
disabled={disabled ?? buttonProps?.disabled}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
{detailInput && (
|
|
122
|
+
<div className="input-address-row input-address-lower">
|
|
123
|
+
<InputBase
|
|
124
|
+
{...inputStyle}
|
|
125
|
+
{...detailInput}
|
|
126
|
+
register={detailRegister}
|
|
127
|
+
name={detailName}
|
|
128
|
+
width="full"
|
|
129
|
+
className="input-address-field input-address-field-detail"
|
|
130
|
+
/>
|
|
131
|
+
</div>
|
|
132
|
+
)}
|
|
133
|
+
</div>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import clsx from "clsx";
|
|
4
|
-
import type { PointerEvent as ReactPointerEvent } from "react";
|
|
4
|
+
import type { CSSProperties, PointerEvent as ReactPointerEvent } from "react";
|
|
5
5
|
import {
|
|
6
6
|
ChangeEvent,
|
|
7
7
|
FocusEvent,
|
|
@@ -14,6 +14,10 @@ import {
|
|
|
14
14
|
useState,
|
|
15
15
|
} from "react";
|
|
16
16
|
import type { InputProps } from "../../types";
|
|
17
|
+
import {
|
|
18
|
+
getFormFieldWidthAttr,
|
|
19
|
+
getFormFieldWidthValue,
|
|
20
|
+
} from "../../../form/utils/form-field";
|
|
17
21
|
|
|
18
22
|
import InputBaseSideSlot from "./SideSlot";
|
|
19
23
|
import InputBaseUtil from "./Utility";
|
|
@@ -56,6 +60,7 @@ const InputBase = forwardRef<HTMLInputElement, InputProps>(
|
|
|
56
60
|
size = "medium",
|
|
57
61
|
state: stateProp = "default",
|
|
58
62
|
block = false,
|
|
63
|
+
width,
|
|
59
64
|
left,
|
|
60
65
|
right,
|
|
61
66
|
clear,
|
|
@@ -166,6 +171,18 @@ const InputBase = forwardRef<HTMLInputElement, InputProps>(
|
|
|
166
171
|
};
|
|
167
172
|
|
|
168
173
|
const inputName = registerName ?? name;
|
|
174
|
+
const widthAttr =
|
|
175
|
+
width !== undefined
|
|
176
|
+
? getFormFieldWidthAttr(width)
|
|
177
|
+
: block
|
|
178
|
+
? "full"
|
|
179
|
+
: undefined;
|
|
180
|
+
const widthValue =
|
|
181
|
+
width !== undefined ? getFormFieldWidthValue(width) : undefined;
|
|
182
|
+
const containerStyle: CSSProperties | undefined =
|
|
183
|
+
widthValue !== undefined
|
|
184
|
+
? ({ ["--input-width" as const]: widthValue } as CSSProperties)
|
|
185
|
+
: undefined;
|
|
169
186
|
|
|
170
187
|
return (
|
|
171
188
|
<div
|
|
@@ -182,6 +199,8 @@ const InputBase = forwardRef<HTMLInputElement, InputProps>(
|
|
|
182
199
|
data-state={visualState}
|
|
183
200
|
data-block={block ? "true" : undefined}
|
|
184
201
|
{...(simulatedState ? { "data-simulated-state": simulatedState } : {})}
|
|
202
|
+
data-width={widthAttr}
|
|
203
|
+
style={containerStyle}
|
|
185
204
|
>
|
|
186
205
|
<div
|
|
187
206
|
className={clsx(
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
import { InputFoundation } from "./foundation";
|
|
4
4
|
import { InputText } from "./text";
|
|
5
5
|
import { InputCalendar } from "./calendar";
|
|
6
|
+
import { InputAddress } from "./address";
|
|
6
7
|
|
|
7
8
|
export const Input = {
|
|
8
9
|
...InputFoundation,
|
|
9
10
|
Text: InputText,
|
|
10
11
|
Calendar: InputCalendar,
|
|
12
|
+
Address: InputAddress,
|
|
11
13
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
.input-address-container {
|
|
2
|
+
width: 100%;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.input-address-row {
|
|
6
|
+
width: 100%;
|
|
7
|
+
display: flex;
|
|
8
|
+
gap: var(--spacing-gap-5);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.input-address-lower {
|
|
12
|
+
margin-top: var(--spacing-gap-5);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// .input-address-button {
|
|
16
|
+
// }
|
|
17
|
+
|
|
18
|
+
.input-address-upper {
|
|
19
|
+
align-items: center;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.input-address-field {
|
|
23
|
+
width: 100%;
|
|
24
|
+
}
|
|
@@ -2,9 +2,35 @@
|
|
|
2
2
|
display: flex;
|
|
3
3
|
flex-direction: column;
|
|
4
4
|
gap: var(--spacing-gap-3);
|
|
5
|
-
width:
|
|
5
|
+
width: var(--input-width);
|
|
6
|
+
flex: var(--input-flex);
|
|
7
|
+
min-width: 0;
|
|
8
|
+
|
|
9
|
+
&[data-width="auto"] {
|
|
10
|
+
--input-width: auto;
|
|
11
|
+
--input-flex: 0 1 auto;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
&[data-width="fill"] {
|
|
15
|
+
--input-width: auto;
|
|
16
|
+
--input-flex: 1 1 0%;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&[data-width="full"],
|
|
20
|
+
&[data-block="true"] {
|
|
21
|
+
--input-width: 100%;
|
|
22
|
+
--input-flex: 0 0 100%;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
&[data-width="fit"] {
|
|
26
|
+
--input-width: fit-content;
|
|
27
|
+
--input-flex: 0 0 auto;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&[data-width="custom"] {
|
|
31
|
+
--input-flex: 0 0 auto;
|
|
32
|
+
}
|
|
6
33
|
|
|
7
|
-
&[data-block="true"],
|
|
8
34
|
&--block {
|
|
9
35
|
width: 100%;
|
|
10
36
|
}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { Address } from "react-daum-postcode";
|
|
3
|
+
import type {
|
|
4
|
+
ButtonFill,
|
|
5
|
+
ButtonPriority,
|
|
6
|
+
ButtonSize,
|
|
7
|
+
} from "../../button/types";
|
|
8
|
+
import type { InputProps } from "./foundation";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 주소 문자열/배열 정규화 결과.
|
|
12
|
+
* @property {string} text 최종 병합된 주소 문자열
|
|
13
|
+
* @property {string[]} parts 주소를 구성하는 파트 배열
|
|
14
|
+
*/
|
|
15
|
+
export interface AddressResolvedValue {
|
|
16
|
+
/**
|
|
17
|
+
* 최종 병합된 주소 문자열
|
|
18
|
+
*/
|
|
19
|
+
text: string;
|
|
20
|
+
/**
|
|
21
|
+
* 주소 파트 배열
|
|
22
|
+
*/
|
|
23
|
+
parts: string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 주소 검색 완료 데이터.
|
|
28
|
+
* @property {string} address 전체 주소 문자열
|
|
29
|
+
* @property {string[]} [addressParts] 주소를 구성하는 문자열 배열
|
|
30
|
+
* @property {AddressStructure} [addressStructure] 주소 구성 정보(기본/추가 파트)
|
|
31
|
+
* @property {string} zipCode 우편번호(5자리)
|
|
32
|
+
* @property {string} [buildingName] 건물명
|
|
33
|
+
* @property {string} [district] 법정동/읍면 정보
|
|
34
|
+
* @property {Address} raw react-daum-postcode Address 원본 데이터
|
|
35
|
+
*/
|
|
36
|
+
export interface AddressSearchResult {
|
|
37
|
+
/**
|
|
38
|
+
* 전체 주소 문자열
|
|
39
|
+
*/
|
|
40
|
+
address: string;
|
|
41
|
+
/**
|
|
42
|
+
* 주소를 구성하는 문자열 배열
|
|
43
|
+
*/
|
|
44
|
+
addressParts?: string[];
|
|
45
|
+
/**
|
|
46
|
+
* 주소 구성 정보(기본 주소 + 추가 파트)
|
|
47
|
+
*/
|
|
48
|
+
addressStructure?: AddressStructure;
|
|
49
|
+
/**
|
|
50
|
+
* 우편번호(5자리)
|
|
51
|
+
*/
|
|
52
|
+
zipCode: string;
|
|
53
|
+
/**
|
|
54
|
+
* 건물명
|
|
55
|
+
*/
|
|
56
|
+
buildingName?: string;
|
|
57
|
+
/**
|
|
58
|
+
* 법정동/읍면 정보
|
|
59
|
+
*/
|
|
60
|
+
district?: string;
|
|
61
|
+
/**
|
|
62
|
+
* react-daum-postcode Address 원본 데이터
|
|
63
|
+
*/
|
|
64
|
+
raw: Address;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* 주소 구성 정보.
|
|
69
|
+
* @property {string} main 기본 주소
|
|
70
|
+
* @property {string[]} extras 추가 주소 파트 배열
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const structure: AddressStructure = {
|
|
74
|
+
* main: "서울시 강남구 ...",
|
|
75
|
+
* extras: ["도곡동", "OO아파트"],
|
|
76
|
+
* };
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
export interface AddressStructure {
|
|
80
|
+
/**
|
|
81
|
+
* 기본 주소
|
|
82
|
+
*/
|
|
83
|
+
main: string;
|
|
84
|
+
/**
|
|
85
|
+
* 추가 주소 파트 배열
|
|
86
|
+
*/
|
|
87
|
+
extras: string[];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 주소 선택 처리 공통 옵션.
|
|
92
|
+
* @property {string} [addressFieldName] react-hook-form에 적용할 주소 필드 이름
|
|
93
|
+
* @property {string} [detailFieldName] react-hook-form에 적용할 상세 주소 필드 이름
|
|
94
|
+
* @property {string} [zipCodeFieldName] react-hook-form에 적용할 우편번호 필드 이름
|
|
95
|
+
* @property {boolean} [triggerValidation=true] setValue 이후 trigger 실행 여부
|
|
96
|
+
* @property {boolean} [resetDetailOnSelect=true] 새 주소 선택 시 상세 주소를 초기화할지 여부
|
|
97
|
+
* @property {(payload:AddressSearchResult)=>void} [onSelect] 주소 선택 후 콜백
|
|
98
|
+
*/
|
|
99
|
+
export interface AddressSelectionOptions {
|
|
100
|
+
/**
|
|
101
|
+
* react-hook-form 주소 필드 이름
|
|
102
|
+
*/
|
|
103
|
+
addressFieldName?: string;
|
|
104
|
+
/**
|
|
105
|
+
* react-hook-form 상세 주소 필드 이름
|
|
106
|
+
*/
|
|
107
|
+
detailFieldName?: string;
|
|
108
|
+
/**
|
|
109
|
+
* react-hook-form 우편번호 필드 이름
|
|
110
|
+
*/
|
|
111
|
+
zipCodeFieldName?: string;
|
|
112
|
+
/**
|
|
113
|
+
* setValue 이후 trigger 실행 여부
|
|
114
|
+
*/
|
|
115
|
+
triggerValidation?: boolean;
|
|
116
|
+
/**
|
|
117
|
+
* 새 주소 선택 시 상세 주소 초기화 여부
|
|
118
|
+
*/
|
|
119
|
+
resetDetailOnSelect?: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* 주소 선택 후 콜백
|
|
122
|
+
*/
|
|
123
|
+
onSelect?: (payload: AddressSearchResult) => void;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 제한된 입력 스타일 props; priority/size/state/block만 공유한다.
|
|
128
|
+
*/
|
|
129
|
+
export type AddressSharedInputStyleProps = Pick<
|
|
130
|
+
InputProps,
|
|
131
|
+
"priority" | "size" | "state"
|
|
132
|
+
>;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 주소 검색 버튼 props.
|
|
136
|
+
* @property {ReactNode} [children] 버튼 라벨
|
|
137
|
+
* @property {ButtonPriority} [priority] 버튼 priority
|
|
138
|
+
* @property {ButtonFill} [fill] 버튼 fill 타입
|
|
139
|
+
* @property {ButtonSize} [size] 버튼 size
|
|
140
|
+
* @property {string} [className] 추가 className
|
|
141
|
+
* @property {"button"|"submit"|"reset"} [type] button type
|
|
142
|
+
* @property {boolean} [disabled] disabled 여부
|
|
143
|
+
* @property {string} [addressFieldName] react-hook-form에 적용할 주소 필드 이름
|
|
144
|
+
* @property {string} [zipCodeFieldName] react-hook-form에 적용할 우편번호 필드 이름
|
|
145
|
+
* @property {boolean} [triggerValidation=true] setValue 이후 trigger 실행 여부
|
|
146
|
+
* @property {(payload:AddressSearchResult)=>void} [onSelect] 주소 선택 후 콜백
|
|
147
|
+
*/
|
|
148
|
+
export interface AddressFindButtonProps extends AddressSelectionOptions {
|
|
149
|
+
/**
|
|
150
|
+
* 버튼 라벨
|
|
151
|
+
*/
|
|
152
|
+
label?: ReactNode;
|
|
153
|
+
/**
|
|
154
|
+
* 버튼 priority
|
|
155
|
+
*/
|
|
156
|
+
priority?: ButtonPriority;
|
|
157
|
+
/**
|
|
158
|
+
* 버튼 fill 타입
|
|
159
|
+
*/
|
|
160
|
+
fill?: ButtonFill;
|
|
161
|
+
/**
|
|
162
|
+
* 버튼 size
|
|
163
|
+
*/
|
|
164
|
+
size?: ButtonSize;
|
|
165
|
+
/**
|
|
166
|
+
* 추가 className
|
|
167
|
+
*/
|
|
168
|
+
className?: string;
|
|
169
|
+
/**
|
|
170
|
+
* button type
|
|
171
|
+
*/
|
|
172
|
+
type?: "button" | "submit" | "reset";
|
|
173
|
+
/**
|
|
174
|
+
* disabled 여부
|
|
175
|
+
*/
|
|
176
|
+
disabled?: boolean;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 주소 템플릿 버튼 옵션.
|
|
181
|
+
* @property {ReactNode} [label] 버튼 라벨
|
|
182
|
+
* @property {ButtonPriority} [priority] 버튼 priority
|
|
183
|
+
* @property {ButtonFill} [fill] 버튼 fill 타입
|
|
184
|
+
* @property {ButtonSize} [size] 버튼 size
|
|
185
|
+
* @property {boolean} [disabled] 버튼 disabled 여부
|
|
186
|
+
*/
|
|
187
|
+
export interface AddressTemplateButtonOptions {
|
|
188
|
+
/**
|
|
189
|
+
* 버튼 라벨
|
|
190
|
+
*/
|
|
191
|
+
label?: ReactNode;
|
|
192
|
+
/**
|
|
193
|
+
* 버튼 priority
|
|
194
|
+
*/
|
|
195
|
+
priority?: ButtonPriority;
|
|
196
|
+
/**
|
|
197
|
+
* 버튼 fill 타입
|
|
198
|
+
*/
|
|
199
|
+
fill?: ButtonFill;
|
|
200
|
+
/**
|
|
201
|
+
* 버튼 size
|
|
202
|
+
*/
|
|
203
|
+
size?: ButtonSize;
|
|
204
|
+
/**
|
|
205
|
+
* 버튼 disabled 여부
|
|
206
|
+
*/
|
|
207
|
+
disabled?: boolean;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* 주소 필드 템플릿 props.
|
|
212
|
+
* @property {string} [className] container className
|
|
213
|
+
* @property {AddressSharedInputStyleProps} [inputStyle] 공통 입력 스타일 props
|
|
214
|
+
* @property {InputProps} addressInput 주소 입력 Input props
|
|
215
|
+
* @property {InputProps} [detailInput] 상세 주소 입력 props
|
|
216
|
+
* @property {string} [detailFieldName] react-hook-form에 적용할 상세 주소 필드 이름
|
|
217
|
+
* @property {AddressTemplateButtonOptions} [buttonProps] 버튼 옵션
|
|
218
|
+
* @property {boolean} [disabled] 템플릿 disabled 여부
|
|
219
|
+
* @property {string} [addressFieldName] react-hook-form에 적용할 주소 필드 이름
|
|
220
|
+
* @property {string} [zipCodeFieldName] react-hook-form에 적용할 우편번호 필드 이름
|
|
221
|
+
* @property {boolean} [triggerValidation=true] setValue 이후 trigger 실행 여부
|
|
222
|
+
* @property {(payload:AddressSearchResult)=>void} [onSelect] 주소 선택 후 콜백
|
|
223
|
+
*/
|
|
224
|
+
export interface AddressTemplateProps extends AddressSelectionOptions {
|
|
225
|
+
/**
|
|
226
|
+
* container className
|
|
227
|
+
*/
|
|
228
|
+
className?: string;
|
|
229
|
+
/**
|
|
230
|
+
* 공통 입력 스타일 props
|
|
231
|
+
*/
|
|
232
|
+
inputStyle?: AddressSharedInputStyleProps;
|
|
233
|
+
/**
|
|
234
|
+
* 주소 입력 Input props
|
|
235
|
+
*/
|
|
236
|
+
addressInput: InputProps;
|
|
237
|
+
/**
|
|
238
|
+
* 상세 주소 입력 Input props
|
|
239
|
+
*/
|
|
240
|
+
detailInput?: InputProps;
|
|
241
|
+
/**
|
|
242
|
+
* 버튼 옵션
|
|
243
|
+
*/
|
|
244
|
+
buttonProps?: AddressTemplateButtonOptions;
|
|
245
|
+
/**
|
|
246
|
+
* 템플릿 disabled 여부
|
|
247
|
+
*/
|
|
248
|
+
disabled?: boolean;
|
|
249
|
+
}
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
ReactNode,
|
|
6
6
|
} from "react";
|
|
7
7
|
import type { UseFormRegisterReturn } from "react-hook-form";
|
|
8
|
+
import type { FormFieldWidth } from "../../form/types/props";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* input; priority option
|
|
@@ -99,6 +100,7 @@ export interface InputIcon {
|
|
|
99
100
|
* @property {React.ReactNode} [clear] input reset버튼 커스텀 컨텐츠
|
|
100
101
|
* @property {React.ReactNode} [success] input 입력상태 성공시 커스텀 컨텐츠
|
|
101
102
|
* @property {React.ReactNode} [error] input 입력상태 에러시 커스텀 컨텐츠
|
|
103
|
+
* @property {FormFieldWidth} [width] width preset 옵션
|
|
102
104
|
*/
|
|
103
105
|
export interface InputProps extends Omit<NativeInputProps, "size">, InputIcon {
|
|
104
106
|
/**
|
|
@@ -129,6 +131,10 @@ export interface InputProps extends Omit<NativeInputProps, "size">, InputIcon {
|
|
|
129
131
|
* react-hook-form register 반환값
|
|
130
132
|
*/
|
|
131
133
|
register?: UseFormRegisterReturn;
|
|
134
|
+
/**
|
|
135
|
+
* width preset 옵션
|
|
136
|
+
*/
|
|
137
|
+
width?: FormFieldWidth;
|
|
132
138
|
/**
|
|
133
139
|
* Storybook 등에서 강제 상태 표현용
|
|
134
140
|
*/
|