@saas-ui/forms 2.0.0-next.9 → 2.0.0-rc.23
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/CHANGELOG.md +139 -0
- package/dist/ajv/index.d.ts +15 -350
- package/dist/ajv/index.js.map +1 -1
- package/dist/ajv/index.mjs.map +1 -1
- package/dist/index.d.ts +182 -144
- package/dist/index.js +202 -147
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +202 -148
- package/dist/index.mjs.map +1 -1
- package/dist/yup/index.d.ts +218 -274
- package/dist/yup/index.js +22 -6
- package/dist/yup/index.js.map +1 -1
- package/dist/yup/index.mjs +20 -5
- package/dist/yup/index.mjs.map +1 -1
- package/dist/zod/index.d.ts +246 -303
- package/dist/zod/index.js +16 -1
- package/dist/zod/index.js.map +1 -1
- package/dist/zod/index.mjs +17 -3
- package/dist/zod/index.mjs.map +1 -1
- package/package.json +20 -6
- package/src/array-field.tsx +6 -3
- package/src/create-form.tsx +33 -19
- package/src/create-step-form.tsx +100 -0
- package/src/form-context.tsx +1 -1
- package/src/form.tsx +12 -10
- package/src/index.ts +20 -6
- package/src/object-field.tsx +22 -5
- package/src/select/select.tsx +2 -2
- package/src/step-form.tsx +52 -70
- package/src/types.ts +8 -3
- package/src/use-step-form.tsx +54 -9
package/src/step-form.tsx
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import * as React from 'react'
|
2
2
|
|
3
|
-
import { FieldValues
|
3
|
+
import { FieldValues } from 'react-hook-form'
|
4
4
|
|
5
5
|
import {
|
6
6
|
chakra,
|
@@ -10,76 +10,48 @@ import {
|
|
10
10
|
ThemingProps,
|
11
11
|
} from '@chakra-ui/react'
|
12
12
|
|
13
|
-
import { callAllHandlers,
|
13
|
+
import { callAllHandlers, cx } from '@chakra-ui/utils'
|
14
14
|
|
15
15
|
import {
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
Steps,
|
17
|
+
StepsItem,
|
18
|
+
StepsItemProps,
|
19
|
+
StepsProps,
|
20
20
|
useStepperContext,
|
21
|
-
StepperContainer,
|
22
|
-
StepperProps,
|
23
21
|
} from '@saas-ui/core'
|
24
22
|
|
25
|
-
import { Form } from './form'
|
26
23
|
import { SubmitButton } from './submit-button'
|
27
24
|
|
28
25
|
import {
|
29
|
-
useStepForm,
|
30
26
|
useFormStep,
|
31
|
-
StepFormProvider,
|
32
27
|
UseStepFormProps,
|
33
28
|
FormStepSubmitHandler,
|
34
29
|
} from './use-step-form'
|
30
|
+
import { FieldProps } from './types'
|
31
|
+
|
32
|
+
export type StepsOptions<TSchema, TName extends string = string> = {
|
33
|
+
/**
|
34
|
+
* The step name
|
35
|
+
*/
|
36
|
+
name: TName
|
37
|
+
/**
|
38
|
+
* Schema
|
39
|
+
*/
|
40
|
+
schema?: TSchema
|
41
|
+
}[]
|
35
42
|
|
36
43
|
export interface StepFormProps<
|
44
|
+
TSteps extends StepsOptions<any> = StepsOptions<any>,
|
37
45
|
TFieldValues extends FieldValues = FieldValues,
|
38
|
-
TContext extends object = object
|
39
|
-
|
46
|
+
TContext extends object = object,
|
47
|
+
TFieldTypes = FieldProps<TFieldValues>
|
48
|
+
> extends UseStepFormProps<TSteps, TFieldValues, TContext, TFieldTypes> {}
|
40
49
|
|
41
|
-
|
42
|
-
* The wrapper component provides context, state, and focus management.
|
43
|
-
*
|
44
|
-
* @see Docs https://saas-ui.dev/docs/components/forms/step-form
|
45
|
-
*/
|
46
|
-
export const StepForm = React.forwardRef(
|
47
|
-
<
|
48
|
-
TFieldValues extends FieldValues = FieldValues,
|
49
|
-
TContext extends object = object
|
50
|
-
>(
|
51
|
-
props: StepFormProps<TFieldValues, TContext>,
|
52
|
-
ref: React.ForwardedRef<HTMLFormElement>
|
53
|
-
) => {
|
54
|
-
const { children, ...rest } = props
|
55
|
-
|
56
|
-
const stepper = useStepForm<TFieldValues>(props)
|
57
|
-
|
58
|
-
const { getFormProps, ...ctx } = stepper
|
59
|
-
|
60
|
-
const context = React.useMemo(() => ctx, [ctx])
|
61
|
-
|
62
|
-
return (
|
63
|
-
<StepperProvider value={context}>
|
64
|
-
<StepFormProvider value={context}>
|
65
|
-
<Form ref={ref} {...rest} {...getFormProps()}>
|
66
|
-
{runIfFn(children, stepper)}
|
67
|
-
</Form>
|
68
|
-
</StepFormProvider>
|
69
|
-
</StepperProvider>
|
70
|
-
)
|
71
|
-
}
|
72
|
-
) as <TFieldValues extends FieldValues>(
|
73
|
-
props: StepFormProps<TFieldValues> & {
|
74
|
-
ref?: React.ForwardedRef<HTMLFormElement>
|
75
|
-
}
|
76
|
-
) => React.ReactElement
|
77
|
-
|
78
|
-
export interface FormStepOptions {
|
50
|
+
export interface FormStepOptions<TName extends string = string> {
|
79
51
|
/**
|
80
52
|
* The step name
|
81
53
|
*/
|
82
|
-
name:
|
54
|
+
name: TName
|
83
55
|
/**
|
84
56
|
* Schema
|
85
57
|
*/
|
@@ -90,9 +62,9 @@ export interface FormStepOptions {
|
|
90
62
|
resolver?: any
|
91
63
|
}
|
92
64
|
|
93
|
-
export interface FormStepperProps
|
94
|
-
|
95
|
-
|
65
|
+
export interface FormStepperProps extends StepsProps, ThemingProps<'Stepper'> {
|
66
|
+
render?: StepsItemProps['render']
|
67
|
+
}
|
96
68
|
|
97
69
|
/**
|
98
70
|
* Renders a stepper that displays progress above the form.
|
@@ -102,7 +74,16 @@ export interface FormStepperProps
|
|
102
74
|
export const FormStepper: React.FC<FormStepperProps> = (props) => {
|
103
75
|
const { activeIndex, setIndex } = useStepperContext()
|
104
76
|
|
105
|
-
const {
|
77
|
+
const {
|
78
|
+
children,
|
79
|
+
orientation,
|
80
|
+
variant,
|
81
|
+
colorScheme,
|
82
|
+
size,
|
83
|
+
onChange: onChangeProp,
|
84
|
+
render,
|
85
|
+
...rest
|
86
|
+
} = props
|
106
87
|
|
107
88
|
const elements = React.Children.map(children, (child) => {
|
108
89
|
if (
|
@@ -111,14 +92,15 @@ export const FormStepper: React.FC<FormStepperProps> = (props) => {
|
|
111
92
|
) {
|
112
93
|
const { isCompleted } = useFormStep(child.props) // Register this step
|
113
94
|
return (
|
114
|
-
<
|
95
|
+
<StepsItem
|
96
|
+
render={render}
|
115
97
|
name={child.props.name}
|
116
98
|
title={child.props.title}
|
117
99
|
isCompleted={isCompleted}
|
118
100
|
{...rest}
|
119
101
|
>
|
120
102
|
{child.props.children}
|
121
|
-
</
|
103
|
+
</StepsItem>
|
122
104
|
)
|
123
105
|
}
|
124
106
|
return child
|
@@ -126,10 +108,11 @@ export const FormStepper: React.FC<FormStepperProps> = (props) => {
|
|
126
108
|
|
127
109
|
const onChange = React.useCallback((i: number) => {
|
128
110
|
setIndex(i)
|
111
|
+
onChangeProp?.(i)
|
129
112
|
}, [])
|
130
113
|
|
131
114
|
return (
|
132
|
-
<
|
115
|
+
<Steps
|
133
116
|
orientation={orientation}
|
134
117
|
step={activeIndex}
|
135
118
|
variant={variant}
|
@@ -137,15 +120,13 @@ export const FormStepper: React.FC<FormStepperProps> = (props) => {
|
|
137
120
|
size={size}
|
138
121
|
onChange={onChange}
|
139
122
|
>
|
140
|
-
|
141
|
-
|
142
|
-
</StepperSteps>
|
143
|
-
</StepperContainer>
|
123
|
+
{elements}
|
124
|
+
</Steps>
|
144
125
|
)
|
145
126
|
}
|
146
127
|
|
147
|
-
export interface FormStepProps
|
148
|
-
extends FormStepOptions
|
128
|
+
export interface FormStepProps<TName extends string = string>
|
129
|
+
extends FormStepOptions<TName>,
|
149
130
|
Omit<HTMLChakraProps<'div'>, 'onSubmit'> {
|
150
131
|
onSubmit?: FormStepSubmitHandler
|
151
132
|
}
|
@@ -154,10 +135,11 @@ export interface FormStepProps
|
|
154
135
|
*
|
155
136
|
* @see Docs https://saas-ui.dev/docs/components/forms/step-form
|
156
137
|
*/
|
157
|
-
export const FormStep
|
158
|
-
|
159
|
-
|
160
|
-
const
|
138
|
+
export const FormStep = <TName extends string = string>(
|
139
|
+
props: FormStepProps<TName>
|
140
|
+
) => {
|
141
|
+
const { name, children, className, onSubmit, ...rest } = props
|
142
|
+
const step = useFormStep({ name, onSubmit })
|
161
143
|
|
162
144
|
const { isActive } = step
|
163
145
|
|
@@ -181,7 +163,7 @@ export const PrevButton: React.FC<ButtonProps> = (props) => {
|
|
181
163
|
return (
|
182
164
|
<Button
|
183
165
|
isDisabled={isFirstStep || isCompleted}
|
184
|
-
|
166
|
+
children="Back"
|
185
167
|
{...props}
|
186
168
|
className={cx('sui-form__prev-button', props.className)}
|
187
169
|
onClick={callAllHandlers(props.onClick, prevStep)}
|
package/src/types.ts
CHANGED
@@ -133,12 +133,17 @@ export type FieldOverrides<
|
|
133
133
|
|
134
134
|
export type WithFields<
|
135
135
|
TFormProps extends FormProps<any, any, any, any>,
|
136
|
-
FieldDefs
|
137
|
-
|
136
|
+
FieldDefs,
|
137
|
+
ExtraOverrides = object
|
138
|
+
> = TFormProps extends FormProps<
|
139
|
+
infer TSchema,
|
140
|
+
infer TFieldValues,
|
141
|
+
infer TContext
|
142
|
+
>
|
138
143
|
? Omit<TFormProps, 'children' | 'fields'> & {
|
139
144
|
children?: FormChildren<FieldDefs, TFieldValues, TContext>
|
140
145
|
fields?: FieldOverrides<FieldDefs, TFieldValues> & {
|
141
146
|
submit?: SubmitButtonProps
|
142
|
-
}
|
147
|
+
} & ExtraOverrides
|
143
148
|
}
|
144
149
|
: never
|
package/src/use-step-form.tsx
CHANGED
@@ -34,12 +34,43 @@ export const [StepFormProvider, useStepFormContext] =
|
|
34
34
|
})
|
35
35
|
|
36
36
|
import { FormProps } from './form'
|
37
|
+
import { FormStepProps, StepsOptions } from './step-form'
|
38
|
+
import { FieldProps } from './types'
|
39
|
+
import { FocusableElement } from '@chakra-ui/utils'
|
40
|
+
import { DisplayIfProps } from './display-if'
|
41
|
+
import { ArrayFieldProps } from './array-field'
|
42
|
+
import { UseArrayFieldReturn } from './use-array-field'
|
43
|
+
import { ObjectFieldProps } from './object-field'
|
44
|
+
|
45
|
+
type StepName<T extends { [k: number]: { readonly name: string } }> =
|
46
|
+
T[number]['name']
|
47
|
+
|
48
|
+
interface StepFormRenderContext<
|
49
|
+
TSteps extends StepsOptions<any> = StepsOptions<any>,
|
50
|
+
TFieldValues extends FieldValues = FieldValues,
|
51
|
+
TContext extends object = object,
|
52
|
+
TFieldTypes = FieldProps<TFieldValues>
|
53
|
+
> extends UseStepFormReturn<TFieldValues> {
|
54
|
+
Field: React.FC<TFieldTypes & React.RefAttributes<FocusableElement>>
|
55
|
+
FormStep: React.FC<FormStepProps<StepName<TSteps>>>
|
56
|
+
DisplayIf: React.FC<DisplayIfProps<TFieldValues>>
|
57
|
+
ArrayField: React.FC<
|
58
|
+
ArrayFieldProps<TFieldValues> & React.RefAttributes<UseArrayFieldReturn>
|
59
|
+
>
|
60
|
+
ObjectField: React.FC<ObjectFieldProps<TFieldValues>>
|
61
|
+
}
|
37
62
|
|
38
63
|
export interface UseStepFormProps<
|
39
|
-
|
64
|
+
TSteps extends StepsOptions<any> = StepsOptions<any>,
|
65
|
+
TFieldValues extends FieldValues = FieldValues,
|
66
|
+
TContext extends object = object,
|
67
|
+
TFieldTypes = FieldProps<TFieldValues>
|
40
68
|
> extends Omit<UseStepperProps, 'onChange'>,
|
41
|
-
Omit<FormProps<TFieldValues>, 'children'> {
|
42
|
-
|
69
|
+
Omit<FormProps<any, TFieldValues, TContext, TFieldTypes>, 'children'> {
|
70
|
+
steps?: TSteps
|
71
|
+
children: MaybeRenderProp<
|
72
|
+
StepFormRenderContext<TSteps, TFieldValues, TContext, TFieldTypes>
|
73
|
+
>
|
43
74
|
}
|
44
75
|
|
45
76
|
export interface UseStepFormReturn<
|
@@ -54,12 +85,19 @@ export interface UseStepFormReturn<
|
|
54
85
|
steps: Record<string, any>
|
55
86
|
}
|
56
87
|
|
57
|
-
export function useStepForm<
|
58
|
-
|
88
|
+
export function useStepForm<
|
89
|
+
TSteps extends StepsOptions<any> = StepsOptions<any>,
|
90
|
+
TFieldValues extends FieldValues = FieldValues,
|
91
|
+
TContext extends object = object,
|
92
|
+
TFieldTypes = FieldProps<TFieldValues>
|
93
|
+
>(
|
94
|
+
props: UseStepFormProps<TSteps, TFieldValues, TContext, TFieldTypes>
|
59
95
|
): UseStepFormReturn<TFieldValues> {
|
60
|
-
const { onChange, ...rest } = props
|
96
|
+
const { onChange, steps: stepsOptions, resolver, ...rest } = props
|
61
97
|
const stepper = useStepper(rest)
|
62
98
|
|
99
|
+
const [options, setOptions] = React.useState<TSteps | undefined>(stepsOptions)
|
100
|
+
|
63
101
|
const { activeStep, isLastStep, nextStep } = stepper
|
64
102
|
|
65
103
|
const [steps, updateSteps] = React.useState<Record<string, StepState>>({})
|
@@ -93,23 +131,30 @@ export function useStepForm<TFieldValues extends FieldValues = FieldValues>(
|
|
93
131
|
|
94
132
|
const getFormProps = React.useCallback(() => {
|
95
133
|
const step = steps[activeStep]
|
134
|
+
|
96
135
|
return {
|
97
136
|
onSubmit: onSubmitStep,
|
98
137
|
schema: step?.schema,
|
99
|
-
resolver: step?.
|
138
|
+
resolver: step?.schema
|
139
|
+
? /* @todo fix resolver type */ (resolver as any)?.(step.schema)
|
140
|
+
: undefined,
|
100
141
|
}
|
101
142
|
}, [steps, onSubmitStep, activeStep])
|
102
143
|
|
103
144
|
const updateStep = React.useCallback(
|
104
145
|
(step: StepState) => {
|
146
|
+
const stepOptions = options?.find((s) => s.name === step.name)
|
105
147
|
updateSteps((steps) => {
|
106
148
|
return {
|
107
149
|
...steps,
|
108
|
-
[step.name]:
|
150
|
+
[step.name]: {
|
151
|
+
...step,
|
152
|
+
schema: stepOptions?.schema,
|
153
|
+
},
|
109
154
|
}
|
110
155
|
})
|
111
156
|
},
|
112
|
-
[steps]
|
157
|
+
[steps, options]
|
113
158
|
)
|
114
159
|
|
115
160
|
return {
|