UNPKG

@talend/react-components

Version:
234 lines (227 loc) 8.32 kB
import { Fragment, useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { useTranslation } from 'react-i18next'; import { ErrorState, StackVertical, Stepper as CoralStepper } from '@talend/design-system'; import Icon from '../Icon'; import CircularProgress from '../CircularProgress'; import { getTheme } from '../theme'; import theme from './Stepper.component.module.scss'; import { DEFAULT_TRANSITION_DURATION, StepperTransition } from './StepperTransition.component'; import I18N_DOMAIN_COMPONENTS from '../constants'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const getClass = getTheme(theme); const SHOW_COMPLETED_TRANSITION_TIMER = 1000; const TRANSITION_STATE = { STEPS: 'STEPS', TRANSITION: 'TRANSITION', CHILD: 'CHILD' }; const LOADING_STEP_STATUSES = { ABORTED: 'aborted', PENDING: 'pending', LOADING: 'loading', SUCCESS: 'success', FAILURE: 'failure' }; /** * This function tells if there is an error in the steps * @param {array} steps array of steps */ const isErrorInSteps = steps => steps.some(step => step.status === LOADING_STEP_STATUSES.FAILURE); const getStepInError = steps => steps.find(step => step.status === LOADING_STEP_STATUSES.FAILURE); /** * This function tells if all the steps are successful * @param {array} steps array of steps */ const isAllSuccessful = steps => steps.every(step => step.status === LOADING_STEP_STATUSES.SUCCESS); /** * This function tells if the loading is done, by an error, a success ot not started * @param {array} steps array of steps */ const isStepsLoading = steps => steps.length !== 0 && !isAllSuccessful(steps) && !isErrorInSteps(steps); /** * This function returns a label for some status * @param {string} status the current step status */ function getStatusText(t, status) { switch (status) { case LOADING_STEP_STATUSES.ABORTED: return t('ABORTED', { defaultValue: ' (Aborted)' }); case LOADING_STEP_STATUSES.PENDING: return t('PENDING', { defaultValue: ' (Pending)' }); default: return null; } } /** * This function returns an icon that represent the current step * @param {string} status the current step status */ function getIconByStatus(status) { const iconCLass = getClass(`stepper-icon-${status}`, 'stepper-icon'); switch (status) { case LOADING_STEP_STATUSES.SUCCESS: return /*#__PURE__*/_jsx(Icon, { name: "talend-check", className: iconCLass }); case LOADING_STEP_STATUSES.ABORTED: return /*#__PURE__*/_jsx(Icon, { name: "talend-cross", className: iconCLass }); case LOADING_STEP_STATUSES.PENDING: return /*#__PURE__*/_jsx("span", { className: iconCLass, children: "-" }); case LOADING_STEP_STATUSES.FAILURE: return /*#__PURE__*/_jsx(Icon, { name: "talend-warning", className: iconCLass }); case LOADING_STEP_STATUSES.LOADING: return /*#__PURE__*/_jsx(CircularProgress, { className: iconCLass }); default: return null; } } function changeTransitionState(newTransitionState, setTransitionState, timer = 0) { if (timer === 0) { setTransitionState(newTransitionState); } else { setTimeout(() => { setTransitionState(newTransitionState); }, timer); } } /** * This function returns a rendered step * @param {object} step the current loading step * @param {number} index the index for the key */ function showStep(t, step, index, steps) { const cssStep = getClass('stepper-step', `stepper-step-${step.status}`); const a11y = {}; if ([LOADING_STEP_STATUSES.LOADING, LOADING_STEP_STATUSES.FAILURE].includes(step.status) || index === steps.length - 1 && step.status === LOADING_STEP_STATUSES.SUCCESS) { a11y['aria-current'] = true; } return /*#__PURE__*/_jsxs("li", { className: cssStep, ...a11y, children: [/*#__PURE__*/_jsxs("div", { className: getClass('stepper-step-infos'), children: [getIconByStatus(step.status), step.label, getStatusText(t, step.status)] }), step.message && /*#__PURE__*/_jsxs("div", { className: getClass('stepper-step-message'), children: [/*#__PURE__*/_jsx("span", { className: getClass('stepper-step-message-label'), children: step.message.label }), step.message.description && /*#__PURE__*/_jsx("p", { children: step.message.description })] })] }, `step-${index}`); } /** * This function generates a set transition state function * @param {string} transition the transition state to set * @param {number} timer the timer to set the transition */ function transition(transitionState, timer = 0) { return setTransitionState => changeTransitionState(transitionState, setTransitionState, timer); } const transitionLoadingToEmpty = transition(TRANSITION_STATE.TRANSITION, SHOW_COMPLETED_TRANSITION_TIMER); const transitionEmptyToChildren = transition(TRANSITION_STATE.CHILD, SHOW_COMPLETED_TRANSITION_TIMER + DEFAULT_TRANSITION_DURATION); const transitionChildrenToEmpty = transition(TRANSITION_STATE.TRANSITION); const transitionEmptyToLoading = transition(TRANSITION_STATE.STEPS, DEFAULT_TRANSITION_DURATION); function Stepper({ steps, title, renderActions, children }) { const { t } = useTranslation(I18N_DOMAIN_COMPONENTS); const errorStep = getStepInError(steps); const [transitionState, setTransitionState] = useState(isStepsLoading(steps) || !children ? TRANSITION_STATE.STEPS : TRANSITION_STATE.CHILD); useEffect(() => { const allSuccessful = isAllSuccessful(steps); if (children && allSuccessful && (transitionState === TRANSITION_STATE.STEPS || transitionState === TRANSITION_STATE.TRANSITION)) { transitionLoadingToEmpty(setTransitionState); transitionEmptyToChildren(setTransitionState); } else if (!allSuccessful && transitionState === TRANSITION_STATE.CHILD) { transitionChildrenToEmpty(setTransitionState); transitionEmptyToLoading(setTransitionState); } }, [steps]); if (!!errorStep) { var _errorStep$message; return /*#__PURE__*/_jsx("div", { className: getClass('loading-content-steps', 'error'), children: /*#__PURE__*/_jsxs(StackVertical, { gap: 0, align: "center", justify: "center", children: [/*#__PURE__*/_jsx(ErrorState, { title: errorStep.label, description: (_errorStep$message = errorStep.message) === null || _errorStep$message === void 0 ? void 0 : _errorStep$message.label }), renderActions && renderActions(!!errorStep) ? /*#__PURE__*/_jsx("div", { children: renderActions(!!errorStep) }) : null] }) }); } return /*#__PURE__*/_jsxs(Fragment, { children: [/*#__PURE__*/_jsx(StepperTransition, { active: transitionState === TRANSITION_STATE.CHILD, children: children }), /*#__PURE__*/_jsx(StepperTransition, { active: transitionState === TRANSITION_STATE.STEPS, children: /*#__PURE__*/_jsx("div", { className: getClass('stepper'), children: /*#__PURE__*/_jsxs("div", { className: getClass('loading-content-steps'), children: [title && /*#__PURE__*/_jsx("h2", { children: title }), /*#__PURE__*/_jsx("ol", { className: getClass('stepper-steps'), children: steps.map((step, index, array) => showStep(t, step, index, array)) })] }) }) })] }); } Stepper.displayName = 'Stepper'; Stepper.defaultProps = { steps: [] }; Stepper.propTypes = { title: PropTypes.string, renderActions: PropTypes.func, children: PropTypes.element, steps: PropTypes.arrayOf(PropTypes.shape({ label: PropTypes.string, status: PropTypes.oneOf(Object.values(LOADING_STEP_STATUSES)), message: PropTypes.shape({ label: PropTypes.string, description: PropTypes.string }) })) }; Stepper.SHOW_COMPLETED_TRANSITION_TIMER = SHOW_COMPLETED_TRANSITION_TIMER; Stepper.LOADING_STEP_STATUSES = LOADING_STEP_STATUSES; Stepper.isStepsLoading = isStepsLoading; Stepper.isAllSuccessful = isAllSuccessful; Stepper.isErrorInSteps = isErrorInSteps; Stepper.Form = CoralStepper; export default Stepper; //# sourceMappingURL=Stepper.component.js.map