UNPKG

react-native-onboarding-flow

Version:

Beautiful, customizable onboarding flows for React Native with smooth animations

175 lines (170 loc) 6.64 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const react_1 = __importDefault(require("react")); const react_native_1 = require("react-native"); const vector_icons_1 = require("@expo/vector-icons"); const OnboardingSlide_1 = __importDefault(require("./OnboardingSlide")); const { width } = react_native_1.Dimensions.get('window'); const OnboardingModal = ({ visible, slides, currentSlide, onNext, onClose, closeable, showProgress, theme, showPaywall = false, paywallComponent, }) => { const isValidSlide = currentSlide >= 0 && currentSlide < slides.length; const isLastSlide = isValidSlide && currentSlide === slides.length - 1; const currentSlideData = isValidSlide ? slides[currentSlide] : null; const renderProgressDots = () => { if (!showProgress) return null; return (<react_native_1.View style={styles.progressContainer}> {slides.map((_, index) => (<react_native_1.View key={index} style={[ styles.progressDot, { backgroundColor: index <= currentSlide ? ((theme === null || theme === void 0 ? void 0 : theme.progressDotActiveColor) || '#6B8E5A') : ((theme === null || theme === void 0 ? void 0 : theme.progressDotColor) || '#E5E5E5'), width: index === currentSlide ? 24 : 8, }, ]}/>))} </react_native_1.View>); }; return (<react_native_1.Modal visible={visible} animationType="slide" presentationStyle="pageSheet" onRequestClose={closeable ? onClose : undefined}> <react_native_1.SafeAreaView style={[styles.container, { backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.backgroundColor) || 'white' }]}> {showPaywall && paywallComponent ? ( // Render paywall component in full screen <react_native_1.View style={styles.paywallContainer}> {paywallComponent} </react_native_1.View>) : (<> {/* Header with optional close button */} <react_native_1.View style={styles.header}> <react_native_1.View style={styles.headerSpacer}/> {closeable && onClose && (<react_native_1.TouchableOpacity onPress={onClose} style={styles.closeButton}> <vector_icons_1.Ionicons name="close" size={24} color={(theme === null || theme === void 0 ? void 0 : theme.closeButtonColor) || '#666'}/> </react_native_1.TouchableOpacity>)} </react_native_1.View> {/* Progress dots */} {renderProgressDots()} {/* Slide content */} <react_native_1.View style={styles.slideContainer}> {currentSlideData && currentSlideData.media && (<OnboardingSlide_1.default slide={currentSlideData} isActive={true} theme={theme}/>)} {!currentSlideData && (<react_native_1.View style={styles.errorContainer}> <react_native_1.Text style={styles.errorText}>Unable to load slide</react_native_1.Text> </react_native_1.View>)} </react_native_1.View> {/* Footer with next button */} <react_native_1.View style={styles.footer}> <react_native_1.TouchableOpacity style={[ styles.nextButton, { backgroundColor: (theme === null || theme === void 0 ? void 0 : theme.buttonBackgroundColor) || '#6B8E5A' }, isLastSlide && styles.completeButton, ]} onPress={onNext} activeOpacity={0.8}> <react_native_1.Text style={[ styles.nextButtonText, { color: (theme === null || theme === void 0 ? void 0 : theme.buttonTextColor) || 'white' }, isLastSlide && styles.completeButtonText, ]}> {isLastSlide ? 'Get Started' : 'Next'} </react_native_1.Text> {!isLastSlide && (<vector_icons_1.Ionicons name="arrow-forward" size={20} color="white" style={styles.nextIcon}/>)} </react_native_1.TouchableOpacity> {!isLastSlide && (<react_native_1.Text style={styles.slideCounter}> {currentSlide + 1} of {slides.length} </react_native_1.Text>)} </react_native_1.View> </>)} </react_native_1.SafeAreaView> </react_native_1.Modal>); }; const styles = react_native_1.StyleSheet.create({ container: { flex: 1, backgroundColor: '#F8FAF6', }, header: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingHorizontal: 20, paddingVertical: 10, height: 50, }, headerSpacer: { width: 32, }, closeButton: { padding: 4, borderRadius: 20, backgroundColor: 'rgba(0,0,0,0.05)', }, progressContainer: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', paddingVertical: 20, gap: 8, }, progressDot: { height: 8, borderRadius: 4, }, slideContainer: { flex: 1, paddingHorizontal: 0, }, errorContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, errorText: { fontSize: 16, color: '#666', textAlign: 'center', }, footer: { paddingHorizontal: 30, paddingVertical: 30, alignItems: 'center', gap: 16, }, nextButton: { backgroundColor: '#6B8E5A', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', paddingVertical: 16, paddingHorizontal: 32, borderRadius: 25, minWidth: width * 0.6, shadowColor: '#000', shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 3, }, completeButton: { backgroundColor: '#2F4F2F', }, nextButtonText: { color: 'white', fontSize: 16, fontWeight: '600', }, completeButtonText: { color: 'white', }, nextIcon: { marginLeft: 8, }, slideCounter: { fontSize: 14, color: '#666', textAlign: 'center', }, paywallContainer: { flex: 1, }, }); exports.default = OnboardingModal;