@saas-ui/forms 1.0.0-rc.0 → 1.0.0-rc.11
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +130 -0
- package/README.md +29 -0
- package/ajv/package.json +18 -0
- package/dist/ajv/ajv-resolver.d.ts +11 -0
- package/dist/ajv/ajv-resolver.d.ts.map +1 -0
- package/dist/ajv/index.d.ts +2 -0
- package/dist/ajv/index.d.ts.map +1 -0
- package/dist/ajv/index.js +104 -0
- package/dist/ajv/index.js.map +1 -0
- package/dist/ajv/index.modern.mjs +104 -0
- package/dist/ajv/index.modern.mjs.map +1 -0
- package/dist/array-field.d.ts +14 -3
- package/dist/array-field.d.ts.map +1 -1
- package/dist/auto-form.d.ts +13 -1
- package/dist/auto-form.d.ts.map +1 -1
- package/dist/field.d.ts +82 -27
- package/dist/field.d.ts.map +1 -1
- package/dist/form.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.mjs +1 -1
- package/dist/index.modern.mjs.map +1 -1
- package/dist/step-form.d.ts +4 -4
- package/dist/step-form.d.ts.map +1 -1
- package/dist/submit-button.d.ts +2 -1
- package/dist/submit-button.d.ts.map +1 -1
- package/dist/use-step-form.d.ts +7 -3
- package/dist/use-step-form.d.ts.map +1 -1
- package/dist/yup/index.js +1 -1
- package/dist/yup/index.js.map +1 -1
- package/dist/yup/index.modern.mjs +1 -1
- package/dist/yup/index.modern.mjs.map +1 -1
- package/dist/zod/index.js +1 -1
- package/dist/zod/index.js.map +1 -1
- package/dist/zod/index.modern.mjs +1 -1
- package/dist/zod/index.modern.mjs.map +1 -1
- package/dist/zod/zod-resolver.d.ts +2 -2
- package/dist/zod/zod-resolver.d.ts.map +1 -1
- package/package.json +32 -17
- package/src/array-field.tsx +21 -22
- package/src/auto-form.tsx +22 -3
- package/src/field-resolver.ts +2 -2
- package/src/field.tsx +184 -73
- package/src/form.tsx +0 -1
- package/src/object-field.tsx +3 -3
- package/src/step-form.tsx +27 -20
- package/src/submit-button.tsx +32 -24
- package/src/use-step-form.tsx +27 -12
- package/yup/package.json +2 -2
- package/zod/package.json +4 -4
package/src/step-form.tsx
CHANGED
@@ -2,13 +2,7 @@ import * as React from 'react'
|
|
2
2
|
|
3
3
|
import { FieldValues, UseFormReturn } from 'react-hook-form'
|
4
4
|
|
5
|
-
import {
|
6
|
-
chakra,
|
7
|
-
HTMLChakraProps,
|
8
|
-
useMultiStyleConfig,
|
9
|
-
StylesProvider,
|
10
|
-
SystemStyleObject,
|
11
|
-
} from '@chakra-ui/system'
|
5
|
+
import { chakra, HTMLChakraProps } from '@chakra-ui/system'
|
12
6
|
|
13
7
|
import { callAllHandlers, runIfFn, cx, __DEV__ } from '@chakra-ui/utils'
|
14
8
|
|
@@ -18,10 +12,11 @@ import {
|
|
18
12
|
StepperStepsProps,
|
19
13
|
StepperStep,
|
20
14
|
useStepperContext,
|
15
|
+
StepperContainer,
|
21
16
|
} from '@saas-ui/stepper'
|
22
17
|
import { Button, ButtonProps } from '@saas-ui/button'
|
23
18
|
|
24
|
-
import { Form
|
19
|
+
import { Form } from './form'
|
25
20
|
import { SubmitButton } from './submit-button'
|
26
21
|
|
27
22
|
import {
|
@@ -29,7 +24,7 @@ import {
|
|
29
24
|
useFormStep,
|
30
25
|
StepFormProvider,
|
31
26
|
UseStepFormProps,
|
32
|
-
|
27
|
+
FormStepSubmitHandler,
|
33
28
|
} from './use-step-form'
|
34
29
|
|
35
30
|
export interface StepFormProps<TFieldValues extends FieldValues = FieldValues>
|
@@ -59,7 +54,7 @@ export const StepForm = React.forwardRef(
|
|
59
54
|
)
|
60
55
|
}
|
61
56
|
) as <TFieldValues extends FieldValues>(
|
62
|
-
props:
|
57
|
+
props: StepFormProps<TFieldValues> & {
|
63
58
|
ref?: React.ForwardedRef<UseFormReturn<TFieldValues>>
|
64
59
|
}
|
65
60
|
) => React.ReactElement
|
@@ -80,9 +75,9 @@ export interface FormStepOptions {
|
|
80
75
|
}
|
81
76
|
|
82
77
|
export const FormStepper: React.FC<StepperStepsProps> = (props) => {
|
83
|
-
const
|
78
|
+
const { activeIndex, setIndex } = useStepperContext()
|
84
79
|
|
85
|
-
const { children } = props
|
80
|
+
const { children, orientation } = props
|
86
81
|
|
87
82
|
const elements = React.Children.map(children, (child) => {
|
88
83
|
if (React.isValidElement(child) && child?.type === FormStep) {
|
@@ -100,22 +95,33 @@ export const FormStepper: React.FC<StepperStepsProps> = (props) => {
|
|
100
95
|
return child
|
101
96
|
})
|
102
97
|
|
98
|
+
const onChange = React.useCallback((i: number) => {
|
99
|
+
setIndex(i)
|
100
|
+
}, [])
|
101
|
+
|
103
102
|
return (
|
104
|
-
<
|
103
|
+
<StepperContainer
|
104
|
+
orientation={orientation}
|
105
|
+
step={activeIndex}
|
106
|
+
onChange={onChange}
|
107
|
+
>
|
105
108
|
<StepperSteps mb="4" {...props}>
|
106
109
|
{elements}
|
107
110
|
</StepperSteps>
|
108
|
-
</
|
111
|
+
</StepperContainer>
|
109
112
|
)
|
110
113
|
}
|
111
114
|
|
112
115
|
export interface FormStepProps
|
113
116
|
extends FormStepOptions,
|
114
|
-
HTMLChakraProps<'div'> {
|
117
|
+
Omit<HTMLChakraProps<'div'>, 'onSubmit'> {
|
118
|
+
onSubmit?: FormStepSubmitHandler
|
119
|
+
}
|
115
120
|
|
116
121
|
export const FormStep: React.FC<FormStepProps> = (props) => {
|
117
|
-
const { name, schema, resolver, children, className, ...rest } =
|
118
|
-
|
122
|
+
const { name, schema, resolver, children, className, onSubmit, ...rest } =
|
123
|
+
props
|
124
|
+
const step = useFormStep({ name, schema, resolver, onSubmit })
|
119
125
|
|
120
126
|
const { isActive } = step
|
121
127
|
|
@@ -158,11 +164,12 @@ export const NextButton: React.FC<NextButtonProps> = (props) => {
|
|
158
164
|
|
159
165
|
return (
|
160
166
|
<SubmitButton
|
161
|
-
isDisabled={isCompleted}
|
162
|
-
label={isLastStep || isCompleted ? submitLabel : label}
|
163
167
|
{...rest}
|
168
|
+
isDisabled={isCompleted}
|
164
169
|
className={cx('saas-form__next-button', props.className)}
|
165
|
-
|
170
|
+
>
|
171
|
+
{isLastStep || isCompleted ? submitLabel : label}
|
172
|
+
</SubmitButton>
|
166
173
|
)
|
167
174
|
}
|
168
175
|
|
package/src/submit-button.tsx
CHANGED
@@ -4,7 +4,6 @@ import { useFormContext } from 'react-hook-form'
|
|
4
4
|
|
5
5
|
import { Button, ButtonProps } from '@saas-ui/button'
|
6
6
|
|
7
|
-
import { forwardRef } from '@chakra-ui/system'
|
8
7
|
import { __DEV__ } from '@chakra-ui/utils'
|
9
8
|
|
10
9
|
export interface SubmitButtonProps extends ButtonProps {
|
@@ -24,29 +23,38 @@ export interface SubmitButtonProps extends ButtonProps {
|
|
24
23
|
disableIfInvalid?: boolean
|
25
24
|
}
|
26
25
|
|
27
|
-
export const SubmitButton = forwardRef<
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
26
|
+
export const SubmitButton = React.forwardRef<
|
27
|
+
HTMLButtonElement,
|
28
|
+
SubmitButtonProps
|
29
|
+
>((props, ref) => {
|
30
|
+
const {
|
31
|
+
children,
|
32
|
+
disableIfUntouched,
|
33
|
+
disableIfInvalid,
|
34
|
+
isDisabled: isDisabledProp,
|
35
|
+
isLoading,
|
36
|
+
...rest
|
37
|
+
} = props
|
38
|
+
const { formState } = useFormContext()
|
39
|
+
|
40
|
+
const isDisabled =
|
41
|
+
(disableIfUntouched && !formState.isDirty) ||
|
42
|
+
(disableIfInvalid && !formState.isValid) ||
|
43
|
+
isDisabledProp
|
44
|
+
|
45
|
+
return (
|
46
|
+
<Button
|
47
|
+
{...rest}
|
48
|
+
ref={ref}
|
49
|
+
variant="primary"
|
50
|
+
type="submit"
|
51
|
+
isLoading={formState.isSubmitting || isLoading}
|
52
|
+
isDisabled={isDisabled}
|
53
|
+
>
|
54
|
+
{children}
|
55
|
+
</Button>
|
56
|
+
)
|
57
|
+
})
|
50
58
|
|
51
59
|
SubmitButton.defaultProps = {
|
52
60
|
label: 'Submit',
|
package/src/use-step-form.tsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import * as React from 'react'
|
2
|
-
import { FieldValues, SubmitHandler } from 'react-hook-form'
|
3
|
-
import { createContext } from '@chakra-ui/react-utils'
|
2
|
+
import { FieldValues, SubmitHandler, UnpackNestedValue } from 'react-hook-form'
|
3
|
+
import { createContext, MaybeRenderProp } from '@chakra-ui/react-utils'
|
4
4
|
import {
|
5
5
|
useStepper,
|
6
6
|
useStep,
|
@@ -14,8 +14,16 @@ export interface StepState {
|
|
14
14
|
resolver?: any
|
15
15
|
isActive?: boolean
|
16
16
|
isCompleted?: boolean
|
17
|
+
onSubmit?: FormStepSubmitHandler
|
17
18
|
}
|
18
19
|
|
20
|
+
export type FormStepSubmitHandler<
|
21
|
+
TFieldValues extends FieldValues = FieldValues
|
22
|
+
> = (
|
23
|
+
data: UnpackNestedValue<TFieldValues>,
|
24
|
+
stepper: UseStepperReturn
|
25
|
+
) => Promise<void>
|
26
|
+
|
19
27
|
export interface StepFormContext extends UseStepperReturn {
|
20
28
|
updateStep(state: StepState): void
|
21
29
|
steps: Record<string, StepState>
|
@@ -32,11 +40,9 @@ import { FormProps } from './form'
|
|
32
40
|
|
33
41
|
export interface UseStepFormProps<
|
34
42
|
TFieldValues extends FieldValues = FieldValues
|
35
|
-
> extends UseStepperProps,
|
43
|
+
> extends Omit<UseStepperProps, 'onChange'>,
|
36
44
|
Omit<FormProps<TFieldValues>, 'children'> {
|
37
|
-
children:
|
38
|
-
| React.ReactNode
|
39
|
-
| ((stepper: UseStepFormReturn<TFieldValues>) => React.ReactElement)
|
45
|
+
children: MaybeRenderProp<UseStepFormReturn<TFieldValues>>
|
40
46
|
}
|
41
47
|
|
42
48
|
export interface UseStepFormReturn<
|
@@ -54,7 +60,8 @@ export interface UseStepFormReturn<
|
|
54
60
|
export function useStepForm<TFieldValues extends FieldValues = FieldValues>(
|
55
61
|
props: UseStepFormProps<TFieldValues>
|
56
62
|
): UseStepFormReturn<TFieldValues> {
|
57
|
-
const
|
63
|
+
const { onChange, ...rest } = props
|
64
|
+
const stepper = useStepper(rest)
|
58
65
|
|
59
66
|
const { activeStep, isLastStep, nextStep } = stepper
|
60
67
|
|
@@ -62,11 +69,12 @@ export function useStepForm<TFieldValues extends FieldValues = FieldValues>(
|
|
62
69
|
|
63
70
|
const onSubmitStep: SubmitHandler<TFieldValues> = React.useCallback(
|
64
71
|
async (data) => {
|
72
|
+
const step = steps[activeStep]
|
73
|
+
|
65
74
|
if (isLastStep) {
|
66
75
|
return props
|
67
76
|
.onSubmit?.(data)
|
68
77
|
.then(() => {
|
69
|
-
const step = steps[activeStep]
|
70
78
|
updateStep({
|
71
79
|
...step,
|
72
80
|
isCompleted: true,
|
@@ -75,9 +83,15 @@ export function useStepForm<TFieldValues extends FieldValues = FieldValues>(
|
|
75
83
|
.then(nextStep) // Show completed step
|
76
84
|
}
|
77
85
|
|
78
|
-
|
86
|
+
try {
|
87
|
+
await step.onSubmit?.(data, stepper)
|
88
|
+
|
89
|
+
nextStep()
|
90
|
+
} catch (e) {
|
91
|
+
// Step submission failed.
|
92
|
+
}
|
79
93
|
},
|
80
|
-
[activeStep, isLastStep]
|
94
|
+
[steps, activeStep, isLastStep]
|
81
95
|
)
|
82
96
|
|
83
97
|
const getFormProps = React.useCallback(() => {
|
@@ -113,16 +127,17 @@ export interface UseFormStepProps {
|
|
113
127
|
name: string
|
114
128
|
schema?: any
|
115
129
|
resolver?: any
|
130
|
+
onSubmit?: FormStepSubmitHandler
|
116
131
|
}
|
117
132
|
|
118
133
|
export function useFormStep(props: UseFormStepProps): StepState {
|
119
|
-
const { name, schema, resolver } = props
|
134
|
+
const { name, schema, resolver, onSubmit } = props
|
120
135
|
const step = useStep({ name })
|
121
136
|
|
122
137
|
const { steps, updateStep } = useStepFormContext()
|
123
138
|
|
124
139
|
React.useEffect(() => {
|
125
|
-
updateStep({ name, schema, resolver })
|
140
|
+
updateStep({ name, schema, resolver, onSubmit })
|
126
141
|
}, [name, schema])
|
127
142
|
|
128
143
|
return {
|
package/yup/package.json
CHANGED
@@ -10,8 +10,8 @@
|
|
10
10
|
"author": "Eelco Wiersma <eelco@appulse.nl>",
|
11
11
|
"license": "MIT",
|
12
12
|
"peerDependencies": {
|
13
|
-
"@hookform/resolvers": "^2.
|
14
|
-
"react-hook-form": "^7.
|
13
|
+
"@hookform/resolvers": "^2.9.0",
|
14
|
+
"react-hook-form": "^7.31.3",
|
15
15
|
"yup": "^0.32.11"
|
16
16
|
}
|
17
17
|
}
|
package/zod/package.json
CHANGED
@@ -10,9 +10,9 @@
|
|
10
10
|
"author": "Eelco Wiersma <eelco@appulse.nl>",
|
11
11
|
"license": "MIT",
|
12
12
|
"peerDependencies": {
|
13
|
-
"@chakra-ui/utils": "^2.0.
|
14
|
-
"@hookform/resolvers": "^2.
|
15
|
-
"react-hook-form": "^7.
|
16
|
-
"zod": "^3.
|
13
|
+
"@chakra-ui/utils": "^2.0.2",
|
14
|
+
"@hookform/resolvers": "^2.9.0",
|
15
|
+
"react-hook-form": "^7.31.3",
|
16
|
+
"zod": "^3.17.3"
|
17
17
|
}
|
18
18
|
}
|