UNPKG

carbon-react

Version:

A library of reusable React components and an interface for easily building user interfaces based on Flux.

370 lines (312 loc) • 12.4 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _react2 = require('react'); var _react3 = _interopRequireDefault(_react2); var _babelTransform = require('livereactload/babel-transform'); var _babelTransform2 = _interopRequireDefault(_babelTransform); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var _class, _temp2; var _propTypes = require('prop-types'); var _propTypes2 = _interopRequireDefault(_propTypes); var _classnames = require('classnames'); var _classnames2 = _interopRequireDefault(_classnames); var _step = require('./step'); var _step2 = _interopRequireDefault(_step); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _components = { MultiStepWizard: { displayName: 'MultiStepWizard' } }; var _livereactloadBabelTransform2 = (0, _babelTransform2.default)({ filename: 'src/components/multi-step-wizard/multi-step-wizard.js', components: _components, locals: [], imports: [_react3.default] }); function _wrapComponent(id) { return function (Component) { return _livereactloadBabelTransform2(Component, id); }; } /** * A MultiStepWizard widget. * * == How to use a MultiStepWizard in a component: * * In your file: * * import MultiStepWizard from 'components/multi-step-wizard'; * * To render the Wizard: * * <MultiStepWizard steps={ [<Step1 />, <Step2 />, ...] } /> * * The component rendering the wizard must pass down a prop of 'steps' where you need to provide an array of custom * step components. Note that Step components must be objects and you can pass props to Step components, e.g. * <MultiStepWizard steps={ [<Textbox onChange={ this.updateTextboxValue } />, <div className='some-style' />] } /> * * You also need to provide a 'onSubmit' handler to handle a submit event. * * The wizard also takes a 'currentStep' prop with an integer to specify a step you want to start with. * e.g. currentStep={ 2 }. The wizard starts with the first step by default. * * The wizard disables inactive steps by default. If you wish to enable inactive steps, pass a 'enableInactiveSteps' * prop and set it to true. * * The wizard generates Next and Back buttons by default. If you wish to use custom buttons to replace the default ones * in a step component, you can pass a 'defaultButton' prop in the corresponding step component and set it to false. * Also, if you want to add additional buttons beside the default Next and Back buttons, you can pass a 'extraButtons' * prop in the corresponding step component with your extra buttons. * Individual Steps can be optionally disabled by a passing a prop of `enabled={ false }`. * e.g. <MultiStepWizard steps={ [<Step1 defaultButton={ false } />, <Step2 />] } /> * <MultiStepWizard steps={ [<Step1 />, <Step2 extraButtons={ [<Button>Cancel</Button>] }) />] } /> * <MultiStepWizard steps={ [<Step1 />, <Step2 enabled={ false } />] } /> * * The wizard provides the ability to hook into the handle next/back/submit methods. * (1) By passing a 'beforeSubmitValidation' prop in the wizard, you can add custom logic before a submit event, and * the submit event can be completed only when the 'beforeSubmitValidation' prop returns 'true'. * (2) By passing 'onNext' prop in the corresponding step component, you can add custom logic when moving a step forward, and * the 'onNext' prop overrides the step's default behaviour of moving next. * (3) By passing 'onBack' prop in the corresponding step component, you can add custom logic when moving a step backward, and * the 'onBack' prop overrides the step's default behaviour of moving back. * e.g. <MultiStepWizard steps={ [<Step1 onNext={ this.customMethodOnNext }/>, <Step2 onBack={ this.customMethodOnBack }) />] } /> * <MultiStepWizard beforeSubmitValidation={ this.customValidation } onSubmit={ this.customMethodOnSubmit } /> * * If you want to complete the wizard without going through steps, you can pass a 'completed' prop and set it to true. * * @class MultiStepWizard * @constructor */ var MultiStepWizard = _wrapComponent('MultiStepWizard')((_temp2 = _class = function (_React$Component) { _inherits(MultiStepWizard, _React$Component); function MultiStepWizard() { var _ref; var _temp, _this, _ret; _classCallCheck(this, MultiStepWizard); for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = MultiStepWizard.__proto__ || Object.getPrototypeOf(MultiStepWizard)).call.apply(_ref, [this].concat(args))), _this), _this.validateStepProps = function (stepProps) { var step = stepProps.currentStep, completed = stepProps.completed, totalSteps = stepProps.steps.length; if (completed === true) { return { currentStep: totalSteps, completed: true }; } else if (parseInt(step) !== step || step < 1 || step > totalSteps) { return { currentStep: 1, completed: false }; } else { return { currentStep: step, completed: false }; } }, _this.next = function () { if (_this.state.currentStep < _this.totalSteps) { _this.setState({ currentStep: _this.state.currentStep + 1 }); } }, _this.back = function () { if (_this.state.currentStep > 1) { _this.setState({ completed: false, currentStep: _this.state.currentStep - 1 }); } }, _this.complete = function () { if (_this.state.currentStep === _this.totalSteps) { _this.setState({ completed: true }); } }, _temp), _possibleConstructorReturn(_this, _ret); } _createClass(MultiStepWizard, [{ key: 'componentWillMount', /** * A lifecycle method that is called before initial render. * Can set up state of component without causing a re-render. * * @method componentWillMount */ value: function componentWillMount() { var validProps = this.validateStepProps(this.props); this.setState({ currentStep: validProps.currentStep, completed: validProps.completed }); } /** * A lifecycle method to update the currentStep state when a new valid value has been specified. * * @method componentWillReceiveProps * @param {Object} props The new props passed down to the component * @return {void} */ }, { key: 'componentWillReceiveProps', value: function componentWillReceiveProps(nextProps) { var validProps = this.validateStepProps(nextProps); this.setState({ currentStep: validProps.currentStep, completed: validProps.completed }); } }, { key: 'getChildContext', /** * Returns wizard object to child components. * * @method getChildContext * @return {void} */ value: function getChildContext() { return { wizard: { nextHandler: this.props.onNext, backHandler: this.props.onBack, beforeSubmitValidation: this.props.beforeSubmitValidation, submitHandler: this.props.onSubmit, enableInactiveSteps: this.props.enableInactiveSteps, currentStep: this.state.currentStep, completed: this.state.completed, next: this.next, back: this.back, complete: this.complete, totalSteps: this.totalSteps } }; } /** * Validate step props * * @method validateStepProps * @return {Object} */ }, { key: 'render', /** * Renders the component. * * @method render * @return {Object} JSX */ value: function render() { return _react3.default.createElement( 'div', { className: this.mainClasses }, _react3.default.createElement( 'div', { className: 'multi-step-wizard__content' }, this.wizardStepsHTML ) ); } }, { key: 'totalSteps', /** * Get total number of steps * * @method totalSteps * @return {Number} */ get: function get() { return this.props.steps.length; } /** * Moves to the next step. * * @method next * @return {void} */ /** * Back to the previous step. * * @method back * @return {void} */ /** * Completes the wizard. * * @method complete * @return {void} */ }, { key: 'wizardStepsHTML', /** * Returns the computed HTML for the wizard's steps. * * @method wizardStepsHTML * @return {Object} JSX */ get: function get() { return this.props.steps.map(function (step, index) { return _react3.default.createElement( _step2.default, _extends({ stepNumber: index + 1, key: 'multi-step-wizard-step-' + index }, step.props), step ); }); } /** * Returns classes for the wizard. * * @method mainClasses * @return {String} Main className */ }, { key: 'mainClasses', get: function get() { return (0, _classnames2.default)('multi-step-wizard', this.props.className); } }]); return MultiStepWizard; }(_react3.default.Component), _class.propTypes = { /** * Individual steps * * @property steps * @type {Array} */ steps: _propTypes2.default.arrayOf(_propTypes2.default.object).isRequired, /** * Custom function that is called immediately before a submit event * * @property beforeSubmitValidation * @type {Function} */ beforeSubmitValidation: _propTypes2.default.func, /** * A custom submit event handler * * @property onSubmit * @type {Function} */ onSubmit: _propTypes2.default.func.isRequired, /** * Current step * * @property currentStep * @type {Number} * @default 1 */ currentStep: _propTypes2.default.number, /** * Determines if the wizard disables inactive steps * * @property enableInactiveSteps * @type {Boolean} * @default false */ enableInactiveSteps: _propTypes2.default.bool, /** * The completion state of the wizard * * @property enableInactiveSteps * @type {Boolean} * @default false */ completed: _propTypes2.default.bool }, _class.defaultProps = { currentStep: 1, enableInactiveSteps: false, completed: false }, _class.childContextTypes = { /** * Defines a context object for child components of this wizard. * * @property wizard * @type {Object} */ wizard: _propTypes2.default.object }, _temp2)); exports.default = MultiStepWizard;