@ttoss/forms 0.26.0 → 0.26.1
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/LICENSE +21 -674
- package/package.json +11 -11
- package/src/Brazil/FormFieldCEP.tsx +0 -25
- package/src/Brazil/FormFieldCNPJ.tsx +0 -93
- package/src/Brazil/FormFieldPhone.tsx +0 -41
- package/src/Brazil/index.ts +0 -4
- package/src/Form.tsx +0 -29
- package/src/FormErrorMessage.tsx +0 -60
- package/src/FormField.tsx +0 -86
- package/src/FormFieldCheckbox.tsx +0 -49
- package/src/FormFieldCreditCardNumber.tsx +0 -25
- package/src/FormFieldCurrencyInput.tsx +0 -36
- package/src/FormFieldInput.tsx +0 -43
- package/src/FormFieldNumericFormat.tsx +0 -35
- package/src/FormFieldPassword.tsx +0 -43
- package/src/FormFieldPatternFormat.tsx +0 -36
- package/src/FormFieldRadio.tsx +0 -57
- package/src/FormFieldSelect.tsx +0 -47
- package/src/FormFieldTextarea.tsx +0 -36
- package/src/FormGroup.tsx +0 -136
- package/src/MultistepForm/MultistepFlowMessage.tsx +0 -14
- package/src/MultistepForm/MultistepFlowMessageImageText.tsx +0 -37
- package/src/MultistepForm/MultistepFooter.tsx +0 -18
- package/src/MultistepForm/MultistepForm.tsx +0 -117
- package/src/MultistepForm/MultistepFormStepper.tsx +0 -70
- package/src/MultistepForm/MultistepHeader.tsx +0 -78
- package/src/MultistepForm/MultistepNavigation.tsx +0 -38
- package/src/MultistepForm/MultistepQuestion.tsx +0 -28
- package/src/MultistepForm/index.ts +0 -1
- package/src/MultistepForm/types.ts +0 -7
- package/src/index.ts +0 -35
- package/src/yup/i18n.ts +0 -31
- package/src/yup/schema.ts +0 -26
- package/src/yup/typings.d.ts +0 -14
- package/src/yup/yup.ts +0 -4
package/src/FormFieldRadio.tsx
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { Box, Flex, Label, Radio, type RadioProps } from '@ttoss/ui';
|
|
2
|
-
import { FieldPath, FieldValues, useController } from 'react-hook-form';
|
|
3
|
-
import { FormErrorMessage } from './FormErrorMessage';
|
|
4
|
-
|
|
5
|
-
type FormRadioOption = {
|
|
6
|
-
value: string | number;
|
|
7
|
-
label: string;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export const FormFieldRadio = <TFieldValues extends FieldValues = FieldValues>({
|
|
11
|
-
label,
|
|
12
|
-
name,
|
|
13
|
-
options,
|
|
14
|
-
sx,
|
|
15
|
-
...radioProps
|
|
16
|
-
}: {
|
|
17
|
-
label?: string;
|
|
18
|
-
name: FieldPath<TFieldValues>;
|
|
19
|
-
options: FormRadioOption[];
|
|
20
|
-
} & RadioProps) => {
|
|
21
|
-
const {
|
|
22
|
-
field: { onChange, onBlur, value, ref },
|
|
23
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
24
|
-
} = useController<any>({
|
|
25
|
-
name,
|
|
26
|
-
defaultValue: '',
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
return (
|
|
30
|
-
<Flex sx={{ flexDirection: 'column', width: '100%', ...sx }}>
|
|
31
|
-
{label && <Label sx={{ marginBottom: 'md' }}>{label}</Label>}
|
|
32
|
-
<Box>
|
|
33
|
-
{options.map((option: FormRadioOption) => {
|
|
34
|
-
const id = `form-field-radio-${name}-${option.value}`;
|
|
35
|
-
|
|
36
|
-
return (
|
|
37
|
-
<Label key={id} htmlFor={id}>
|
|
38
|
-
<Radio
|
|
39
|
-
ref={ref}
|
|
40
|
-
onChange={onChange}
|
|
41
|
-
onBlur={onBlur}
|
|
42
|
-
value={option.value}
|
|
43
|
-
checked={value === option.value}
|
|
44
|
-
name={name}
|
|
45
|
-
id={id}
|
|
46
|
-
{...radioProps}
|
|
47
|
-
/>
|
|
48
|
-
{option.label}
|
|
49
|
-
</Label>
|
|
50
|
-
);
|
|
51
|
-
})}
|
|
52
|
-
</Box>
|
|
53
|
-
|
|
54
|
-
<FormErrorMessage name={name} />
|
|
55
|
-
</Flex>
|
|
56
|
-
);
|
|
57
|
-
};
|
package/src/FormFieldSelect.tsx
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { FieldPath, FieldValues } from 'react-hook-form';
|
|
2
|
-
import { FormField, FormFieldProps } from './FormField';
|
|
3
|
-
import { Select, type SelectProps } from '@ttoss/ui';
|
|
4
|
-
|
|
5
|
-
type FormFieldSelectProps<
|
|
6
|
-
TFieldValues extends FieldValues = FieldValues,
|
|
7
|
-
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
8
|
-
> = Omit<SelectProps, 'defaultValue'> & FormFieldProps<TFieldValues, TName>;
|
|
9
|
-
|
|
10
|
-
export const FormFieldSelect = <
|
|
11
|
-
TFieldValues extends FieldValues = FieldValues,
|
|
12
|
-
>({
|
|
13
|
-
label,
|
|
14
|
-
name,
|
|
15
|
-
id,
|
|
16
|
-
defaultValue,
|
|
17
|
-
sx,
|
|
18
|
-
css,
|
|
19
|
-
disabled,
|
|
20
|
-
tooltip,
|
|
21
|
-
onTooltipClick,
|
|
22
|
-
...selectProps
|
|
23
|
-
}: FormFieldSelectProps<TFieldValues>) => {
|
|
24
|
-
return (
|
|
25
|
-
<FormField
|
|
26
|
-
name={name}
|
|
27
|
-
label={label}
|
|
28
|
-
id={id}
|
|
29
|
-
defaultValue={defaultValue}
|
|
30
|
-
disabled={disabled}
|
|
31
|
-
tooltip={tooltip}
|
|
32
|
-
onTooltipClick={onTooltipClick}
|
|
33
|
-
sx={sx}
|
|
34
|
-
css={css}
|
|
35
|
-
render={({ field, fieldState }) => {
|
|
36
|
-
return (
|
|
37
|
-
<Select
|
|
38
|
-
{...selectProps}
|
|
39
|
-
{...field}
|
|
40
|
-
isDisabled={disabled}
|
|
41
|
-
aria-invalid={fieldState.error ? 'true' : undefined}
|
|
42
|
-
/>
|
|
43
|
-
);
|
|
44
|
-
}}
|
|
45
|
-
/>
|
|
46
|
-
);
|
|
47
|
-
};
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { FieldPath, FieldValues } from 'react-hook-form';
|
|
2
|
-
import { FormField } from './FormField';
|
|
3
|
-
import { Textarea, type TextareaProps } from '@ttoss/ui';
|
|
4
|
-
|
|
5
|
-
export const FormFieldTextarea = <
|
|
6
|
-
TFieldValues extends FieldValues = FieldValues,
|
|
7
|
-
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
|
8
|
-
>({
|
|
9
|
-
label,
|
|
10
|
-
name,
|
|
11
|
-
sx,
|
|
12
|
-
...textareaProps
|
|
13
|
-
}: {
|
|
14
|
-
label?: string;
|
|
15
|
-
name: TName;
|
|
16
|
-
} & TextareaProps) => {
|
|
17
|
-
const id = `form-field-textarea-${name}`;
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<FormField
|
|
21
|
-
label={label}
|
|
22
|
-
name={name}
|
|
23
|
-
id={id}
|
|
24
|
-
sx={sx}
|
|
25
|
-
render={({ field, fieldState }) => {
|
|
26
|
-
return (
|
|
27
|
-
<Textarea
|
|
28
|
-
{...field}
|
|
29
|
-
{...textareaProps}
|
|
30
|
-
aria-invalid={fieldState.error ? 'true' : undefined}
|
|
31
|
-
/>
|
|
32
|
-
);
|
|
33
|
-
}}
|
|
34
|
-
/>
|
|
35
|
-
);
|
|
36
|
-
};
|
package/src/FormGroup.tsx
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Box, BoxProps, Flex, FlexProps, Text } from '@ttoss/ui';
|
|
3
|
-
import { FormErrorMessage } from './FormErrorMessage';
|
|
4
|
-
|
|
5
|
-
type FormGroupLevelsManagerContextType = {
|
|
6
|
-
levelsLength: number;
|
|
7
|
-
registerChild: (level: number) => void;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
const FormGroupLevelsManagerContext =
|
|
11
|
-
React.createContext<FormGroupLevelsManagerContextType>({
|
|
12
|
-
levelsLength: 1,
|
|
13
|
-
registerChild: () => {
|
|
14
|
-
return null;
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const FormGroupLevelsManager = ({
|
|
19
|
-
children,
|
|
20
|
-
}: {
|
|
21
|
-
children: React.ReactNode;
|
|
22
|
-
}) => {
|
|
23
|
-
const [levelsLength, setLevelsLength] = React.useState(0);
|
|
24
|
-
|
|
25
|
-
const registerChild = React.useCallback(
|
|
26
|
-
(level: number) => {
|
|
27
|
-
if (level + 1 > levelsLength) {
|
|
28
|
-
setLevelsLength(level + 1);
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
[levelsLength]
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<FormGroupLevelsManagerContext.Provider
|
|
36
|
-
value={{ levelsLength, registerChild }}
|
|
37
|
-
>
|
|
38
|
-
{children}
|
|
39
|
-
</FormGroupLevelsManagerContext.Provider>
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
type FormGroupContextType = {
|
|
44
|
-
parentLevel?: number;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const FormGroupContext = React.createContext<FormGroupContextType>({});
|
|
48
|
-
|
|
49
|
-
export const useFormGroup = () => {
|
|
50
|
-
const { parentLevel } = React.useContext(FormGroupContext);
|
|
51
|
-
const { levelsLength } = React.useContext(FormGroupLevelsManagerContext);
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
level: parentLevel,
|
|
55
|
-
levelsLength,
|
|
56
|
-
};
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
type FormGroupProps = {
|
|
60
|
-
name?: string;
|
|
61
|
-
title?: string;
|
|
62
|
-
direction?: 'column' | 'row';
|
|
63
|
-
} & BoxProps;
|
|
64
|
-
|
|
65
|
-
const FormGroupWrapper = ({
|
|
66
|
-
title,
|
|
67
|
-
direction,
|
|
68
|
-
children,
|
|
69
|
-
name,
|
|
70
|
-
...boxProps
|
|
71
|
-
}: FormGroupProps) => {
|
|
72
|
-
const { level } = useFormGroup();
|
|
73
|
-
|
|
74
|
-
const { registerChild } = React.useContext(FormGroupLevelsManagerContext);
|
|
75
|
-
|
|
76
|
-
React.useEffect(() => {
|
|
77
|
-
/**
|
|
78
|
-
* We can't use if(level) because level can be 0 and we want to register
|
|
79
|
-
* it anyway.
|
|
80
|
-
*/
|
|
81
|
-
if (typeof level === 'number') {
|
|
82
|
-
registerChild(level);
|
|
83
|
-
}
|
|
84
|
-
}, [level, registerChild]);
|
|
85
|
-
|
|
86
|
-
const childrenContainerSx: FlexProps['sx'] = {
|
|
87
|
-
flexDirection: direction || 'column',
|
|
88
|
-
gap: 'md',
|
|
89
|
-
width: '100%',
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
return (
|
|
93
|
-
<Box
|
|
94
|
-
aria-level={level}
|
|
95
|
-
{...boxProps}
|
|
96
|
-
sx={{
|
|
97
|
-
marginTop: level === 0 ? 'none' : 'lg',
|
|
98
|
-
marginBottom: 'lg',
|
|
99
|
-
...boxProps.sx,
|
|
100
|
-
}}
|
|
101
|
-
>
|
|
102
|
-
{title && (
|
|
103
|
-
<Box sx={{ marginBottom: 'md' }}>
|
|
104
|
-
<Text
|
|
105
|
-
sx={{
|
|
106
|
-
fontSize: '2xl',
|
|
107
|
-
fontWeight: 'bold',
|
|
108
|
-
}}
|
|
109
|
-
>
|
|
110
|
-
{title}
|
|
111
|
-
</Text>
|
|
112
|
-
</Box>
|
|
113
|
-
)}
|
|
114
|
-
<Flex sx={childrenContainerSx}>{children}</Flex>
|
|
115
|
-
{name && <FormErrorMessage name={name} />}
|
|
116
|
-
</Box>
|
|
117
|
-
);
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
export const FormGroup = (props: FormGroupProps) => {
|
|
121
|
-
const { level } = useFormGroup();
|
|
122
|
-
|
|
123
|
-
const currentLevel = level === undefined ? 0 : level + 1;
|
|
124
|
-
|
|
125
|
-
return (
|
|
126
|
-
<FormGroupContext.Provider value={{ parentLevel: currentLevel }}>
|
|
127
|
-
{currentLevel === 0 ? (
|
|
128
|
-
<FormGroupLevelsManager>
|
|
129
|
-
<FormGroupWrapper {...props} />
|
|
130
|
-
</FormGroupLevelsManager>
|
|
131
|
-
) : (
|
|
132
|
-
<FormGroupWrapper {...props} />
|
|
133
|
-
)}
|
|
134
|
-
</FormGroupContext.Provider>
|
|
135
|
-
);
|
|
136
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
MultistepFlowMessageImageText,
|
|
3
|
-
MultistepFlowMessageImageTextProps,
|
|
4
|
-
} from './MultistepFlowMessageImageText';
|
|
5
|
-
|
|
6
|
-
export type MultistepFlowMessageProps = MultistepFlowMessageImageTextProps;
|
|
7
|
-
|
|
8
|
-
export const MultistepFlowMessage = (props: MultistepFlowMessageProps) => {
|
|
9
|
-
if (props.variant === 'image-text') {
|
|
10
|
-
return <MultistepFlowMessageImageText {...props} />;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return null;
|
|
14
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Flex, Image, Text } from '@ttoss/ui';
|
|
3
|
-
import { MultistepFlowMessageBase } from './types';
|
|
4
|
-
|
|
5
|
-
export type MultistepFlowMessageImageTextProps = MultistepFlowMessageBase & {
|
|
6
|
-
variant: 'image-text';
|
|
7
|
-
src: string;
|
|
8
|
-
description: string | React.ReactNode;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const MultistepFlowMessageImageText = ({
|
|
12
|
-
src,
|
|
13
|
-
description,
|
|
14
|
-
}: MultistepFlowMessageImageTextProps) => {
|
|
15
|
-
return (
|
|
16
|
-
<Flex
|
|
17
|
-
sx={{
|
|
18
|
-
flexDirection: 'column',
|
|
19
|
-
paddingY: 'xl',
|
|
20
|
-
paddingX: '2xl',
|
|
21
|
-
gap: 'xl',
|
|
22
|
-
}}
|
|
23
|
-
>
|
|
24
|
-
<Image
|
|
25
|
-
src={src}
|
|
26
|
-
sx={{
|
|
27
|
-
width: '184px',
|
|
28
|
-
height: '184px',
|
|
29
|
-
objectFit: 'cover',
|
|
30
|
-
alignSelf: 'center',
|
|
31
|
-
}}
|
|
32
|
-
/>
|
|
33
|
-
|
|
34
|
-
<Text sx={{ textAlign: 'center' }}>{description}</Text>
|
|
35
|
-
</Flex>
|
|
36
|
-
);
|
|
37
|
-
};
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Flex, Text } from '@ttoss/ui';
|
|
2
|
-
|
|
3
|
-
export const MultistepFooter = ({ footer }: { footer: string }) => {
|
|
4
|
-
return (
|
|
5
|
-
<Flex sx={{ display: 'flex', justifyContent: 'center' }}>
|
|
6
|
-
<Text
|
|
7
|
-
sx={{
|
|
8
|
-
textAlign: 'center',
|
|
9
|
-
marginTop: '4xl',
|
|
10
|
-
marginBottom: 'lg',
|
|
11
|
-
marginX: '2xl',
|
|
12
|
-
}}
|
|
13
|
-
>
|
|
14
|
-
{footer}
|
|
15
|
-
</Text>
|
|
16
|
-
</Flex>
|
|
17
|
-
);
|
|
18
|
-
};
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Flex } from '@ttoss/ui';
|
|
3
|
-
import { MultistepFlowMessageProps } from './MultistepFlowMessage';
|
|
4
|
-
import { MultistepFooter } from './MultistepFooter';
|
|
5
|
-
import {
|
|
6
|
-
MultistepFormStepper,
|
|
7
|
-
type MultistepFormStepperProps,
|
|
8
|
-
} from './MultistepFormStepper';
|
|
9
|
-
import { MultistepHeader, type MultistepHeaderProps } from './MultistepHeader';
|
|
10
|
-
import { MultistepNavigation } from './MultistepNavigation';
|
|
11
|
-
|
|
12
|
-
export type MultistepStep = {
|
|
13
|
-
question: string;
|
|
14
|
-
flowMessage: MultistepFlowMessageProps;
|
|
15
|
-
label: string;
|
|
16
|
-
fields: React.ReactNode | React.ReactNode[];
|
|
17
|
-
schema?: MultistepFormStepperProps['schema'];
|
|
18
|
-
defaultValues?: MultistepFormStepperProps['defaultValues'];
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export type MultistepFormProps<FormValues = unknown> = {
|
|
22
|
-
header: MultistepHeaderProps;
|
|
23
|
-
steps: MultistepStep[];
|
|
24
|
-
footer?: string;
|
|
25
|
-
onSubmit: (data: FormValues) => void;
|
|
26
|
-
nextStepButtonLabel?: string;
|
|
27
|
-
submitButtonLabel?: string;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const MultistepForm = ({
|
|
31
|
-
nextStepButtonLabel = 'Next',
|
|
32
|
-
submitButtonLabel = 'Send',
|
|
33
|
-
...props
|
|
34
|
-
}: MultistepFormProps) => {
|
|
35
|
-
const amountOfSteps = props.steps.length;
|
|
36
|
-
const [currentStep, setCurrentStep] = React.useState(1);
|
|
37
|
-
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
-
const [form, setForm] = React.useState<any>({});
|
|
40
|
-
|
|
41
|
-
const nextStep = () => {
|
|
42
|
-
if (currentStep < amountOfSteps) {
|
|
43
|
-
setCurrentStep((step) => {
|
|
44
|
-
return step + 1;
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
const backStep = () => {
|
|
50
|
-
if (currentStep > 1) {
|
|
51
|
-
setCurrentStep((step) => {
|
|
52
|
-
return step - 1;
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<Flex
|
|
59
|
-
sx={{
|
|
60
|
-
flexDirection: 'column',
|
|
61
|
-
maxWidth: '390px',
|
|
62
|
-
background: '#fff',
|
|
63
|
-
}}
|
|
64
|
-
>
|
|
65
|
-
<MultistepHeader {...props.header} />
|
|
66
|
-
{props.steps.map((step, stepIndex) => {
|
|
67
|
-
const isLastStep = stepIndex + 1 === amountOfSteps;
|
|
68
|
-
const isCurrentStep = stepIndex + 1 === currentStep;
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<Flex
|
|
72
|
-
sx={{
|
|
73
|
-
flexDirection: 'column',
|
|
74
|
-
display: isCurrentStep ? 'flex' : 'none',
|
|
75
|
-
}}
|
|
76
|
-
key={`form-step-${step.question}`}
|
|
77
|
-
aria-hidden={!isCurrentStep}
|
|
78
|
-
>
|
|
79
|
-
<MultistepFormStepper
|
|
80
|
-
{...step}
|
|
81
|
-
stepNumber={stepIndex + 1}
|
|
82
|
-
isLastStep={isLastStep}
|
|
83
|
-
// isCurrentStep={isCurrentStep}
|
|
84
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
85
|
-
onSubmit={(data: any) => {
|
|
86
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
87
|
-
const newValue = { ...form, ...data };
|
|
88
|
-
|
|
89
|
-
setForm(newValue);
|
|
90
|
-
|
|
91
|
-
if (isLastStep) {
|
|
92
|
-
props.onSubmit(newValue);
|
|
93
|
-
} else {
|
|
94
|
-
nextStep();
|
|
95
|
-
}
|
|
96
|
-
}}
|
|
97
|
-
submitLabel={isLastStep ? submitButtonLabel : nextStepButtonLabel}
|
|
98
|
-
/>
|
|
99
|
-
</Flex>
|
|
100
|
-
);
|
|
101
|
-
})}
|
|
102
|
-
|
|
103
|
-
{currentStep > 1 && (
|
|
104
|
-
<MultistepNavigation
|
|
105
|
-
amountOfSteps={amountOfSteps}
|
|
106
|
-
currentStepNumber={currentStep}
|
|
107
|
-
onBack={backStep}
|
|
108
|
-
stepsLabel={props.steps.map((s) => {
|
|
109
|
-
return s.label;
|
|
110
|
-
})}
|
|
111
|
-
/>
|
|
112
|
-
)}
|
|
113
|
-
|
|
114
|
-
{props.footer && <MultistepFooter footer={props.footer} />}
|
|
115
|
-
</Flex>
|
|
116
|
-
);
|
|
117
|
-
};
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Button } from '@ttoss/ui';
|
|
3
|
-
import { Form, useForm, yup, yupResolver } from '../';
|
|
4
|
-
import {
|
|
5
|
-
MultistepFlowMessage,
|
|
6
|
-
MultistepFlowMessageProps,
|
|
7
|
-
} from './MultistepFlowMessage';
|
|
8
|
-
import { MultistepQuestion } from './MultistepQuestion';
|
|
9
|
-
|
|
10
|
-
export type MultistepFormStepperProps = {
|
|
11
|
-
flowMessage: MultistepFlowMessageProps;
|
|
12
|
-
onSubmit: (data: unknown) => void;
|
|
13
|
-
question: string;
|
|
14
|
-
isLastStep: boolean;
|
|
15
|
-
fields: React.ReactNode | React.ReactNode[];
|
|
16
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
-
schema?: yup.ObjectSchema<any>;
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
-
defaultValues?: any;
|
|
20
|
-
submitLabel: string;
|
|
21
|
-
stepNumber: number;
|
|
22
|
-
// isCurrentStep: boolean;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const MultistepFormStepper = ({
|
|
26
|
-
flowMessage,
|
|
27
|
-
fields,
|
|
28
|
-
onSubmit,
|
|
29
|
-
question,
|
|
30
|
-
submitLabel,
|
|
31
|
-
schema,
|
|
32
|
-
isLastStep,
|
|
33
|
-
defaultValues,
|
|
34
|
-
stepNumber,
|
|
35
|
-
// isCurrentStep,
|
|
36
|
-
}: MultistepFormStepperProps) => {
|
|
37
|
-
const formMethods = useForm({
|
|
38
|
-
resolver: schema ? yupResolver(schema) : undefined,
|
|
39
|
-
defaultValues,
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<Form
|
|
44
|
-
{...formMethods}
|
|
45
|
-
sx={{
|
|
46
|
-
display: 'flex',
|
|
47
|
-
flexDirection: 'column',
|
|
48
|
-
}}
|
|
49
|
-
onSubmit={onSubmit}
|
|
50
|
-
>
|
|
51
|
-
<MultistepFlowMessage {...flowMessage} />
|
|
52
|
-
|
|
53
|
-
<MultistepQuestion fields={fields} question={question} />
|
|
54
|
-
|
|
55
|
-
<Button
|
|
56
|
-
sx={{
|
|
57
|
-
justifyContent: 'center',
|
|
58
|
-
marginTop: '2xl',
|
|
59
|
-
marginBottom: 'xl',
|
|
60
|
-
marginX: '2xl',
|
|
61
|
-
}}
|
|
62
|
-
rightIcon={isLastStep ? undefined : 'nav-right'}
|
|
63
|
-
aria-label={`btn-step-${stepNumber}`}
|
|
64
|
-
type="submit"
|
|
65
|
-
>
|
|
66
|
-
{submitLabel}
|
|
67
|
-
</Button>
|
|
68
|
-
</Form>
|
|
69
|
-
);
|
|
70
|
-
};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { CloseButton, Flex, Image, Text } from '@ttoss/ui';
|
|
2
|
-
import { Icon, type IconType } from '@ttoss/react-icons';
|
|
3
|
-
|
|
4
|
-
type MultistepHeaderTitledProps = {
|
|
5
|
-
variant: 'titled';
|
|
6
|
-
title: string;
|
|
7
|
-
leftIcon: IconType;
|
|
8
|
-
rightIcon: IconType;
|
|
9
|
-
onLeftIconClick: () => void;
|
|
10
|
-
onRightIconClick: () => void;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const MultistepHeaderTitled = ({
|
|
14
|
-
title,
|
|
15
|
-
leftIcon,
|
|
16
|
-
onLeftIconClick,
|
|
17
|
-
rightIcon,
|
|
18
|
-
onRightIconClick,
|
|
19
|
-
}: MultistepHeaderTitledProps) => {
|
|
20
|
-
return (
|
|
21
|
-
<Flex
|
|
22
|
-
sx={{
|
|
23
|
-
display: 'flex',
|
|
24
|
-
justifyContent: 'space-between',
|
|
25
|
-
paddingX: 'xl',
|
|
26
|
-
paddingY: 'lg',
|
|
27
|
-
alignItems: 'center',
|
|
28
|
-
}}
|
|
29
|
-
>
|
|
30
|
-
<Icon icon={leftIcon} onClick={onLeftIconClick} />
|
|
31
|
-
<Text sx={{ fontWeight: 'bold', fontSize: 'lg' }}>{title}</Text>
|
|
32
|
-
<Icon icon={rightIcon} onClick={onRightIconClick} />
|
|
33
|
-
</Flex>
|
|
34
|
-
);
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
type MultistepHeaderLogoProps = {
|
|
38
|
-
variant: 'logo';
|
|
39
|
-
src: string;
|
|
40
|
-
onClose?: () => void;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const MultistepHeaderLogo = ({ onClose, src }: MultistepHeaderLogoProps) => {
|
|
44
|
-
return (
|
|
45
|
-
<Flex
|
|
46
|
-
sx={{
|
|
47
|
-
justifyContent: 'space-between',
|
|
48
|
-
alignItems: 'center',
|
|
49
|
-
paddingX: 'xl',
|
|
50
|
-
paddingY: 'lg',
|
|
51
|
-
}}
|
|
52
|
-
>
|
|
53
|
-
<Image
|
|
54
|
-
width={115}
|
|
55
|
-
height={32}
|
|
56
|
-
sx={{ objectFit: 'cover', width: 115, height: 32 }}
|
|
57
|
-
src={src}
|
|
58
|
-
/>
|
|
59
|
-
{onClose && <CloseButton onClick={onClose} />}
|
|
60
|
-
</Flex>
|
|
61
|
-
);
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export type MultistepHeaderProps =
|
|
65
|
-
| MultistepHeaderLogoProps
|
|
66
|
-
| MultistepHeaderTitledProps;
|
|
67
|
-
|
|
68
|
-
export const MultistepHeader = (props: MultistepHeaderProps) => {
|
|
69
|
-
if (props.variant === 'logo') {
|
|
70
|
-
return <MultistepHeaderLogo {...props} />;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (props.variant === 'titled') {
|
|
74
|
-
return <MultistepHeaderTitled {...props} />;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return null;
|
|
78
|
-
};
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { Flex, Text } from '@ttoss/ui';
|
|
2
|
-
import { Icon } from '@ttoss/react-icons';
|
|
3
|
-
|
|
4
|
-
export type MultistepNavigationProps = {
|
|
5
|
-
amountOfSteps: number;
|
|
6
|
-
currentStepNumber: number;
|
|
7
|
-
onBack: () => void;
|
|
8
|
-
stepsLabel: string[];
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const MultistepNavigation = ({
|
|
12
|
-
amountOfSteps,
|
|
13
|
-
currentStepNumber,
|
|
14
|
-
onBack,
|
|
15
|
-
stepsLabel,
|
|
16
|
-
}: MultistepNavigationProps) => {
|
|
17
|
-
return (
|
|
18
|
-
<Flex
|
|
19
|
-
sx={{
|
|
20
|
-
justifyContent: 'space-between',
|
|
21
|
-
marginX: '2xl',
|
|
22
|
-
}}
|
|
23
|
-
>
|
|
24
|
-
<Flex onClick={onBack} sx={{ alignItems: 'center', cursor: 'pointer' }}>
|
|
25
|
-
<Text sx={{ color: '#ACADB7', display: 'flex' }}>
|
|
26
|
-
<Icon icon="nav-left" />
|
|
27
|
-
</Text>
|
|
28
|
-
<Text sx={{ color: '#ACADB7' }}>
|
|
29
|
-
{stepsLabel[currentStepNumber - 2]}
|
|
30
|
-
</Text>
|
|
31
|
-
</Flex>
|
|
32
|
-
|
|
33
|
-
<Text sx={{ alignItems: 'center', color: '#ACADB7' }}>
|
|
34
|
-
{currentStepNumber}/{amountOfSteps}
|
|
35
|
-
</Text>
|
|
36
|
-
</Flex>
|
|
37
|
-
);
|
|
38
|
-
};
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import * as React from 'react';
|
|
2
|
-
import { Flex, Text } from '@ttoss/ui';
|
|
3
|
-
|
|
4
|
-
type MultistepQuestionProps = {
|
|
5
|
-
question: string;
|
|
6
|
-
fields: React.ReactNode | React.ReactNode[];
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export const MultistepQuestion = ({
|
|
10
|
-
fields,
|
|
11
|
-
question,
|
|
12
|
-
}: MultistepQuestionProps) => {
|
|
13
|
-
return (
|
|
14
|
-
<Flex
|
|
15
|
-
sx={{
|
|
16
|
-
flexDirection: 'column',
|
|
17
|
-
paddingTop: 'xl',
|
|
18
|
-
paddingX: '2xl',
|
|
19
|
-
}}
|
|
20
|
-
>
|
|
21
|
-
<Text sx={{ textAlign: 'center', fontSize: 'lg', marginBottom: 'xl' }}>
|
|
22
|
-
{question}
|
|
23
|
-
</Text>
|
|
24
|
-
|
|
25
|
-
<Flex sx={{ flexDirection: 'column', gap: 'xl' }}>{fields}</Flex>
|
|
26
|
-
</Flex>
|
|
27
|
-
);
|
|
28
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { MultistepForm, type MultistepFormProps } from './MultistepForm';
|