UNPKG

react-native-multistep

Version:

Create multi-step forms with ease in your React Native app

121 lines (118 loc) 4.18 kB
"use strict"; import React, { useState, forwardRef, useImperativeHandle } from 'react'; import { View, Text, TouchableOpacity, Animated } from 'react-native'; import { BACK, DONE, NEXT } from "./constants.js"; import { styles } from "./styles.js"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; export const MultiStepForm = /*#__PURE__*/forwardRef(({ stepsContent, onStepChange, onStepForward, onStepBackward, backButtonLabel = BACK, nextButtonLabel = NEXT, doneButtonLabel = DONE, onComplete, style, nextButtonStyle, previousButtonStyle, doneButtonStyle, stepsContainerStyle, activeStepStyle, inactiveStepStyle, contentContainerStyle, buttonsContainerStyle, lineColor, activeLineColor }, ref) => { const totalSteps = stepsContent.length; const [step, setStep] = useState(1); if (totalSteps === 0 || !stepsContent) { throw new Error('Missing steps content'); } // Step transition animations const [scaleAnim] = useState(new Animated.Value(1)); const changeStep = direction => { setStep(prevStep => { const newStep = direction === 'next' ? Math.min(prevStep + 1, totalSteps) : Math.max(prevStep - 1, 1); Animated.timing(scaleAnim, { toValue: 1.1, duration: 200, useNativeDriver: true }).start(() => { Animated.timing(scaleAnim, { toValue: 1, duration: 200, useNativeDriver: true }).start(); }); direction === 'next' ? onStepForward?.(newStep) : onStepBackward?.(newStep); onStepChange?.(newStep); if (newStep === totalSteps) onComplete?.(newStep); return newStep; }); }; // Expose methods to parent component via ref useImperativeHandle(ref, () => ({ goToStep: targetStep => { setStep(Math.min(Math.max(targetStep, 1), totalSteps)); onStepChange?.(targetStep); } })); const stepIndicators = React.useMemo(() => { return Array.from({ length: totalSteps }, (_, i) => { const isActive = i + 1 <= step; const isCurrent = i + 1 === step; return /*#__PURE__*/_jsxs(View, { style: [styles.stepContainer, stepsContainerStyle], children: [/*#__PURE__*/_jsx(Animated.View, { style: [styles.stepIndicator, isActive ? [styles.activeStep, activeStepStyle, { transform: [{ scale: isCurrent ? scaleAnim : 1 }] }] : inactiveStepStyle], children: /*#__PURE__*/_jsx(Text, { style: [styles.stepText, isActive && styles.activeStepText], children: i + 1 }) }), i + 1 < totalSteps && /*#__PURE__*/_jsx(View, { style: [styles.line, { backgroundColor: lineColor }, i + 1 < step && [styles.activeLine, { backgroundColor: activeLineColor }]] })] }, i); }); }, [totalSteps, step, stepsContainerStyle, activeStepStyle, scaleAnim, inactiveStepStyle, lineColor, activeLineColor]); return /*#__PURE__*/_jsxs(View, { style: [styles.container, style], children: [/*#__PURE__*/_jsx(View, { style: styles.indicatorContainer, children: stepIndicators }), /*#__PURE__*/_jsx(Animated.View, { style: [styles.contentContainer, contentContainerStyle], children: stepsContent[step - 1] }), /*#__PURE__*/_jsxs(View, { style: [styles.fixedFooter, buttonsContainerStyle], children: [step > 1 && /*#__PURE__*/_jsx(TouchableOpacity, { onPress: () => changeStep('previous'), style: [styles.button, styles.backButton, previousButtonStyle], children: /*#__PURE__*/_jsx(Text, { style: styles.backButtonText, children: backButtonLabel }) }), /*#__PURE__*/_jsx(TouchableOpacity, { onPress: () => changeStep('next'), style: [styles.button, styles.nextButton, step < totalSteps ? nextButtonStyle : doneButtonStyle], children: /*#__PURE__*/_jsx(Text, { style: styles.nextButtonText, children: step < totalSteps ? nextButtonLabel : doneButtonLabel }) })] })] }); }); //# sourceMappingURL=index.js.map