Skip to content

Commit 9c9981b

Browse files
authored
Merge pull request #803 from rvsia/carbonWizard
feat(carbon): wizard component
2 parents a664ba9 + 156fe34 commit 9c9981b

File tree

6 files changed

+538
-15
lines changed

6 files changed

+538
-15
lines changed

packages/carbon-component-mapper/demo/demo-schemas/wizard-schema.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@ export const wizardSchema = {
66
component: componentTypes.WIZARD,
77
name: 'wizzard',
88
crossroads: ['source.source-type'],
9-
//inModal: true,
9+
stepsInfo: [{ title: 'Configure source' }, { title: 'Enter details' }, { title: 'Review' }],
1010
title: 'Title',
11-
showTitles: true,
1211
description: 'Description',
13-
buttonsPosition: 'left',
12+
vertical: true,
1413
fields: [
1514
{
1615
title: 'Get started with adding source',

packages/carbon-component-mapper/src/files/wizard.d.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
import { Field, AnyObject } from "@data-driven-forms/react-form-renderer";
2+
import { ReactNode } from "react";
3+
import { ButtonProps, ProgressIndicatorProps, ProgressStepProps } from "carbon-components-react";
4+
5+
export interface WizardButtonLabels {
6+
submit?: ReactNode;
7+
back?: ReactNode;
8+
next?: ReactNode;
9+
}
210

311
export interface WizardNextStepFunctionArgument {
412
values?: AnyObject;
@@ -27,9 +35,21 @@ export interface WizardField {
2735
disableForwardJumping?: boolean;
2836
}
2937

38+
export interface WizardNavItem extends ProgressStepProps {
39+
title: ReactNode;
40+
}
41+
3042
export interface WizardProps {
3143
crossroads?: string[];
3244
fields: WizardField[];
45+
buttonLabels?: WizardButtonLabels;
46+
BackButtonProps?: ButtonProps;
47+
NextButtonProps?: ButtonProps;
48+
SubmitButtonProps?: ButtonProps;
49+
ButtonSetProps?: React.HTMLProps<HTMLDivElement>;
50+
ProgressIndicatorProps?: ProgressIndicatorProps;
51+
vertical?: boolean;
52+
stepsInfo?: WizardNavItem[];
3353
}
3454

3555
declare const Wizard: React.ComponentType<WizardProps>;
Lines changed: 138 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,155 @@
11
import React, { useContext } from 'react';
2+
import PropTypes from 'prop-types';
3+
import clsx from 'clsx';
4+
25
import WizardCommon from '@data-driven-forms/common/src/wizard/wizard';
36
import { FormSpy, WizardContext } from '@data-driven-forms/react-form-renderer';
7+
import { ProgressIndicator, ProgressStep, Button, Column, Grid, Row } from 'carbon-components-react';
8+
9+
import './wizard.scss';
10+
11+
const WizardNav = ({ stepsInfo, jumpToStep, ...props }) => (
12+
<ProgressIndicator
13+
onChange={(index) => (props.currentIndex > index ? jumpToStep(index, true) : undefined)}
14+
{...props}
15+
className={clsx('ddorg__carbon-wizard-navigation-horizontal', props.className)}
16+
>
17+
{stepsInfo.map(({ title, ...step }, index) => (
18+
<ProgressStep key={index} label={title} disabled={index > props.currentIndex} {...step} />
19+
))}
20+
</ProgressIndicator>
21+
);
422

5-
const WizardInternal = () => {
6-
const { formOptions, currentStep, handlePrev, onKeyDown, handleNext, activeStepIndex, selectNext } = useContext(WizardContext);
23+
WizardNav.propTypes = {
24+
stepsInfo: PropTypes.arrayOf(
25+
PropTypes.shape({
26+
title: PropTypes.node
27+
})
28+
),
29+
currentIndex: PropTypes.number,
30+
jumpToStep: PropTypes.func,
31+
className: PropTypes.string
32+
};
33+
34+
const defaultLabels = {
35+
submit: 'Submit',
36+
back: 'Back',
37+
next: 'Next'
38+
};
39+
40+
const Layout = ({ nav, fields }) => (
41+
<React.Fragment>
42+
{nav}
43+
{fields}
44+
</React.Fragment>
45+
);
46+
47+
Layout.propTypes = {
48+
nav: PropTypes.node,
49+
fields: PropTypes.node
50+
};
51+
52+
const VerticalLayout = ({ nav, fields }) => (
53+
<Grid narrow>
54+
<Row>
55+
<Column sm={1} md={2} lg={3}>
56+
{nav}
57+
</Column>
58+
<Column>{fields}</Column>
59+
</Row>
60+
</Grid>
61+
);
62+
63+
VerticalLayout.propTypes = {
64+
nav: PropTypes.node,
65+
fields: PropTypes.node
66+
};
67+
68+
const WizardInternal = ({
69+
stepsInfo,
70+
buttonLabels,
71+
ButtonSetProps,
72+
BackButtonProps,
73+
NextButtonProps,
74+
SubmitButtonProps,
75+
ProgressIndicatorProps,
76+
vertical,
77+
...props
78+
}) => {
79+
const { formOptions, currentStep, handlePrev, onKeyDown, handleNext, activeStepIndex, selectNext, jumpToStep } = useContext(WizardContext);
80+
81+
const finalButtoLabels = {
82+
...defaultLabels,
83+
...buttonLabels
84+
};
85+
86+
const nav = stepsInfo && (
87+
<WizardNav vertical={vertical} stepsInfo={stepsInfo} currentIndex={activeStepIndex} jumpToStep={jumpToStep} {...ProgressIndicatorProps} />
88+
);
89+
const fields = currentStep.fields.map((item) => formOptions.renderForm([item], formOptions));
90+
91+
const WizardLayout = vertical && nav ? VerticalLayout : Layout;
792

893
return (
9-
<div onKeyDown={onKeyDown}>
10-
{currentStep.fields.map((item) => formOptions.renderForm([item], formOptions))}
94+
<div onKeyDown={onKeyDown} {...props}>
95+
<WizardLayout nav={nav ? nav : null} fields={fields} />
1196
<FormSpy>
12-
{({ valid }) => (
13-
<div>
14-
<button onClick={() => handleNext(selectNext(currentStep.nextStep, formOptions.getState))} disabled={!valid}>
15-
Next
16-
</button>
17-
<button onClick={handlePrev} disabled={activeStepIndex === 0}>
18-
Back
19-
</button>
97+
{({ invalid, validating, submitting }) => (
98+
<div {...ButtonSetProps} className={clsx('ddorg__carbon-wizard-button-set', ButtonSetProps.className)}>
99+
{currentStep.nextStep ? (
100+
<Button
101+
onClick={() => handleNext(selectNext(currentStep.nextStep, formOptions.getState))}
102+
disabled={!formOptions.valid || invalid || validating || submitting}
103+
{...NextButtonProps}
104+
>
105+
{finalButtoLabels.next}
106+
</Button>
107+
) : (
108+
<Button
109+
onClick={() => formOptions.handleSubmit()}
110+
disabled={!formOptions.valid || invalid || validating || submitting}
111+
{...SubmitButtonProps}
112+
>
113+
{finalButtoLabels.submit}
114+
</Button>
115+
)}
116+
<Button kind="secondary" onClick={handlePrev} disabled={activeStepIndex === 0} {...BackButtonProps}>
117+
{finalButtoLabels.back}
118+
</Button>
20119
</div>
21120
)}
22121
</FormSpy>
23122
</div>
24123
);
25124
};
26125

126+
WizardInternal.propTypes = {
127+
stepsInfo: PropTypes.arrayOf(
128+
PropTypes.shape({
129+
title: PropTypes.node
130+
})
131+
),
132+
buttonLabels: PropTypes.shape({
133+
submit: PropTypes.node,
134+
back: PropTypes.node,
135+
next: PropTypes.node
136+
}),
137+
BackButtonProps: PropTypes.object,
138+
NextButtonProps: PropTypes.object,
139+
SubmitButtonProps: PropTypes.object,
140+
ButtonSetProps: PropTypes.object,
141+
ProgressIndicatorProps: PropTypes.object,
142+
vertical: PropTypes.bool
143+
};
144+
145+
WizardInternal.defaultProps = {
146+
BackButtonProps: {},
147+
NextButtonProps: {},
148+
SubmitButtonProps: {},
149+
ButtonSetProps: {},
150+
ProgressIndicatorProps: {}
151+
};
152+
27153
const Wizard = (props) => <WizardCommon Wizard={WizardInternal} {...props} />;
28154

29155
export default Wizard;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.ddorg__carbon-wizard-navigation-horizontal {
2+
margin-bottom: 48px;
3+
}
4+
5+
.ddorg__carbon-wizard-button-set {
6+
margin-top: 48px;
7+
flex-direction: row-reverse;
8+
display: flex;
9+
}

0 commit comments

Comments
 (0)