@saas-ui/forms 1.0.0-rc.0 → 1.0.0-rc.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 (50) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +29 -0
  3. package/ajv/package.json +18 -0
  4. package/dist/ajv/ajv-resolver.d.ts +11 -0
  5. package/dist/ajv/ajv-resolver.d.ts.map +1 -0
  6. package/dist/ajv/index.d.ts +2 -0
  7. package/dist/ajv/index.d.ts.map +1 -0
  8. package/dist/ajv/index.js +104 -0
  9. package/dist/ajv/index.js.map +1 -0
  10. package/dist/ajv/index.modern.mjs +104 -0
  11. package/dist/ajv/index.modern.mjs.map +1 -0
  12. package/dist/array-field.d.ts +14 -3
  13. package/dist/array-field.d.ts.map +1 -1
  14. package/dist/auto-form.d.ts +13 -1
  15. package/dist/auto-form.d.ts.map +1 -1
  16. package/dist/field.d.ts +82 -27
  17. package/dist/field.d.ts.map +1 -1
  18. package/dist/form.d.ts.map +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/index.modern.mjs +1 -1
  22. package/dist/index.modern.mjs.map +1 -1
  23. package/dist/step-form.d.ts +4 -4
  24. package/dist/step-form.d.ts.map +1 -1
  25. package/dist/submit-button.d.ts +2 -1
  26. package/dist/submit-button.d.ts.map +1 -1
  27. package/dist/use-step-form.d.ts +7 -3
  28. package/dist/use-step-form.d.ts.map +1 -1
  29. package/dist/yup/index.js +1 -1
  30. package/dist/yup/index.js.map +1 -1
  31. package/dist/yup/index.modern.mjs +1 -1
  32. package/dist/yup/index.modern.mjs.map +1 -1
  33. package/dist/zod/index.js +1 -1
  34. package/dist/zod/index.js.map +1 -1
  35. package/dist/zod/index.modern.mjs +1 -1
  36. package/dist/zod/index.modern.mjs.map +1 -1
  37. package/dist/zod/zod-resolver.d.ts +2 -2
  38. package/dist/zod/zod-resolver.d.ts.map +1 -1
  39. package/package.json +32 -17
  40. package/src/array-field.tsx +21 -22
  41. package/src/auto-form.tsx +22 -3
  42. package/src/field-resolver.ts +2 -2
  43. package/src/field.tsx +184 -73
  44. package/src/form.tsx +0 -1
  45. package/src/object-field.tsx +3 -3
  46. package/src/step-form.tsx +27 -20
  47. package/src/submit-button.tsx +32 -24
  48. package/src/use-step-form.tsx +27 -12
  49. package/yup/package.json +2 -2
  50. 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, FormProps } from './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
- UseStepFormReturn,
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: FormProps<TFieldValues> & {
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 styles = useMultiStyleConfig('Stepper', props)
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
- <StylesProvider value={styles}>
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
- </StylesProvider>
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 } = props
118
- 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 })
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
 
@@ -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
- isPrimary
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,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 stepper = useStepper(props)
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
- nextStep()
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.8.3",
14
- "react-hook-form": "^7.22.0",
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.0",
14
- "@hookform/resolvers": "^2.8.3",
15
- "react-hook-form": "^7.22.0",
16
- "zod": "^3.14.4"
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
  }