@uniai-fe/uds-templates 0.0.9 → 0.0.11

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 (44) hide show
  1. package/README.md +77 -1
  2. package/dist/styles.css +212 -267
  3. package/package.json +6 -4
  4. package/src/components/auth/index.tsx +11 -0
  5. package/src/components/auth/login/index.tsx +1 -1
  6. package/src/components/auth/login/markup/FormField.tsx +2 -2
  7. package/src/components/auth/login/types/props.ts +12 -12
  8. package/src/components/auth/login/types.ts +2 -2
  9. package/src/components/auth/signup/hooks/index.ts +3 -0
  10. package/src/components/auth/signup/hooks/useSignupAccountForm.ts +77 -0
  11. package/src/components/auth/signup/hooks/useSignupUserInfoForm.ts +81 -0
  12. package/src/components/auth/signup/hooks/useSignupVerificationForm.ts +77 -0
  13. package/src/components/auth/signup/index.ts +24 -0
  14. package/src/components/auth/signup/markup/AccountForm.tsx +124 -0
  15. package/src/components/auth/signup/markup/Complete.tsx +61 -0
  16. package/src/components/auth/signup/markup/UserInfoForm.tsx +97 -0
  17. package/src/components/auth/signup/markup/VerificationForm.tsx +155 -0
  18. package/src/components/auth/signup/markup/index.ts +4 -0
  19. package/src/components/auth/signup/styles/signup.scss +135 -0
  20. package/src/components/auth/signup/types/hooks.ts +85 -0
  21. package/src/components/auth/signup/types/index.ts +2 -0
  22. package/src/components/auth/signup/types/props.ts +105 -0
  23. package/src/components/auth/signup/utils/composeFieldProps.ts +50 -0
  24. package/src/components/modal/core/components/Container.tsx +41 -0
  25. package/src/components/modal/core/components/FooterButtons.tsx +132 -0
  26. package/src/components/modal/core/components/Provider.tsx +28 -0
  27. package/src/components/modal/core/components/Root.tsx +93 -0
  28. package/src/components/modal/core/hooks/useModal.ts +136 -0
  29. package/src/components/modal/core/jotai/atoms.ts +10 -0
  30. package/src/components/modal/index.scss +4 -0
  31. package/src/components/modal/index.tsx +16 -0
  32. package/src/components/modal/styles/animations.scss +24 -0
  33. package/src/components/modal/styles/base.scss +45 -0
  34. package/src/components/modal/styles/container.scss +138 -0
  35. package/src/components/modal/styles/dimmer.scss +23 -0
  36. package/src/components/modal/templates/Alert.tsx +104 -0
  37. package/src/components/modal/templates/Dialog.tsx +112 -0
  38. package/src/components/modal/types/footer.ts +36 -0
  39. package/src/components/modal/types/index.ts +21 -0
  40. package/src/components/modal/types/options.ts +6 -0
  41. package/src/components/modal/types/state.ts +31 -0
  42. package/src/components/modal/types/templates.ts +32 -0
  43. package/src/index.scss +1 -0
  44. package/src/index.tsx +1 -0
@@ -2,44 +2,44 @@ import React from "react";
2
2
  import type { SubmitHandler } from "react-hook-form";
3
3
  import type { AuthContainerProps } from "../../container";
4
4
  import type {
5
- InputFieldConfig,
5
+ InputFieldProps,
6
6
  InputPasswordProps,
7
7
  InputProps,
8
8
  } from "@uniai-fe/uds-primitives";
9
9
 
10
10
  /**
11
- * 로그인 입력 필드 설정
12
- * @typedef {AuthLoginFieldConfig}
11
+ * 로그인 입력 필드 props
12
+ * @typedef {AuthLoginFieldProps}
13
13
  * @template TProps
14
14
  * @desc
15
- * - InputFieldConfig 제네릭을 래핑해 로그인 요구사항과 연결한다.
15
+ * - InputFieldProps 제네릭을 래핑해 로그인 요구사항과 연결한다.
16
16
  * - props 제네릭으로 Input/PasswordInput 등 세부 props를 주입한다.
17
17
  */
18
- export type AuthLoginFieldConfig<TProps extends InputProps = InputProps> =
19
- InputFieldConfig<TProps>;
18
+ export type AuthLoginFieldProps<TProps extends InputProps = InputProps> =
19
+ InputFieldProps<TProps>;
20
20
 
21
21
  /**
22
22
  * 로그인 필드 묶음
23
23
  * @template TAdditional
24
24
  * @desc
25
25
  * - 필수 id/password 필드와 확장 필드를 포함한다.
26
- * @property {AuthLoginFieldConfig} id 아이디 필드 설정
27
- * @property {AuthLoginFieldConfig} password 비밀번호 필드 설정
26
+ * @property {AuthLoginFieldProps} id 아이디 필드 설정
27
+ * @property {AuthLoginFieldProps} password 비밀번호 필드 설정
28
28
  */
29
29
  export type AuthLoginFields<
30
- TAdditional extends Record<string, AuthLoginFieldConfig> = Record<
30
+ TAdditional extends Record<string, AuthLoginFieldProps> = Record<
31
31
  string,
32
- AuthLoginFieldConfig
32
+ AuthLoginFieldProps
33
33
  >,
34
34
  > = TAdditional & {
35
35
  /**
36
36
  * 아이디 필드 설정
37
37
  */
38
- id: AuthLoginFieldConfig<InputProps>;
38
+ id: AuthLoginFieldProps<InputProps>;
39
39
  /**
40
40
  * 비밀번호 필드 설정
41
41
  */
42
- password: AuthLoginFieldConfig<InputPasswordProps>;
42
+ password: AuthLoginFieldProps<InputPasswordProps>;
43
43
  };
44
44
 
45
45
  /**
@@ -1,2 +1,2 @@
1
- export * from "./types/props";
2
- export * from "./types/hooks";
1
+ export type * from "./types/props";
2
+ export type * from "./types/hooks";
@@ -0,0 +1,3 @@
1
+ export * from "./useSignupUserInfoForm";
2
+ export * from "./useSignupVerificationForm";
3
+ export * from "./useSignupAccountForm";
@@ -0,0 +1,77 @@
1
+ import { useMemo } from "react";
2
+ import { useWatch } from "react-hook-form";
3
+ import type { ReactNode } from "react";
4
+ import type {
5
+ AuthSignupAccountFields,
6
+ AuthSignupAccountValues,
7
+ AuthSignupFieldProps,
8
+ UseSignupAccountFormOptions,
9
+ UseSignupAccountFormReturn,
10
+ } from "../types";
11
+
12
+ /**
13
+ * 회원가입 Step3 훅; 계정 정보
14
+ * @hook
15
+ * @template TFields
16
+ * @param {UseSignupAccountFormOptions<TFields>} options
17
+ * @desc
18
+ * - 1) form init → 2) register merge → 3) helper/state → 4) submit 순서
19
+ */
20
+ export function useSignupAccountForm<
21
+ TFields extends Record<string, AuthSignupFieldProps> =
22
+ AuthSignupAccountFields,
23
+ >({
24
+ fields,
25
+ form,
26
+ onSubmit,
27
+ }: UseSignupAccountFormOptions<TFields>): UseSignupAccountFormReturn<TFields> {
28
+ const values = useWatch({ control: form.control }) as
29
+ | AuthSignupAccountValues
30
+ | undefined;
31
+
32
+ const register = useMemo(() => {
33
+ return (Object.keys(fields) as Array<keyof TFields>).reduce(
34
+ (acc, fieldKey) => {
35
+ const config = fields[fieldKey] as AuthSignupFieldProps;
36
+ const fieldName = config.attr?.name ?? String(fieldKey);
37
+ acc[fieldKey] = form.register(fieldName);
38
+ return acc;
39
+ },
40
+ {} as UseSignupAccountFormReturn<TFields>["register"],
41
+ );
42
+ }, [fields, form]);
43
+
44
+ const helpers = useMemo(() => {
45
+ return (Object.keys(fields) as Array<keyof TFields>).reduce(
46
+ (acc, fieldKey) => {
47
+ const config = fields[fieldKey] as AuthSignupFieldProps;
48
+ const fieldName = config.attr?.name ?? String(fieldKey);
49
+ const state = form.getFieldState(fieldName);
50
+ acc[fieldKey] = {
51
+ text:
52
+ (state.error?.message as ReactNode | undefined) ?? config.helper,
53
+ state: state.invalid ? "error" : undefined,
54
+ };
55
+ return acc;
56
+ },
57
+ {} as UseSignupAccountFormReturn<TFields>["helpers"],
58
+ );
59
+ }, [fields, form]);
60
+
61
+ const trimmedFilled =
62
+ values &&
63
+ Object.values(values).every(value =>
64
+ typeof value === "string" ? value.trim().length > 0 : false,
65
+ );
66
+
67
+ const disabled = form.formState.isSubmitting || !trimmedFilled;
68
+
69
+ const onSubmitHandler = form.handleSubmit(onSubmit);
70
+
71
+ return {
72
+ register,
73
+ helpers,
74
+ disabled,
75
+ onSubmit: onSubmitHandler,
76
+ };
77
+ }
@@ -0,0 +1,81 @@
1
+ import { useMemo } from "react";
2
+ import { useWatch } from "react-hook-form";
3
+ import type { ReactNode } from "react";
4
+ import type {
5
+ AuthSignupFieldProps,
6
+ AuthSignupUserInfoFields,
7
+ AuthSignupUserInfoValues,
8
+ UseSignupUserInfoFormOptions,
9
+ UseSignupUserInfoFormReturn,
10
+ } from "../types";
11
+
12
+ /**
13
+ * 회원가입 기본 정보 훅 옵션
14
+ * @typedef {UseSignupUserInfoFormOptions}
15
+ */
16
+ /**
17
+ * 회원가입 Step1 훅; 사용자 기본 정보
18
+ * @hook
19
+ * @template TFields
20
+ * @param {UseSignupUserInfoFormOptions<TFields>} options 훅 옵션
21
+ * @desc
22
+ * - 1) form init → 2) register merge → 3) helper/state → 4) submit 순서
23
+ */
24
+ export function useSignupUserInfoForm<
25
+ TFields extends Record<string, AuthSignupFieldProps> =
26
+ AuthSignupUserInfoFields,
27
+ >({
28
+ fields,
29
+ form,
30
+ onSubmit,
31
+ }: UseSignupUserInfoFormOptions<TFields>): UseSignupUserInfoFormReturn<TFields> {
32
+ const values = useWatch({ control: form.control }) as
33
+ | AuthSignupUserInfoValues
34
+ | undefined;
35
+
36
+ const register = useMemo(() => {
37
+ return (Object.keys(fields) as Array<keyof TFields>).reduce(
38
+ (acc, fieldKey) => {
39
+ const config = fields[fieldKey] as AuthSignupFieldProps;
40
+ const fieldName = config.attr?.name ?? String(fieldKey);
41
+ acc[fieldKey] = form.register(fieldName);
42
+ return acc;
43
+ },
44
+ {} as UseSignupUserInfoFormReturn<TFields>["register"],
45
+ );
46
+ }, [fields, form]);
47
+
48
+ const helpers = useMemo(() => {
49
+ return (Object.keys(fields) as Array<keyof TFields>).reduce(
50
+ (acc, fieldKey) => {
51
+ const config = fields[fieldKey] as AuthSignupFieldProps;
52
+ const fieldName = config.attr?.name ?? String(fieldKey);
53
+ const state = form.getFieldState(fieldName);
54
+ acc[fieldKey] = {
55
+ text:
56
+ (state.error?.message as ReactNode | undefined) ?? config.helper,
57
+ state: state.invalid ? "error" : undefined,
58
+ };
59
+ return acc;
60
+ },
61
+ {} as UseSignupUserInfoFormReturn<TFields>["helpers"],
62
+ );
63
+ }, [fields, form]);
64
+
65
+ const trimmedFilled =
66
+ values &&
67
+ Object.values(values).every(value =>
68
+ typeof value === "string" ? value.trim().length > 0 : false,
69
+ );
70
+
71
+ const disabled = form.formState.isSubmitting || !trimmedFilled;
72
+
73
+ const onSubmitHandler = form.handleSubmit(onSubmit);
74
+
75
+ return {
76
+ register,
77
+ helpers,
78
+ disabled,
79
+ onSubmit: onSubmitHandler,
80
+ };
81
+ }
@@ -0,0 +1,77 @@
1
+ import { useMemo } from "react";
2
+ import { useWatch } from "react-hook-form";
3
+ import type { ReactNode } from "react";
4
+ import type {
5
+ AuthSignupFieldProps,
6
+ AuthSignupVerificationFields,
7
+ AuthSignupVerificationValues,
8
+ UseSignupVerificationFormOptions,
9
+ UseSignupVerificationFormReturn,
10
+ } from "../types";
11
+
12
+ /**
13
+ * 회원가입 Step2 훅; 약관 + 이메일 인증
14
+ * @hook
15
+ * @template TFields
16
+ * @param {UseSignupVerificationFormOptions<TFields>} options
17
+ * @desc
18
+ * - 1) form init → 2) register merge → 3) helper/state → 4) submit 순서
19
+ */
20
+ export function useSignupVerificationForm<
21
+ TFields extends Record<string, AuthSignupFieldProps> =
22
+ AuthSignupVerificationFields,
23
+ >({
24
+ fields,
25
+ form,
26
+ onSubmit,
27
+ }: UseSignupVerificationFormOptions<TFields>): UseSignupVerificationFormReturn<TFields> {
28
+ const values = useWatch({ control: form.control }) as
29
+ | AuthSignupVerificationValues
30
+ | undefined;
31
+
32
+ const register = useMemo(() => {
33
+ return (Object.keys(fields) as Array<keyof TFields>).reduce(
34
+ (acc, fieldKey) => {
35
+ const config = fields[fieldKey] as AuthSignupFieldProps;
36
+ const fieldName = config.attr?.name ?? String(fieldKey);
37
+ acc[fieldKey] = form.register(fieldName);
38
+ return acc;
39
+ },
40
+ {} as UseSignupVerificationFormReturn<TFields>["register"],
41
+ );
42
+ }, [fields, form]);
43
+
44
+ const helpers = useMemo(() => {
45
+ return (Object.keys(fields) as Array<keyof TFields>).reduce(
46
+ (acc, fieldKey) => {
47
+ const config = fields[fieldKey] as AuthSignupFieldProps;
48
+ const fieldName = config.attr?.name ?? String(fieldKey);
49
+ const state = form.getFieldState(fieldName);
50
+ acc[fieldKey] = {
51
+ text:
52
+ (state.error?.message as ReactNode | undefined) ?? config.helper,
53
+ state: state.invalid ? "error" : undefined,
54
+ };
55
+ return acc;
56
+ },
57
+ {} as UseSignupVerificationFormReturn<TFields>["helpers"],
58
+ );
59
+ }, [fields, form]);
60
+
61
+ const trimmedFilled =
62
+ values &&
63
+ Object.values(values).every(value =>
64
+ typeof value === "string" ? value.trim().length > 0 : false,
65
+ );
66
+
67
+ const disabled = form.formState.isSubmitting || !trimmedFilled;
68
+
69
+ const onSubmitHandler = form.handleSubmit(onSubmit);
70
+
71
+ return {
72
+ register,
73
+ helpers,
74
+ disabled,
75
+ onSubmit: onSubmitHandler,
76
+ };
77
+ }
@@ -0,0 +1,24 @@
1
+ import {
2
+ AuthSignupUserInfoForm,
3
+ AuthSignupVerificationForm,
4
+ AuthSignupAccountForm,
5
+ AuthSignupComplete,
6
+ } from "./markup";
7
+
8
+ import "./styles/signup.scss";
9
+
10
+ export type * from "./types";
11
+ export * from "./hooks";
12
+ export {
13
+ AuthSignupUserInfoForm,
14
+ AuthSignupVerificationForm,
15
+ AuthSignupAccountForm,
16
+ AuthSignupComplete,
17
+ };
18
+
19
+ export const AuthSignup = {
20
+ StepUserInfo: AuthSignupUserInfoForm,
21
+ StepVerification: AuthSignupVerificationForm,
22
+ StepAccount: AuthSignupAccountForm,
23
+ StepComplete: AuthSignupComplete,
24
+ };
@@ -0,0 +1,124 @@
1
+ import { useMemo } from "react";
2
+ import { useForm } from "react-hook-form";
3
+ import {
4
+ Button,
5
+ Input,
6
+ PasswordInput,
7
+ type InputPasswordProps,
8
+ type InputProps,
9
+ } from "@uniai-fe/uds-primitives";
10
+ import type { AuthSignupAccountProps, AuthSignupAccountValues } from "../types";
11
+ import { useSignupAccountForm } from "../hooks";
12
+ import { composeSignupFieldProps } from "../utils/composeFieldProps";
13
+
14
+ const DEFAULT_SUBMIT_LABEL = "가입 요청";
15
+
16
+ /**
17
+ * 회원가입 Step3; 계정 정보 입력(아이디/비밀번호)
18
+ * @component
19
+ * @param {AuthSignupAccountProps} props account props
20
+ * @param {AuthSignupAccountProps["fields"]} props.fields 아이디/비밀번호 필드
21
+ * @param {AuthSignupPasswordRule[]} [props.passwordRules] 비밀번호 규칙 상태
22
+ * @param {React.FormHTMLAttributes<HTMLFormElement>} [props.formAttr] form attr
23
+ * @param {import("react").ReactNode} [props.submitLabel] CTA 라벨
24
+ */
25
+ export function AuthSignupAccountForm({
26
+ fields,
27
+ passwordRules,
28
+ formAttr,
29
+ submitLabel,
30
+ onSubmit,
31
+ }: AuthSignupAccountProps) {
32
+ // 필드 구성에서 name attr을 추출해 RHF default 값을 정의한다.
33
+ const defaultValues = useMemo(
34
+ () =>
35
+ (Object.keys(fields) as Array<keyof typeof fields>).reduce(
36
+ (acc, fieldKey) => {
37
+ const config = fields[fieldKey];
38
+ const fieldName = config.attr?.name ?? String(fieldKey);
39
+ acc[fieldName] = "";
40
+ return acc;
41
+ },
42
+ {} as AuthSignupAccountValues,
43
+ ),
44
+ [fields],
45
+ );
46
+
47
+ const form = useForm<AuthSignupAccountValues>({
48
+ mode: "onChange",
49
+ defaultValues,
50
+ });
51
+
52
+ const {
53
+ register,
54
+ helpers,
55
+ disabled,
56
+ onSubmit: handleSubmit,
57
+ } = useSignupAccountForm({
58
+ fields,
59
+ form,
60
+ onSubmit,
61
+ });
62
+
63
+ return (
64
+ <form
65
+ className="auth-signup-form auth-signup-form--account"
66
+ {...formAttr}
67
+ onSubmit={handleSubmit}
68
+ >
69
+ <div className="auth-signup-fields">
70
+ <Input
71
+ {...composeSignupFieldProps<InputProps>(
72
+ fields.accountId,
73
+ helpers.accountId,
74
+ )}
75
+ register={register.accountId}
76
+ />
77
+ <PasswordInput
78
+ {...composeSignupFieldProps<InputPasswordProps>(
79
+ fields.password,
80
+ helpers.password,
81
+ )}
82
+ register={register.password}
83
+ />
84
+ <PasswordInput
85
+ {...composeSignupFieldProps<InputPasswordProps>(
86
+ fields.confirmPassword,
87
+ helpers.confirmPassword,
88
+ )}
89
+ register={register.confirmPassword}
90
+ />
91
+ </div>
92
+ {passwordRules?.length ? (
93
+ <ul className="auth-signup-password-rules">
94
+ {passwordRules.map(rule => (
95
+ <li
96
+ key={rule.id}
97
+ className="auth-signup-password-rule"
98
+ data-fulfilled={rule.fulfilled ? "true" : undefined}
99
+ >
100
+ <span
101
+ className="auth-signup-password-rule-indicator"
102
+ aria-hidden="true"
103
+ />
104
+ <span className="auth-signup-password-rule-text">
105
+ {rule.label}
106
+ </span>
107
+ </li>
108
+ ))}
109
+ </ul>
110
+ ) : null}
111
+ <Button.Default
112
+ type="submit"
113
+ scale="solid-xlarge"
114
+ priority="primary"
115
+ block
116
+ disabled={disabled}
117
+ >
118
+ {submitLabel ?? DEFAULT_SUBMIT_LABEL}
119
+ </Button.Default>
120
+ </form>
121
+ );
122
+ }
123
+
124
+ export default AuthSignupAccountForm;
@@ -0,0 +1,61 @@
1
+ import { Button } from "@uniai-fe/uds-primitives";
2
+ import type { AuthSignupCompleteProps } from "../types";
3
+
4
+ /**
5
+ * 회원가입 Step4; 가입 완료/승인 대기 안내
6
+ * @component
7
+ * @param {AuthSignupCompleteProps} props complete props
8
+ * @param {React.ReactNode} props.title 완료 메시지
9
+ * @param {React.ReactNode} [props.description] 부가 설명
10
+ * @param {React.ReactNode} [props.illustration] 일러스트 영역
11
+ * @param {AuthSignupCompleteAction} props.primaryAction 주요 CTA
12
+ * @param {AuthSignupCompleteAction} [props.secondaryAction] 보조 CTA
13
+ */
14
+ export function AuthSignupComplete({
15
+ title,
16
+ description,
17
+ illustration,
18
+ primaryAction,
19
+ secondaryAction,
20
+ }: AuthSignupCompleteProps) {
21
+ // CTA 섹션은 primary/secondary 순으로 렌더해 사용자가 자연스럽게 진행하도록 안내한다.
22
+ return (
23
+ <section className="auth-signup-complete">
24
+ {illustration ? (
25
+ <div className="auth-signup-complete-illustration">{illustration}</div>
26
+ ) : null}
27
+ <div className="auth-signup-complete-text">
28
+ <h2 className="auth-signup-complete-title">{title}</h2>
29
+ {description ? (
30
+ <p className="auth-signup-complete-description">{description}</p>
31
+ ) : null}
32
+ </div>
33
+ <div className="auth-signup-complete-actions">
34
+ <Button.Default
35
+ type="button"
36
+ scale="solid-xlarge"
37
+ priority="primary"
38
+ block
39
+ disabled={primaryAction.disabled}
40
+ onClick={primaryAction.onClick}
41
+ >
42
+ {primaryAction.label}
43
+ </Button.Default>
44
+ {secondaryAction ? (
45
+ <Button.Default
46
+ type="button"
47
+ scale="solid-xlarge"
48
+ priority="secondary"
49
+ block
50
+ disabled={secondaryAction.disabled}
51
+ onClick={secondaryAction.onClick}
52
+ >
53
+ {secondaryAction.label}
54
+ </Button.Default>
55
+ ) : null}
56
+ </div>
57
+ </section>
58
+ );
59
+ }
60
+
61
+ export default AuthSignupComplete;
@@ -0,0 +1,97 @@
1
+ import { useMemo } from "react";
2
+ import { useForm } from "react-hook-form";
3
+ import {
4
+ Button,
5
+ Input,
6
+ PhoneInput,
7
+ type InputProps,
8
+ type PhoneInputProps,
9
+ } from "@uniai-fe/uds-primitives";
10
+ import type {
11
+ AuthSignupUserInfoProps,
12
+ AuthSignupUserInfoValues,
13
+ } from "../types";
14
+ import { useSignupUserInfoForm } from "../hooks";
15
+ import { composeSignupFieldProps } from "../utils/composeFieldProps";
16
+
17
+ const DEFAULT_SUBMIT_LABEL = "다음";
18
+
19
+ /**
20
+ * 회원가입 Step1; 사용자 기본 정보(이름/휴대폰) 입력 폼
21
+ * @component
22
+ * @param {AuthSignupUserInfoProps} props form props
23
+ * @param {AuthSignupUserInfoFields} props.fields 필드 설정
24
+ * @param {React.FormHTMLAttributes<HTMLFormElement>} [props.formAttr] form attr
25
+ * @param {import("react").ReactNode} [props.submitLabel] CTA 라벨
26
+ * @param {SubmitHandler<AuthSignupUserInfoValues>} props.onSubmit 제출 핸들러
27
+ */
28
+ export function AuthSignupUserInfoForm({
29
+ fields,
30
+ formAttr,
31
+ submitLabel,
32
+ onSubmit,
33
+ }: AuthSignupUserInfoProps) {
34
+ // 필드 name attr을 기준으로 RHF defaultValues를 생성한다.
35
+ const defaultValues = useMemo(
36
+ () =>
37
+ (Object.keys(fields) as Array<keyof typeof fields>).reduce(
38
+ (acc, fieldKey) => {
39
+ const config = fields[fieldKey];
40
+ const fieldName = config.attr?.name ?? String(fieldKey);
41
+ acc[fieldName] = "";
42
+ return acc;
43
+ },
44
+ {} as AuthSignupUserInfoValues,
45
+ ),
46
+ [fields],
47
+ );
48
+
49
+ const form = useForm<AuthSignupUserInfoValues>({
50
+ mode: "onChange",
51
+ defaultValues,
52
+ });
53
+
54
+ const {
55
+ register,
56
+ helpers,
57
+ disabled,
58
+ onSubmit: handleSubmit,
59
+ } = useSignupUserInfoForm({
60
+ fields,
61
+ form,
62
+ onSubmit,
63
+ });
64
+
65
+ return (
66
+ <form
67
+ className="auth-signup-form auth-signup-form--user-info"
68
+ {...formAttr}
69
+ onSubmit={handleSubmit}
70
+ >
71
+ <div className="auth-signup-fields">
72
+ <Input
73
+ {...composeSignupFieldProps<InputProps>(fields.name, helpers.name)}
74
+ register={register.name}
75
+ />
76
+ <PhoneInput
77
+ {...composeSignupFieldProps<PhoneInputProps>(
78
+ fields.phone,
79
+ helpers.phone,
80
+ )}
81
+ register={register.phone}
82
+ />
83
+ </div>
84
+ <Button.Default
85
+ type="submit"
86
+ scale="solid-xlarge"
87
+ priority="primary"
88
+ block
89
+ disabled={disabled}
90
+ >
91
+ {submitLabel ?? DEFAULT_SUBMIT_LABEL}
92
+ </Button.Default>
93
+ </form>
94
+ );
95
+ }
96
+
97
+ export default AuthSignupUserInfoForm;