Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate from react-albus to react-step-wizard #32

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"peerDependencies": {
"formik": "^2.0.1-rc.12",
"react": "^16.8.6",
"react-albus": "^2.0.0",
"yup": "^0.27.0"
},
"devDependencies": {
Expand All @@ -34,13 +33,13 @@
"formik": "^2.0.1-rc.12",
"prettier": "^1.18.2",
"react": "^16.8.6",
"react-albus": "^2.0.0",
"rimraf": "^2.6.3",
"tsdx": "^0.7.2",
"typescript": "^3.5.3",
"yup": "^0.27.0"
},
"dependencies": {
"immer": "^3.1.3"
"immer": "^3.1.3",
"react-step-wizard": "^5.3.2"
}
}
48 changes: 48 additions & 0 deletions src/@types/react-step-wizard.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Initial typings by dmk99 - https://github.com/jcmcneal/react-step-wizard/issues/31#issuecomment-505399131

declare module 'react-step-wizard' {
import * as React from 'react'

export type StepWizardProps = Partial<
React.PropsWithChildren<{
className: string

hashKey: string
initialStep: number
instance: (wizard: StepWizardProps) => void
isHashEnabled: boolean
isLazyMount: boolean
nav: React.ReactNode

onStepChange: (stepChange: {
previousStep: number
activeStep: number
}) => void

transitions: {
enterRight?: string
enterLeft?: string
exitRight?: string
exitLeft?: string
}
}>
>

export type StepWizardChildProps<
T extends Record<string, any> = {}
> = React.PropsWithChildren<{
isActive: boolean
currentStep: number
totalSteps: number
firstStep: () => void
lastStep: () => void
nextStep: () => void
previousStep: () => void
goToStep: (step: number) => void
}> &
T

export default class StepWizard extends React.PureComponent<
StepWizardProps
> {}
}
Empty file added src/index.d.ts
Empty file.
119 changes: 71 additions & 48 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { Form as DefaultForm, Formik, FormikProps } from 'formik'
import produce from 'immer'
import React from 'react'
import { Step as AlbusStep, Steps as AlbusSteps, Wizard as AlbusWizard, WizardContext } from 'react-albus'
import StepWizard, { StepWizardChildProps } from 'react-step-wizard'

import {
FormikWizardBaseValues,
AnyFormValue,
FormikWizardContextValue,
FormikWizardProps,
FormikWizardStepType,
FormikWizardWrapperProps,
} from './types'

function getInitialValues(steps: FormikWizardStepType[]) {
return steps.reduce<FormikWizardBaseValues>((curr, next) => {
return steps.reduce<AnyFormValue>((curr, next) => {
curr[next.id] = next.initialValues
return curr
}, {})
Expand All @@ -23,23 +23,23 @@ const FormikWizardContext = React.createContext<FormikWizardContextValue | null>
)

interface FormikWizardStepProps
extends FormikWizardContextValue<FormikWizardBaseValues, any> {
extends FormikWizardContextValue<AnyFormValue, any> {
step: FormikWizardStepType
Form?: any
steps: string[]
FormWrapper: React.SFC<FormikWizardWrapperProps<any>>
wizard: WizardContext
formikProps?: Partial<FormikProps<any>>
onSubmit: FormikWizardProps<any>['onSubmit']
childWizardProps: StepWizardChildProps
}

function FormikWizardStep({
step,
Form = DefaultForm,
FormWrapper,
steps,
wizard,
formikProps,
childWizardProps,
onSubmit,
setStatus,
status,
Expand Down Expand Up @@ -79,7 +79,7 @@ function FormikWizardStep({
})
})

setImmediate(wizard.next)
setImmediate(childWizardProps.nextStep)
}
} catch (e) {
status = e
Expand All @@ -95,7 +95,7 @@ function FormikWizardStep({
setValues,
step,
values,
wizard.next,
childWizardProps.nextStep,
]
)

Expand All @@ -113,7 +113,7 @@ function FormikWizardStep({
<FormWrapper
{...info}
steps={steps}
wizard={wizard}
childWizardProps={childWizardProps}
actionLabel={step.actionLabel}
isSubmitting={props.isSubmitting}
goToPreviousStep={() => {
Expand All @@ -127,7 +127,7 @@ function FormikWizardStep({
)
}

wizard.previous()
childWizardProps.previousStep()
}}
status={status}
values={values}
Expand All @@ -144,7 +144,7 @@ function FormikWizardStep({

export function FormikWizard<T>({
formikProps,
albusProps,
wizardProps: userWizardProps,
onSubmit,
steps,
Form,
Expand All @@ -160,44 +160,67 @@ export function FormikWizard<T>({

const stepIds = React.useMemo(() => steps.map((step) => step.id), [steps])

return (
<AlbusWizard {...albusProps}>
<FormikWizardContext.Provider
value={{
status,
setStatus,
values,
setValues,
const topLevelWizardProps = Object.assign(
{
transitions: {
enterRight: '',
enterLeft: '',
exitRight: '',
exitLeft: '',
},
},
userWizardProps
)

function StepRenderer({
i,
...childWizardProps
}: StepWizardChildProps & { i: number }) {
const step = steps[i]

return (
<FormikWizardStep
formikProps={formikProps}
childWizardProps={childWizardProps}
onSubmit={onSubmit}
steps={stepIds}
status={status}
values={values}
setValues={setValues}
setStatus={setStatus}
step={{
...step,
initialValues: values[step.id] || {},
}}
>
<AlbusSteps>
{steps.map((step) => (
<AlbusStep
key={step.id}
id={step.id}
render={(wizard) => (
<FormikWizardStep
wizard={wizard}
formikProps={formikProps}
onSubmit={onSubmit}
steps={stepIds}
status={status}
values={values}
setValues={setValues}
setStatus={setStatus}
step={{
...step,
initialValues: values[step.id] || {},
}}
Form={Form}
FormWrapper={render}
/>
)}
/>
))}
</AlbusSteps>
</FormikWizardContext.Provider>
</AlbusWizard>
Form={Form}
FormWrapper={render}
/>
)
}

// react-step-wizard expects children as arrays
// https://github.com/jcmcneal/react-step-wizard/blob/6ee7978ccc08021c7e2ca54d9d77a6de3b992117/src/index.js#L179
const renderSteps = () => {
return steps.map((_, i) => {
return React.createElement(StepRenderer, {
i,
key: i,
// other props will be passed down by react-step-wizard on render
} as any)
})
}

return (
<FormikWizardContext.Provider
value={{
status,
setStatus,
values,
setValues,
}}
>
<StepWizard {...topLevelWizardProps}>{renderSteps()}</StepWizard>
</FormikWizardContext.Provider>
)
}

Expand Down
41 changes: 26 additions & 15 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,59 @@
import { PropsWithChildren } from 'react'
import { FormikProps, FormikErrors } from 'formik'
import { WizardContext, WizardProps } from 'react-albus'
import { Schema } from 'yup'
import { StepWizardProps, StepWizardChildProps } from 'react-step-wizard'

export type FormikWizardBaseValues = any
export type AnyFormValue = any

export interface FormikWizardContextValue<V = any, S = any> {
export interface FormikWizardContextValue<
V extends AnyFormValue = AnyFormValue,
S = any
> {
status: S
setStatus: React.Dispatch<React.SetStateAction<S>>
values: V
setValues: React.Dispatch<React.SetStateAction<V>>
}

export interface FormikWizardStepType {
export interface FormikWizardStepType<
Values extends any = AnyFormValue,
CurrentSection extends keyof Values = any
> extends StepWizardChildProps {
id: string
component: React.SFC<{}>
validationSchema?: Schema<any>
validate?: (values: any) => void | object | Promise<FormikErrors<any>>,
initialValues?: FormikWizardBaseValues
validate?: (values: any) => void | object | Promise<FormikErrors<any>>
initialValues?: AnyFormValue
actionLabel?: string
onAction?: (
sectionValues: FormikWizardBaseValues,
formValues: FormikWizardBaseValues
sectionValues: Values,
formValues: Values[CurrentSection]
) => Promise<any>
keepValuesOnPrevious?: boolean
}

export interface FormikWizardWrapperProps<Values, Status = any>
extends FormikWizardContextValue<Values, Status> {
export interface FormikWizardWrapperProps<
Values extends AnyFormValue = AnyFormValue,
Status = any
> extends PropsWithChildren<FormikWizardContextValue<Values, Status>> {
canGoBack: boolean
goToPreviousStep: () => void
currentStep: string
actionLabel?: string
isLastStep: boolean
steps: string[]
wizard: WizardContext
children: React.ReactNode
childWizardProps: StepWizardChildProps
isSubmitting: boolean
}

export interface FormikWizardProps<Values, Status = any> {
steps: FormikWizardStepType[]
export interface FormikWizardProps<
Values extends AnyFormValue = AnyFormValue,
Status = any
> {
steps: FormikWizardStepType<Values, any>[]
render: React.SFC<FormikWizardWrapperProps<Values, Status>>
onSubmit: (values: Values) => void | Promise<void>
formikProps?: Partial<FormikProps<Values>>
albusProps?: Partial<WizardProps>
Form?: any
wizardProps?: StepWizardProps
}
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"*": ["src/*", "node_modules/*"]
},
"jsx": "react",
"esModuleInterop": true
"esModuleInterop": true,
"typeRoots": ["node_modules/@types", "src/@types"]
},
"include": ["src", "types"]
}
Loading