@saas-ui/forms 1.0.0-rc.9 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
package/src/step-form.tsx CHANGED
@@ -16,7 +16,7 @@ import {
16
16
  } from '@saas-ui/stepper'
17
17
  import { Button, ButtonProps } from '@saas-ui/button'
18
18
 
19
- import { Form, FormProps } from './form'
19
+ import { Form } from './form'
20
20
  import { SubmitButton } from './submit-button'
21
21
 
22
22
  import {
@@ -24,6 +24,7 @@ import {
24
24
  useFormStep,
25
25
  StepFormProvider,
26
26
  UseStepFormProps,
27
+ FormStepSubmitHandler,
27
28
  } from './use-step-form'
28
29
 
29
30
  export interface StepFormProps<TFieldValues extends FieldValues = FieldValues>
@@ -113,11 +114,14 @@ export const FormStepper: React.FC<StepperStepsProps> = (props) => {
113
114
 
114
115
  export interface FormStepProps
115
116
  extends FormStepOptions,
116
- HTMLChakraProps<'div'> {}
117
+ Omit<HTMLChakraProps<'div'>, 'onSubmit'> {
118
+ onSubmit?: FormStepSubmitHandler
119
+ }
117
120
 
118
121
  export const FormStep: React.FC<FormStepProps> = (props) => {
119
- const { name, schema, resolver, children, className, ...rest } = props
120
- const step = useFormStep({ name, schema, resolver })
122
+ const { name, schema, resolver, children, className, onSubmit, ...rest } =
123
+ props
124
+ const step = useFormStep({ name, schema, resolver, onSubmit })
121
125
 
122
126
  const { isActive } = step
123
127
 
@@ -160,11 +164,12 @@ export const NextButton: React.FC<NextButtonProps> = (props) => {
160
164
 
161
165
  return (
162
166
  <SubmitButton
163
- isDisabled={isCompleted}
164
- label={isLastStep || isCompleted ? submitLabel : label}
165
167
  {...rest}
168
+ isDisabled={isCompleted}
166
169
  className={cx('saas-form__next-button', props.className)}
167
- />
170
+ >
171
+ {isLastStep || isCompleted ? submitLabel : label}
172
+ </SubmitButton>
168
173
  )
169
174
  }
170
175
 
@@ -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<SubmitButtonProps, 'button'>(
28
- (props, ref) => {
29
- const { children, disableIfUntouched, disableIfInvalid, ...rest } = props
30
- const { formState } = useFormContext()
31
-
32
- const isDisabled =
33
- (disableIfUntouched && !formState.isDirty) ||
34
- (disableIfInvalid && !formState.isValid)
35
-
36
- return (
37
- <Button
38
- type="submit"
39
- isLoading={formState.isSubmitting}
40
- colorScheme="primary"
41
- ref={ref}
42
- isDisabled={isDisabled}
43
- {...rest}
44
- >
45
- {children}
46
- </Button>
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',
@@ -1,5 +1,5 @@
1
1
  import * as React from 'react'
2
- import { FieldValues, SubmitHandler } from 'react-hook-form'
2
+ import { FieldValues, SubmitHandler, UnpackNestedValue } from 'react-hook-form'
3
3
  import { createContext, MaybeRenderProp } from '@chakra-ui/react-utils'
4
4
  import {
5
5
  useStepper,
@@ -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>
@@ -61,11 +69,12 @@ export function useStepForm<TFieldValues extends FieldValues = FieldValues>(
61
69
 
62
70
  const onSubmitStep: SubmitHandler<TFieldValues> = React.useCallback(
63
71
  async (data) => {
72
+ const step = steps[activeStep]
73
+
64
74
  if (isLastStep) {
65
75
  return props
66
76
  .onSubmit?.(data)
67
77
  .then(() => {
68
- const step = steps[activeStep]
69
78
  updateStep({
70
79
  ...step,
71
80
  isCompleted: true,
@@ -74,9 +83,15 @@ export function useStepForm<TFieldValues extends FieldValues = FieldValues>(
74
83
  .then(nextStep) // Show completed step
75
84
  }
76
85
 
77
- nextStep()
86
+ try {
87
+ await step.onSubmit?.(data, stepper)
88
+
89
+ nextStep()
90
+ } catch (e) {
91
+ // Step submission failed.
92
+ }
78
93
  },
79
- [activeStep, isLastStep]
94
+ [steps, activeStep, isLastStep]
80
95
  )
81
96
 
82
97
  const getFormProps = React.useCallback(() => {
@@ -112,16 +127,17 @@ export interface UseFormStepProps {
112
127
  name: string
113
128
  schema?: any
114
129
  resolver?: any
130
+ onSubmit?: FormStepSubmitHandler
115
131
  }
116
132
 
117
133
  export function useFormStep(props: UseFormStepProps): StepState {
118
- const { name, schema, resolver } = props
134
+ const { name, schema, resolver, onSubmit } = props
119
135
  const step = useStep({ name })
120
136
 
121
137
  const { steps, updateStep } = useStepFormContext()
122
138
 
123
139
  React.useEffect(() => {
124
- updateStep({ name, schema, resolver })
140
+ updateStep({ name, schema, resolver, onSubmit })
125
141
  }, [name, schema])
126
142
 
127
143
  return {