fk-react-ui-components
Version:
Step 1 : Create a file in [ Seeds / Plants / Trees ] <br> Step 2 : It should export an Object with component name and story Component [Refer other components] <br> Step 3 : Story Component should return a react component <br> Step 3 : Created file should
310 lines (267 loc) • 9.54 kB
JavaScript
import React from 'react';
import { StepperContainer, StepsWrapper, ContentWrapper, StepItem, DoneIconContainer, ActiveIconContainer, InactiveIconContainer } from './styles';
import { PropTypes } from 'prop-types';
/**
* @class{Step} Should be a child of Stepper component
*/
export class Step extends React.PureComponent {
render() {
return React.isValidElement(this.props.children) ? this.props.children : null;
}
}
/**
* @class{Stepper} Parent class controlling the logic and rendering of steps
*/
export class Stepper extends React.PureComponent {
constructor(props) {
super(props);
this.getIcon = (childProps, index) => {
if (childProps.disabled) {
return childProps.disabledIcon || childProps.icon || this.props.disabledIcon || this.props.icon || React.createElement(InactiveIconContainer, null);
} else if (index === this.state.stepIndex) {
return childProps.activeIcon || childProps.icon || this.props.activeIcon || this.props.icon || React.createElement(
ActiveIconContainer,
null,
React.createElement('i', { className: 'fa fa-chevron-right' })
);
} else if (this.state.doneMapping[index]) {
return childProps.doneIcon || childProps.icon || this.props.doneIcon || this.props.icon || React.createElement(
DoneIconContainer,
null,
React.createElement('i', { className: 'fa fa-check' })
);
} else {
return childProps.inactiveIcon || childProps.icon || this.props.inactiveIcon || this.props.icon || React.createElement(InactiveIconContainer, null);
}
};
this.handleClick = index => {
const childrenArray = React.Children.toArray(this.props.children);
if (!childrenArray[index].props.disabled && this.state.doneMapping[index]) {
if (this.props.onChange && typeof this.props.stepIndex !== 'undefined') {
this.props.onChange(index, 'click');
} else {
this.setState({ stepIndex: index });
}
}
};
this.next = () => {
let index = this.state.stepIndex;
const childrenArray = React.Children.toArray(this.props.children);
/**
* Mark the current step as done in case of un-controlled component
*/
if (!this.props.doneMapping) {
const doneMapping = [...this.state.doneMapping];
doneMapping[index] = true;
this.setState({ doneMapping });
}
/**
* Call onComplete handler if all steps are complete
*/
if (index === childrenArray.length - 1) {
if (this.props.onComplete) {
this.props.onComplete();
}
return;
}
/**
* Calculate the next step index
*/
while (index < childrenArray.length && (index === this.state.stepIndex || childrenArray[index].props.disabled)) {
index += 1;
}
/**
* Update the step index in the local state in case of un-controlled component.
* For controlled component simply call the onChange handler
*/
if (!childrenArray[index].props.disabled) {
if (this.props.onChange && this.props.stepIndex !== 'undefined') {
this.props.onChange(index, 'next');
} else {
this.setState({
stepIndex: index
});
}
}
};
this.previous = () => {
let index = this.state.stepIndex;
const childrenArray = React.Children.toArray(this.props.children);
/**
* Calculate the previous index
*/
while (index > 0 && (index === this.state.stepIndex || childrenArray[index].props.disabled)) {
index -= 1;
}
/**
* Update the step index in the local state in case of un-controlled component.
* For controlled component simply call the onChange handler
*/
if (!childrenArray[index].props.disabled) {
if (this.props.onChange && typeof this.props.stepIndex !== 'undefined') {
this.props.onChange(index, 'previous');
} else {
this.setState({
stepIndex: index
});
}
}
};
this.state = {
stepIndex: props.stepIndex || 0,
doneMapping: props.doneMapping || Array(React.Children.count(props.children)).fill(false)
};
}
/**
* Update local state when props change
* @param {object} nextProps
*/
componentWillReceiveProps(nextProps) {
if (this.props.stepIndex !== nextProps.stepIndex) {
this.setState({ stepIndex: nextProps.stepIndex });
}
if (this.props.doneMapping !== nextProps.doneMapping) {
this.setState({ doneMapping: nextProps.doneMapping });
}
}
/**
* Returns the icon to be rendered for any step
* @param {object} childProps
* @param {number} index
* @return {element}
*/
/**
* Handles click on any step.
* Calls onClick prop if provided else goes to that step if current
* stepIndex is greater than index and step is not disabled
* @param {number} index
*/
/**
* Function to move to the next step
*/
/**
* Function to move to the previous step
*/
render() {
return React.createElement(
StepperContainer,
{
orientation: this.props.orientation,
styles: this.props.styles.container || {}
},
React.createElement(
StepsWrapper,
{
orientation: this.props.orientation,
styles: this.props.styles.stepper || {}
},
React.Children.map(this.props.children, (step, index) => {
return React.createElement(
StepItem,
{
orientation: this.props.orientation,
styles: this.props.styles.step || {},
onClick: () => this.handleClick(index),
active: index === this.state.stepIndex,
done: this.state.doneMapping[index]
},
this.getIcon(step.props, index),
step.props.label
);
})
),
React.createElement(
ContentWrapper,
null,
this.props.header ? this.props.header : null,
React.Children.toArray(this.props.children)[this.state.stepIndex],
this.props.footer ? this.props.footer : null
)
);
}
}
Stepper.propTypes = {
/**
* Orientation of the stepper. May be horizontal or vertical
*/
orientation: PropTypes.oneOf(['horizontal', 'vertical']),
/**
* Styles of the stepper.
*/
styles: PropTypes.object,
/**
* Current step index ( to be passes for controlled component)
*/
stepIndex: PropTypes.number,
/**
* Header element
*/
header: PropTypes.element,
/**
* Footer element
*/
footer: PropTypes.element,
/**
* Mapping of steps vs there done state (true / false)
* e.g. [true, false, false, false] (First step is done, rest are not)
* To be passed for controlled component
*/
doneMapping: PropTypes.arrayOf(PropTypes.number),
/**
* Invoked when the step changes
*/
onChange: PropTypes.func,
/**
* Invoked when all the steps are completed
*/
onComplete: PropTypes.func,
/**
* Default icon JSX element
*/
icon: PropTypes.element,
/**
* Inactive icon. Ovverrides icon prop for inactive state
*/
inactiveIcon: PropTypes.element,
/**
* Active icon. Overrides icon prop for active state
*/
activeIcon: PropTypes.element,
/**
* Disabled icon. Overrides icon prop for disabled state
*/
disabledIcon: PropTypes.element
};
Step.propTypes = {
/**
* Label for each step
*/
label: PropTypes.string,
/**
* Set disabled to true to disable a step
*/
disabled: PropTypes.bool,
/**
* Icon for a specific step. If provided, it ovverides the icon provided
* in the parent Stepper Component
*/
icon: PropTypes.element,
/**
* Inactive icon. Ovverrides icon prop for inactive state
*/
inactiveIcon: PropTypes.element,
/**
* Active icon. Ovverrides icon prop for inactive state
*/
activeIcon: PropTypes.element,
/**
* Disabled icon. Ovverrides icon prop for inactive state
*/
disabledIcon: PropTypes.element
};
Stepper.defaultProps = {
orientation: 'vertical',
styles: {},
disabled: false
};
//# sourceMappingURL=index.js.map