@saas-ui/forms 0.3.3 → 0.5.0
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 +35 -0
- package/dist/display-field.d.ts +3 -0
- package/dist/display-field.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +1 -1
- package/dist/index.modern.js.map +1 -1
- package/dist/step-form.d.ts +32 -0
- package/dist/step-form.d.ts.map +1 -0
- package/dist/use-step-form.d.ts +44 -0
- package/dist/use-step-form.d.ts.map +1 -0
- package/package.json +9 -8
- package/src/display-field.tsx +8 -3
- package/src/index.ts +2 -0
- package/src/step-form.tsx +165 -0
- package/src/use-step-form.tsx +118 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import { FieldValues, UseFormReturn } from 'react-hook-form';
|
3
|
+
import { HTMLChakraProps } from '@chakra-ui/system';
|
4
|
+
import { StepperStepsProps } from '@saas-ui/stepper';
|
5
|
+
import { ButtonProps } from '@saas-ui/button';
|
6
|
+
import { FormProps } from '.';
|
7
|
+
import { UseStepFormProps } from './use-step-form';
|
8
|
+
export interface StepFormProps<TFieldValues extends FieldValues = FieldValues> extends UseStepFormProps<TFieldValues>, FormProps<TFieldValues> {
|
9
|
+
}
|
10
|
+
export declare const StepForm: <TFieldValues extends FieldValues>(props: FormProps<TFieldValues> & {
|
11
|
+
ref?: React.ForwardedRef<UseFormReturn<TFieldValues, object>> | undefined;
|
12
|
+
}) => React.ReactElement;
|
13
|
+
export interface FormStepOptions {
|
14
|
+
/**
|
15
|
+
* The step name
|
16
|
+
*/
|
17
|
+
name: string;
|
18
|
+
/**
|
19
|
+
* Schema
|
20
|
+
*/
|
21
|
+
schema?: any;
|
22
|
+
}
|
23
|
+
export declare const FormStepper: React.FC<StepperStepsProps>;
|
24
|
+
export interface FormStepProps extends FormStepOptions, HTMLChakraProps<'div'> {
|
25
|
+
}
|
26
|
+
export declare const FormStep: React.FC<FormStepProps>;
|
27
|
+
export declare const PrevButton: React.FC<ButtonProps>;
|
28
|
+
export interface NextButtonProps extends ButtonProps {
|
29
|
+
submitLabel?: string;
|
30
|
+
}
|
31
|
+
export declare const NextButton: React.FC<NextButtonProps>;
|
32
|
+
//# sourceMappingURL=step-form.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"step-form.d.ts","sourceRoot":"","sources":["../src/step-form.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE5D,OAAO,EAEL,eAAe,EAGhB,MAAM,mBAAmB,CAAA;AAI1B,OAAO,EAGL,iBAAiB,EAGlB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAU,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAErD,OAAO,EAAQ,SAAS,EAAgB,MAAM,GAAG,CAAA;AAEjD,OAAO,EAIL,gBAAgB,EACjB,MAAM,iBAAiB,CAAA;AAExB,MAAM,WAAW,aAAa,CAAC,YAAY,SAAS,WAAW,GAAG,WAAW,CAC3E,SAAQ,gBAAgB,CAAC,YAAY,CAAC,EACpC,SAAS,CAAC,YAAY,CAAC;CAAG;AAE9B,eAAO,MAAM,QAAQ;;MA2BhB,MAAM,YAAY,CAAA;AAEvB,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;OAEG;IACH,MAAM,CAAC,EAAE,GAAG,CAAA;CACb;AAED,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA4BnD,CAAA;AAED,MAAM,WAAW,aACf,SAAQ,eAAe,EACrB,eAAe,CAAC,KAAK,CAAC;CAAG;AAE7B,eAAO,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CAW5C,CAAA;AAMD,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,WAAW,CAY5C,CAAA;AAMD,MAAM,WAAW,eAAgB,SAAQ,WAAW;IAClD,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CAYhD,CAAA"}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import * as React from 'react';
|
2
|
+
import { FieldValues, SubmitHandler } from 'react-hook-form';
|
3
|
+
import { UseStepperProps, UseStepperReturn } from '@saas-ui/stepper';
|
4
|
+
export interface StepState {
|
5
|
+
name: string;
|
6
|
+
schema?: any;
|
7
|
+
isActive?: boolean;
|
8
|
+
isCompleted?: boolean;
|
9
|
+
}
|
10
|
+
export interface StepFormContext extends UseStepperReturn {
|
11
|
+
updateStep(state: StepState): void;
|
12
|
+
steps: Record<string, StepState>;
|
13
|
+
}
|
14
|
+
export declare const StepFormProvider: React.Provider<StepFormContext>, useStepFormContext: () => StepFormContext;
|
15
|
+
import { FormProps } from './form';
|
16
|
+
export interface UseStepFormProps<TFieldValues extends FieldValues = FieldValues> extends UseStepperProps, FormProps<TFieldValues> {
|
17
|
+
}
|
18
|
+
export declare function useStepForm<TFieldValues extends FieldValues = FieldValues>(props: UseStepFormProps<TFieldValues>): {
|
19
|
+
stepsRef: React.MutableRefObject<string[]>;
|
20
|
+
activeStep: string;
|
21
|
+
activeIndex: number;
|
22
|
+
isFirstStep: boolean;
|
23
|
+
isLastStep: boolean;
|
24
|
+
isCompleted: boolean;
|
25
|
+
setIndex: React.Dispatch<React.SetStateAction<number>>;
|
26
|
+
setStep: (name: string) => void;
|
27
|
+
nextStep: () => void;
|
28
|
+
prevStep: () => void;
|
29
|
+
registerStep: (name: string) => void;
|
30
|
+
unregisterStep: (name: string) => void;
|
31
|
+
getFormProps: (props: any) => {
|
32
|
+
onSubmit: SubmitHandler<TFieldValues>;
|
33
|
+
schema: any;
|
34
|
+
};
|
35
|
+
updateStep: (step: any) => void;
|
36
|
+
steps: {};
|
37
|
+
};
|
38
|
+
export declare type UseStepFormReturn = ReturnType<typeof useStepForm>;
|
39
|
+
export interface UseFormStepProps {
|
40
|
+
name: string;
|
41
|
+
schema?: any;
|
42
|
+
}
|
43
|
+
export declare function useFormStep(props: UseFormStepProps): StepState;
|
44
|
+
//# sourceMappingURL=use-step-form.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"use-step-form.d.ts","sourceRoot":"","sources":["../src/use-step-form.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE5D,OAAO,EAGL,eAAe,EACf,gBAAgB,EACjB,MAAM,kBAAkB,CAAA;AAEzB,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,GAAG,CAAA;IACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;IAClC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;CACjC;AAED,eAAO,MAAO,gBAAgB,mCAAE,kBAAkB,uBAK9C,CAAA;AAEJ,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAElC,MAAM,WAAW,gBAAgB,CAC/B,YAAY,SAAS,WAAW,GAAG,WAAW,CAC9C,SAAQ,eAAe,EACrB,SAAS,CAAC,YAAY,CAAC;CAAG;AAE9B,wBAAgB,WAAW,CAAC,YAAY,SAAS,WAAW,GAAG,WAAW,EACxE,KAAK,EAAE,gBAAgB,CAAC,YAAY,CAAC;;;;;;;;;;;;;;;;;;;EAyDtC;AAED,oBAAY,iBAAiB,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAA;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,CAAC,EAAE,GAAG,CAAA;CACb;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAc9D"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@saas-ui/forms",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.5.0",
|
4
4
|
"description": "Theme and components agnostic SaasProvider",
|
5
5
|
"source": "src/index.ts",
|
6
6
|
"exports": {
|
@@ -65,13 +65,14 @@
|
|
65
65
|
"@chakra-ui/icons": "^1.1.1",
|
66
66
|
"@chakra-ui/react-utils": "^1.2.1",
|
67
67
|
"@hookform/resolvers": "^2.8.3",
|
68
|
-
"@saas-ui/button": "0.
|
69
|
-
"@saas-ui/input-right-button": "0.
|
70
|
-
"@saas-ui/number-input": "0.
|
71
|
-
"@saas-ui/password-input": "0.
|
72
|
-
"@saas-ui/pin-input": "0.
|
73
|
-
"@saas-ui/radio": "0.
|
74
|
-
"@saas-ui/
|
68
|
+
"@saas-ui/button": "0.3.0",
|
69
|
+
"@saas-ui/input-right-button": "0.3.0",
|
70
|
+
"@saas-ui/number-input": "0.3.0",
|
71
|
+
"@saas-ui/password-input": "0.3.0",
|
72
|
+
"@saas-ui/pin-input": "0.3.0",
|
73
|
+
"@saas-ui/radio": "0.3.0",
|
74
|
+
"@saas-ui/react-utils": "0.1.0",
|
75
|
+
"@saas-ui/select": "0.3.0",
|
75
76
|
"react-hook-form": "^7.22.0"
|
76
77
|
},
|
77
78
|
"peerDependencies": {
|
package/src/display-field.tsx
CHANGED
@@ -20,12 +20,17 @@ export const DisplayField: React.FC<DisplayFieldProps> = ({
|
|
20
20
|
placeholder,
|
21
21
|
...props
|
22
22
|
}) => {
|
23
|
-
const { getValues } = useFormContext()
|
24
|
-
|
25
23
|
return (
|
26
24
|
<FormControl {...props}>
|
27
25
|
{label ? <FormLabel htmlFor={name}>{label}</FormLabel> : null}
|
28
|
-
<Text fontSize="md">
|
26
|
+
<Text fontSize="md">
|
27
|
+
<FormValue name={name} />
|
28
|
+
</Text>
|
29
29
|
</FormControl>
|
30
30
|
)
|
31
31
|
}
|
32
|
+
|
33
|
+
export const FormValue: React.FC<{ name: string }> = ({ name }) => {
|
34
|
+
const { getValues } = useFormContext()
|
35
|
+
return getValues(name) || null
|
36
|
+
}
|
package/src/index.ts
CHANGED
@@ -0,0 +1,165 @@
|
|
1
|
+
import * as React from 'react'
|
2
|
+
|
3
|
+
import { FieldValues, UseFormReturn } from 'react-hook-form'
|
4
|
+
|
5
|
+
import {
|
6
|
+
chakra,
|
7
|
+
HTMLChakraProps,
|
8
|
+
useMultiStyleConfig,
|
9
|
+
StylesProvider,
|
10
|
+
} from '@chakra-ui/system'
|
11
|
+
|
12
|
+
import { callAllHandlers, runIfFn, cx, __DEV__ } from '@chakra-ui/utils'
|
13
|
+
|
14
|
+
import {
|
15
|
+
StepperProvider,
|
16
|
+
StepperSteps,
|
17
|
+
StepperStepsProps,
|
18
|
+
StepperStep,
|
19
|
+
useStepperContext,
|
20
|
+
} from '@saas-ui/stepper'
|
21
|
+
import { Button, ButtonProps } from '@saas-ui/button'
|
22
|
+
|
23
|
+
import { Form, FormProps, SubmitButton } from '.'
|
24
|
+
|
25
|
+
import {
|
26
|
+
useStepForm,
|
27
|
+
useFormStep,
|
28
|
+
StepFormProvider,
|
29
|
+
UseStepFormProps,
|
30
|
+
} from './use-step-form'
|
31
|
+
|
32
|
+
export interface StepFormProps<TFieldValues extends FieldValues = FieldValues>
|
33
|
+
extends UseStepFormProps<TFieldValues>,
|
34
|
+
FormProps<TFieldValues> {}
|
35
|
+
|
36
|
+
export const StepForm = React.forwardRef(
|
37
|
+
<TFieldValues extends FieldValues = FieldValues>(
|
38
|
+
props: StepFormProps<TFieldValues>,
|
39
|
+
ref: React.ForwardedRef<UseFormReturn<TFieldValues>>
|
40
|
+
) => {
|
41
|
+
const { children, onSubmit, ...rest } = props
|
42
|
+
|
43
|
+
const stepper = useStepForm<TFieldValues>(props)
|
44
|
+
|
45
|
+
const { getFormProps, ...ctx } = stepper
|
46
|
+
|
47
|
+
const context = React.useMemo(() => ctx, [ctx])
|
48
|
+
|
49
|
+
return (
|
50
|
+
<StepperProvider value={context}>
|
51
|
+
<StepFormProvider value={context}>
|
52
|
+
<Form ref={ref} {...rest} {...getFormProps(props)}>
|
53
|
+
{runIfFn(children, stepper)}
|
54
|
+
</Form>
|
55
|
+
</StepFormProvider>
|
56
|
+
</StepperProvider>
|
57
|
+
)
|
58
|
+
}
|
59
|
+
) as <TFieldValues extends FieldValues>(
|
60
|
+
props: FormProps<TFieldValues> & {
|
61
|
+
ref?: React.ForwardedRef<UseFormReturn<TFieldValues>>
|
62
|
+
}
|
63
|
+
) => React.ReactElement
|
64
|
+
|
65
|
+
export interface FormStepOptions {
|
66
|
+
/**
|
67
|
+
* The step name
|
68
|
+
*/
|
69
|
+
name: string
|
70
|
+
/**
|
71
|
+
* Schema
|
72
|
+
*/
|
73
|
+
schema?: any
|
74
|
+
}
|
75
|
+
|
76
|
+
export const FormStepper: React.FC<StepperStepsProps> = (props) => {
|
77
|
+
const styles = useMultiStyleConfig('Stepper', props)
|
78
|
+
|
79
|
+
const { children } = props
|
80
|
+
|
81
|
+
const elements = React.Children.map(children, (child) => {
|
82
|
+
if (React.isValidElement(child) && child?.type === FormStep) {
|
83
|
+
const { isCompleted } = useFormStep(child.props) // Register this step
|
84
|
+
return (
|
85
|
+
<StepperStep
|
86
|
+
name={child.props.name}
|
87
|
+
title={child.props.title}
|
88
|
+
isCompleted={isCompleted}
|
89
|
+
>
|
90
|
+
{child.props.children}
|
91
|
+
</StepperStep>
|
92
|
+
)
|
93
|
+
}
|
94
|
+
return child
|
95
|
+
})
|
96
|
+
|
97
|
+
return (
|
98
|
+
<StylesProvider value={styles}>
|
99
|
+
<StepperSteps mb="4" {...props}>
|
100
|
+
{elements}
|
101
|
+
</StepperSteps>
|
102
|
+
</StylesProvider>
|
103
|
+
)
|
104
|
+
}
|
105
|
+
|
106
|
+
export interface FormStepProps
|
107
|
+
extends FormStepOptions,
|
108
|
+
HTMLChakraProps<'div'> {}
|
109
|
+
|
110
|
+
export const FormStep: React.FC<FormStepProps> = (props) => {
|
111
|
+
const { name, schema, children, className, ...rest } = props
|
112
|
+
const step = useFormStep({ name, schema })
|
113
|
+
|
114
|
+
const { isActive } = step
|
115
|
+
|
116
|
+
return isActive ? (
|
117
|
+
<chakra.div {...rest} className={cx('saas-form__step', className)}>
|
118
|
+
{children}
|
119
|
+
</chakra.div>
|
120
|
+
) : null
|
121
|
+
}
|
122
|
+
|
123
|
+
if (__DEV__) {
|
124
|
+
FormStep.displayName = 'FormStep'
|
125
|
+
}
|
126
|
+
|
127
|
+
export const PrevButton: React.FC<ButtonProps> = (props) => {
|
128
|
+
const { isFirstStep, isCompleted, prevStep } = useStepperContext()
|
129
|
+
|
130
|
+
return (
|
131
|
+
<Button
|
132
|
+
isDisabled={isFirstStep || isCompleted}
|
133
|
+
label="Back"
|
134
|
+
{...props}
|
135
|
+
className={cx('saas-form__prev-button', props.className)}
|
136
|
+
onClick={callAllHandlers(props.onClick, prevStep)}
|
137
|
+
/>
|
138
|
+
)
|
139
|
+
}
|
140
|
+
|
141
|
+
if (__DEV__) {
|
142
|
+
PrevButton.displayName = 'PrevButton'
|
143
|
+
}
|
144
|
+
|
145
|
+
export interface NextButtonProps extends ButtonProps {
|
146
|
+
submitLabel?: string
|
147
|
+
}
|
148
|
+
|
149
|
+
export const NextButton: React.FC<NextButtonProps> = (props) => {
|
150
|
+
const { label = 'Next', submitLabel = 'Complete', ...rest } = props
|
151
|
+
const { isLastStep, isCompleted } = useStepperContext()
|
152
|
+
|
153
|
+
return (
|
154
|
+
<SubmitButton
|
155
|
+
isDisabled={isCompleted}
|
156
|
+
label={isLastStep || isCompleted ? submitLabel : label}
|
157
|
+
{...rest}
|
158
|
+
className={cx('saas-form__next-button', props.className)}
|
159
|
+
/>
|
160
|
+
)
|
161
|
+
}
|
162
|
+
|
163
|
+
if (__DEV__) {
|
164
|
+
NextButton.displayName = 'NextButton'
|
165
|
+
}
|
@@ -0,0 +1,118 @@
|
|
1
|
+
import * as React from 'react'
|
2
|
+
import { FieldValues, SubmitHandler } from 'react-hook-form'
|
3
|
+
import { createContext } from '@chakra-ui/react-utils'
|
4
|
+
import {
|
5
|
+
useStepper,
|
6
|
+
useStep,
|
7
|
+
UseStepperProps,
|
8
|
+
UseStepperReturn,
|
9
|
+
} from '@saas-ui/stepper'
|
10
|
+
|
11
|
+
export interface StepState {
|
12
|
+
name: string
|
13
|
+
schema?: any
|
14
|
+
isActive?: boolean
|
15
|
+
isCompleted?: boolean
|
16
|
+
}
|
17
|
+
|
18
|
+
export interface StepFormContext extends UseStepperReturn {
|
19
|
+
updateStep(state: StepState): void
|
20
|
+
steps: Record<string, StepState>
|
21
|
+
}
|
22
|
+
|
23
|
+
export const [StepFormProvider, useStepFormContext] =
|
24
|
+
createContext<StepFormContext>({
|
25
|
+
name: 'StepFormContext',
|
26
|
+
errorMessage:
|
27
|
+
'useStepFormContext: `context` is undefined. Seems you forgot to wrap step form components in `<StepForm />`',
|
28
|
+
})
|
29
|
+
|
30
|
+
import { FormProps } from './form'
|
31
|
+
|
32
|
+
export interface UseStepFormProps<
|
33
|
+
TFieldValues extends FieldValues = FieldValues
|
34
|
+
> extends UseStepperProps,
|
35
|
+
FormProps<TFieldValues> {}
|
36
|
+
|
37
|
+
export function useStepForm<TFieldValues extends FieldValues = FieldValues>(
|
38
|
+
props: UseStepFormProps<TFieldValues>
|
39
|
+
) {
|
40
|
+
const stepper = useStepper(props)
|
41
|
+
|
42
|
+
const { activeStep, isLastStep, nextStep } = stepper
|
43
|
+
|
44
|
+
const [steps, updateSteps] = React.useState({})
|
45
|
+
|
46
|
+
const onSubmitStep: SubmitHandler<TFieldValues> = React.useCallback(
|
47
|
+
async (data) => {
|
48
|
+
if (isLastStep) {
|
49
|
+
return props
|
50
|
+
.onSubmit?.(data)
|
51
|
+
.then(() => {
|
52
|
+
const step = steps[activeStep]
|
53
|
+
updateStep({
|
54
|
+
...step,
|
55
|
+
isCompleted: true,
|
56
|
+
})
|
57
|
+
})
|
58
|
+
.then(nextStep) // Show completed step
|
59
|
+
}
|
60
|
+
|
61
|
+
nextStep()
|
62
|
+
},
|
63
|
+
[activeStep, isLastStep]
|
64
|
+
)
|
65
|
+
|
66
|
+
const getFormProps = React.useCallback(
|
67
|
+
(props) => {
|
68
|
+
const step = steps[activeStep]
|
69
|
+
return {
|
70
|
+
onSubmit: onSubmitStep,
|
71
|
+
schema: step?.schema,
|
72
|
+
}
|
73
|
+
},
|
74
|
+
[steps, onSubmitStep, activeStep]
|
75
|
+
)
|
76
|
+
|
77
|
+
const updateStep = React.useCallback(
|
78
|
+
(step) => {
|
79
|
+
updateSteps((steps) => {
|
80
|
+
return {
|
81
|
+
...steps,
|
82
|
+
[step.name]: step,
|
83
|
+
}
|
84
|
+
})
|
85
|
+
},
|
86
|
+
[steps]
|
87
|
+
)
|
88
|
+
|
89
|
+
return {
|
90
|
+
getFormProps,
|
91
|
+
updateStep,
|
92
|
+
steps,
|
93
|
+
...stepper,
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
export type UseStepFormReturn = ReturnType<typeof useStepForm>
|
98
|
+
|
99
|
+
export interface UseFormStepProps {
|
100
|
+
name: string
|
101
|
+
schema?: any
|
102
|
+
}
|
103
|
+
|
104
|
+
export function useFormStep(props: UseFormStepProps): StepState {
|
105
|
+
const { name, schema } = props
|
106
|
+
const step = useStep({ name })
|
107
|
+
|
108
|
+
const { steps, updateStep } = useStepFormContext()
|
109
|
+
|
110
|
+
React.useEffect(() => {
|
111
|
+
updateStep({ name, schema })
|
112
|
+
}, [name, schema])
|
113
|
+
|
114
|
+
return {
|
115
|
+
...step,
|
116
|
+
...(steps[name] || {}),
|
117
|
+
}
|
118
|
+
}
|